commit ea0292491af7db61f60fec2f173e719887d61a9f Author: gong01 Date: Fri Mar 6 02:52:38 2026 +0800 initial commit diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..8639b64 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +indent_style = space # 탭 대신 공백 사용 (탭 문자 발생 방지) +indent_size = 4 # 공백은 4칸으로 고정 +end_of_line = lf # 줄바꿈은 무조건 LF로 통일 (리눅스 방식) +charset = utf-8 # 인코딩 통일 +trim_trailing_whitespace = true # 줄 끝의 불필요한 공백 제거 +insert_final_newline = true # 파일 끝에 빈 줄 하나 추가 \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d6b284e --- /dev/null +++ b/.gitignore @@ -0,0 +1,77 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +# --- Build outputs --- +/target/ +/build/ +/out/ + +# --- Maven --- +.mvn/wrapper/maven-wrapper.jar +.mvn/wrapper/maven-wrapper.properties +.settings/ + +# --- Gradle --- +.gradle/ +/gradle/ +/gradlew +gradlew.bat +!gradle/wrapper/gradle-wrapper.jar + +# --- Logs --- +*.log +logs/ +log/ + +# --- Spring Boot --- +*.pid +*.pid.lock +*.iml + +# --- IDE (IntelliJ / Eclipse / STS / VSCode) --- +.idea/ +*.ipr +*.iws +.classpath +.project +.factorypath +.settings/ +.springBeans +.springdsl + +.vscode/ +.history/ +.remote/ + +# --- OS specific --- +.DS_Store +Thumbs.db + +# --- Temporary / cache --- +*.tmp +*.bak +*.swp +*.swo +*.orig +.cache/ +tmp/ +bin/ +generated/ + +# --- Security / credentials (예: 환경변수 파일) --- +.env +*.key +*.pem +*.p12 +# application-*.yml +# application-*.properties +# application.properties + +# --- Docker --- +/docker-compose.override.yml + +# --- API Test Tool --- +api_test_tool/ diff --git a/.mvn/wrapper/MavenWrapperDownloader.java b/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 0000000..e76d1f3 --- /dev/null +++ b/.mvn/wrapper/MavenWrapperDownloader.java @@ -0,0 +1,117 @@ +/* + * Copyright 2007-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import java.net.*; +import java.io.*; +import java.nio.channels.*; +import java.util.Properties; + +public class MavenWrapperDownloader { + + private static final String WRAPPER_VERSION = "0.5.6"; + /** + * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. + */ + private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" + + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; + + /** + * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to + * use instead of the default one. + */ + private static final String MAVEN_WRAPPER_PROPERTIES_PATH = + ".mvn/wrapper/maven-wrapper.properties"; + + /** + * Path where the maven-wrapper.jar will be saved to. + */ + private static final String MAVEN_WRAPPER_JAR_PATH = + ".mvn/wrapper/maven-wrapper.jar"; + + /** + * Name of the property which should be used to override the default download url for the wrapper. + */ + private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; + + public static void main(String args[]) { + System.out.println("- Downloader started"); + File baseDirectory = new File(args[0]); + System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); + + // If the maven-wrapper.properties exists, read it and check if it contains a custom + // wrapperUrl parameter. + File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); + String url = DEFAULT_DOWNLOAD_URL; + if(mavenWrapperPropertyFile.exists()) { + FileInputStream mavenWrapperPropertyFileInputStream = null; + try { + mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); + Properties mavenWrapperProperties = new Properties(); + mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); + url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); + } catch (IOException e) { + System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); + } finally { + try { + if(mavenWrapperPropertyFileInputStream != null) { + mavenWrapperPropertyFileInputStream.close(); + } + } catch (IOException e) { + // Ignore ... + } + } + } + System.out.println("- Downloading from: " + url); + + File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); + if(!outputFile.getParentFile().exists()) { + if(!outputFile.getParentFile().mkdirs()) { + System.out.println( + "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); + } + } + System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); + try { + downloadFileFromURL(url, outputFile); + System.out.println("Done"); + System.exit(0); + } catch (Throwable e) { + System.out.println("- Error downloading"); + e.printStackTrace(); + System.exit(1); + } + } + + private static void downloadFileFromURL(String urlString, File destination) throws Exception { + if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { + String username = System.getenv("MVNW_USERNAME"); + char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); + Authenticator.setDefault(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(username, password); + } + }); + } + URL website = new URL(urlString); + ReadableByteChannel rbc; + rbc = Channels.newChannel(website.openStream()); + FileOutputStream fos = new FileOutputStream(destination); + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); + fos.close(); + rbc.close(); + } + +} diff --git a/deploy-aws.sh b/deploy-aws.sh new file mode 100644 index 0000000..873c95f --- /dev/null +++ b/deploy-aws.sh @@ -0,0 +1,83 @@ +#!/bin/bash + +# AWS 서버 파일 업로드 스크립트 +# 사용법: ./deploy-aws.sh + +set -e + +AWS_SERVER=$1 +AWS_USER=$2 +AWS_KEY_PATH=$3 +JAR_FILE=$4 +DEPLOY_PATH=$5 + +if [ -z "$AWS_SERVER" ] || [ -z "$AWS_USER" ] || [ -z "$AWS_KEY_PATH" ] || [ -z "$JAR_FILE" ] || [ -z "$DEPLOY_PATH" ]; then + echo "사용법: $0 " + echo "예시: $0 47.129.51.216 root /path/to/key.pem target/core.jar /home/run" + exit 1 +fi + +echo "=== AWS 서버 파일 업로드 시작 ===" +echo "AWS Server: $AWS_SERVER" +echo "AWS User: $AWS_USER" +echo "JAR File: $JAR_FILE" +echo "Deploy Path: $DEPLOY_PATH" + +# JAR 파일 존재 확인 +if [ ! -f "$JAR_FILE" ]; then + echo "❌ JAR 파일을 찾을 수 없습니다: $JAR_FILE" + exit 1 +fi + +# AWS 키 파일 존재 확인 +if [ ! -f "$AWS_KEY_PATH" ]; then + echo "❌ AWS 키 파일을 찾을 수 없습니다: $AWS_KEY_PATH" + exit 1 +fi + +# AWS 서버 연결 테스트 +echo "AWS 서버 연결 테스트 중..." +ssh -i "$AWS_KEY_PATH" -o ConnectTimeout=10 -o StrictHostKeyChecking=no "$AWS_USER@$AWS_SERVER" "echo 'AWS 서버 연결 성공'" + +if [ $? -ne 0 ]; then + echo "❌ AWS 서버 연결 실패" + exit 1 +fi + +# AWS 서버에서 배포 디렉토리 생성 및 권한 설정 (root 권한으로) +echo "AWS 서버에서 배포 디렉토리 생성 중... (root 권한)" +ssh -i "$AWS_KEY_PATH" "$AWS_USER@$AWS_SERVER" "sudo su - root <<'ROOT_SETUP' + # 배포 디렉토리 및 로그 디렉토리 생성 + mkdir -p $DEPLOY_PATH/logs + chmod -R 755 $DEPLOY_PATH + echo '배포 디렉토리 생성 완료: $DEPLOY_PATH' +ROOT_SETUP +" + +# JAR 파일 이름 추출 +JAR_FILENAME=$(basename "$JAR_FILE") + +# JAR 파일을 AWS 서버로 전송 +echo "JAR 파일을 AWS 서버로 전송 중..." +scp -i "$AWS_KEY_PATH" "$JAR_FILE" "$AWS_USER@$AWS_SERVER:$DEPLOY_PATH/$JAR_FILENAME" + +# JAR 파일 권한 설정 (root가 읽을 수 있도록) +echo "JAR 파일 권한 설정 중... (root 권한)" +ssh -i "$AWS_KEY_PATH" "$AWS_USER@$AWS_SERVER" "sudo su - root <<'ROOT_CHMOD' + chmod 644 $DEPLOY_PATH/$JAR_FILENAME + echo 'JAR 파일 권한 설정 완료' + echo '업로드된 파일: $DEPLOY_PATH/$JAR_FILENAME' + ls -lh $DEPLOY_PATH/$JAR_FILENAME +ROOT_CHMOD +" + +if [ $? -eq 0 ]; then + echo "✅ AWS 서버 파일 업로드 성공!" + echo "JAR 파일이 $DEPLOY_PATH/$JAR_FILENAME 에 업로드되었습니다." +else + echo "❌ AWS 서버 파일 업로드 실패!" + exit 1 +fi + +echo "=== AWS 서버 파일 업로드 완료 ===" + diff --git a/deploy-aws2.sh b/deploy-aws2.sh new file mode 100644 index 0000000..72d6d24 --- /dev/null +++ b/deploy-aws2.sh @@ -0,0 +1,96 @@ +#!/bin/bash + +# AWS 서버 파일 업로드 스크립트 +# 사용법: ./deploy-aws.sh + +set -e + +AWS_SERVER=$1 +AWS_USER=$2 +AWS_KEY_PATH=$3 +JAR_FILE=$4 +DEPLOY_PATH=$5 + +if [ -z "$AWS_SERVER" ] || [ -z "$AWS_USER" ] || [ -z "$AWS_KEY_PATH" ] || [ -z "$JAR_FILE" ] || [ -z "$DEPLOY_PATH" ]; then + echo "사용법: $0 " + echo "예시: $0 47.129.51.216 root /path/to/key.pem target/core.jar /home/run" + exit 1 +fi + +echo "=== AWS 서버 파일 업로드 시작 ===" +echo "AWS Server: $AWS_SERVER" +echo "AWS User: $AWS_USER" +echo "JAR File: $JAR_FILE" +echo "Deploy Path: $DEPLOY_PATH" + +# JAR 파일 존재 확인 +if [ ! -f "$JAR_FILE" ]; then + echo "❌ JAR 파일을 찾을 수 없습니다: $JAR_FILE" + exit 1 +fi + +# AWS 키 파일 존재 확인 +if [ ! -f "$AWS_KEY_PATH" ]; then + echo "❌ AWS 키 파일을 찾을 수 없습니다: $AWS_KEY_PATH" + exit 1 +fi + +# AWS 서버 연결 테스트 +echo "AWS 서버 연결 테스트 중..." +ssh -i "$AWS_KEY_PATH" -o ConnectTimeout=10 -o StrictHostKeyChecking=no "$AWS_USER@$AWS_SERVER" "echo 'AWS 서버 연결 성공'" + +if [ $? -ne 0 ]; then + echo "❌ AWS 서버 연결 실패" + exit 1 +fi + +# AWS 서버에서 배포 디렉토리 생성 및 권한 설정 (root 권한으로) +echo "AWS 서버에서 배포 디렉토리 생성 중... (root 권한)" +ssh -i "$AWS_KEY_PATH" "$AWS_USER@$AWS_SERVER" "sudo su - root < \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 0000000..c8d4337 --- /dev/null +++ b/mvnw.cmd @@ -0,0 +1,182 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM https://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + +FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/pom-real.xml b/pom-real.xml new file mode 100644 index 0000000..3188ec5 --- /dev/null +++ b/pom-real.xml @@ -0,0 +1,217 @@ + + + 4.0.0 + + + org.springframework.boot + spring-boot-starter-parent + 3.0.0 + + + com.example + apiServer + 0.0.1-SNAPSHOT + apiServer + Demo project for Spring Boot + + real + 17 + 2.0.2 + 0.11.5 + 3.0.0 + 1.18.30 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-validation + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-websocket + + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + nz.net.ultraq.thymeleaf + thymeleaf-layout-dialect + + + + org.springframework.boot + spring-boot-starter-jdbc + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + ${mybatis.version} + + + com.mysql + mysql-connector-j + runtime + + + org.mariadb.jdbc + mariadb-java-client + runtime + + + + org.codehaus.jettison + jettison + 1.5.4 + + + com.google.code.gson + gson + + + org.json + json + 20230227 + + + net.sf.json-lib + json-lib + 2.4 + jdk15 + + + + io.jsonwebtoken + jjwt-api + ${jjwt.version} + + + io.jsonwebtoken + jjwt-impl + ${jjwt.version} + runtime + + + io.jsonwebtoken + jjwt-jackson + ${jjwt.version} + runtime + + + + org.springdoc + springdoc-openapi-starter-webmvc-ui + ${springdoc.version} + + + + org.projectlombok + lombok + ${lombok.version} + true + + + org.jsoup + jsoup + 1.15.3 + + + org.apache.httpcomponents.client5 + httpclient5 + + + com.squareup.okhttp3 + okhttp + 4.10.0 + + + + jakarta.xml.bind + jakarta.xml.bind-api + + + com.sun.xml.bind + jaxb-impl + 4.0.0 + runtime + + + com.warrenstrange + googleauth + 1.5.0 + + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.springframework.boot + spring-boot-starter-batch + + + org.springframework.boot + spring-boot-starter-webflux + + + org.springdoc + springdoc-openapi-starter-webmvc-api + 2.0.2 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.10.1 + + 17 + 17 + + + org.projectlombok + lombok + ${lombok.version} + + + org.springframework.boot + spring-boot-configuration-processor + 3.0.0 + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..dff7241 --- /dev/null +++ b/pom.xml @@ -0,0 +1,222 @@ + + + 4.0.0 + + + org.springframework.boot + spring-boot-starter-parent + 3.0.0 + + + com.example + apiServer + 0.0.1-SNAPSHOT + apiServer + Demo project for Spring Boot + + + 17 + 2.0.2 + 0.11.5 + 3.0.0 + 1.18.30 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-validation + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-websocket + + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + nz.net.ultraq.thymeleaf + thymeleaf-layout-dialect + + + + org.springframework.boot + spring-boot-starter-jdbc + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + ${mybatis.version} + + + com.mysql + mysql-connector-j + runtime + + + org.mariadb.jdbc + mariadb-java-client + runtime + + + + org.codehaus.jettison + jettison + 1.5.4 + + + com.google.code.gson + gson + + + org.json + json + 20230227 + + + net.sf.json-lib + json-lib + 2.4 + jdk15 + + + + io.jsonwebtoken + jjwt-api + ${jjwt.version} + + + io.jsonwebtoken + jjwt-impl + ${jjwt.version} + runtime + + + io.jsonwebtoken + jjwt-jackson + ${jjwt.version} + runtime + + + + com.fasterxml.jackson.core + jackson-databind + + + + org.springdoc + springdoc-openapi-starter-webmvc-ui + ${springdoc.version} + + + + org.projectlombok + lombok + ${lombok.version} + true + + + org.jsoup + jsoup + 1.15.3 + + + org.apache.httpcomponents.client5 + httpclient5 + + + com.squareup.okhttp3 + okhttp + 4.10.0 + + + + jakarta.xml.bind + jakarta.xml.bind-api + + + com.sun.xml.bind + jaxb-impl + 4.0.0 + runtime + + + com.warrenstrange + googleauth + 1.5.0 + + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.springframework.boot + spring-boot-starter-batch + + + org.springframework.boot + spring-boot-starter-webflux + + + org.springdoc + springdoc-openapi-starter-webmvc-api + 2.0.2 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.10.1 + + 17 + 17 + + + org.projectlombok + lombok + ${lombok.version} + + + org.springframework.boot + spring-boot-configuration-processor + 3.0.0 + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + + \ No newline at end of file diff --git a/runApi.sh b/runApi.sh new file mode 100644 index 0000000..3adc8eb --- /dev/null +++ b/runApi.sh @@ -0,0 +1,108 @@ +#!/bin/bash + +# API 서버 배포 및 실행 스크립트 +# 사용법: sudo ./runApi.sh +# 필요한 경로/파일이 다를 경우 아래 변수만 수정하세요. + +set -euo pipefail + +JAR_NAME="${JAR_NAME:-apiServer-0.0.1-SNAPSHOT.jar}" +PID_FILE="${PID_FILE:-/home/api.pid}" +RUN_DIR="${RUN_DIR:-/home/run}" +BUILD_DIR="${BUILD_DIR:-/home/build}" +BACKUP_DIR="${BACKUP_DIR:-/home/backup}" +JAVA_BIN="${JAVA_BIN:-/home/openjdk17/bin/java}" +# SCOUTER_AGENT="${SCOUTER_AGENT:-/home/scouter/agent.java/scouter.agent.jar}" +# SCOUTER_CONF="${SCOUTER_CONF:-/home/scouter/agent.java/conf/scouter.conf}" +SPRING_PROFILE="${SPRING_PROFILE:-real}" + +timestamp() { + date +"%Y%m%d_%H%M%S" +} + +log() { + echo "[runApi] $*" +} + +ensure_paths() { + mkdir -p "$RUN_DIR" "$BACKUP_DIR" "$BUILD_DIR" +} + +stop_app() { + if [[ -f "$PID_FILE" ]]; then + local pid + pid=$(cat "$PID_FILE" 2>/dev/null || true) + if [[ -n "${pid:-}" ]] && ps -p "$pid" > /dev/null 2>&1; then + log "기존 프로세스 종료: $pid" + kill -9 "$pid" || true + else + log "PID 파일은 있으나 실행 중인 프로세스가 없습니다." + fi + rm -f "$PID_FILE" + else + log "종료할 PID 파일이 없습니다." + fi +} + +backup_old() { + local current="$RUN_DIR/$JAR_NAME" + if [[ -f "$current" ]]; then + local backup="$BACKUP_DIR/oldApi_$(timestamp).jar" + log "기존 JAR 백업 -> $backup" + mv "$current" "$backup" + else + log "백업할 기존 JAR이 없습니다." + fi +} + +copy_new() { + local source="$BUILD_DIR/$JAR_NAME" + local target="$RUN_DIR/$JAR_NAME" + + # 소스와 타겟이 같으면 복사 불필요 + if [[ "$source" == "$target" ]]; then + if [[ -f "$target" ]]; then + log "배포된 JAR 확인 -> $target" + return 0 + else + log "새 JAR을 찾을 수 없습니다: $target" + exit 1 + fi + fi + + if [[ ! -f "$source" ]]; then + log "새 JAR을 찾을 수 없습니다: $source" + exit 1 + fi + + log "새 JAR 복사 -> $target" + cp "$source" "$target" +} + +start_app() { + local target="$RUN_DIR/$JAR_NAME" + log "애플리케이션 시작" + local log_dir="${LOG_DIR:-/home/log/core}" + local log_file="${LOG_FILE:-$log_dir/apiServer.log}" + mkdir -p "$log_dir" + + nohup "$JAVA_BIN" \ + -Duser.timezone=GMT+09:00 \ + -Dspring.profiles.active="$SPRING_PROFILE" \ + -jar "$target" \ + >> "$log_file" 2>&1 & + echo $! > "$PID_FILE" + log "시작 완료 (PID: $(cat "$PID_FILE"))" +} + +main() { + ensure_paths + stop_app + backup_old + copy_new + start_app + log "배포 완료" +} + +main "$@" + diff --git a/src/main/java/com/bb/ApiServerApplication.java b/src/main/java/com/bb/ApiServerApplication.java new file mode 100644 index 0000000..f186b75 --- /dev/null +++ b/src/main/java/com/bb/ApiServerApplication.java @@ -0,0 +1,15 @@ +package com.bb; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableAsync; + +@EnableAsync +@SpringBootApplication +public class ApiServerApplication { + + public static void main(String[] args) { + SpringApplication.run(ApiServerApplication.class, args); + } + +} diff --git a/src/main/java/com/bb/admin/controller/AgentController.java b/src/main/java/com/bb/admin/controller/AgentController.java new file mode 100644 index 0000000..6f67eab --- /dev/null +++ b/src/main/java/com/bb/admin/controller/AgentController.java @@ -0,0 +1,671 @@ +package com.bb.admin.controller; + +import java.util.HashMap; +import java.util.List; +import java.util.Random; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.reactive.function.client.WebClient; + +import com.bb.model.CommonParamAdmin; +import com.bb.model.PageFormVO; +import com.bb.model.Site; +import com.bb.model.SiteSearch; +import com.bb.model.Vendor; +import com.bb.service.CreditService; +import com.bb.service.SiteService; +import com.bb.util.PagingUtil; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import net.sf.json.JSONObject; + + + +@Slf4j +@Controller +@RequestMapping(value = "/agent") +@PreAuthorize("hasRole('ADMIN')") +public class AgentController { + + @Autowired + SiteService siteService; + + @Autowired + CreditService creditService; + + @Autowired + private WebClient webClient; // 싱글톤 WebClient 주입 + /* + * + * TPA 에이전트 목록 페이지 수정사항 + 1. 에이전트 -> "에이전시" 로 용어수정 + 2. 에이전시 목록 수정사항 : + - 단계 = 레벨. + - 번호 : 생성 순번 (컬럼 맨 앞으로) + - 분류 : 두가지 타입 (추후 추가될수있음) NA(Normal Agency), IA(Insure Agency) + NA, IA + - 타입 : Ota (Operator Agency) : 솔루션 운영하는 에이전시, Ppa (Paper Agency) : 하위 총판만 운영하는 에이전시 + 3. 검색옵션 추가 : 분류, 타입 각각 따로 검색 가능하도록 분리 + 4. 데이터 적용안되어 있는부분 적용 : 요율, 총 지급받은 금액 등 + 요율 : 기준요율만 적시 (벤더별 요율은 상세페이지에서 표시됨) + 5. 소속 에이전트 삭제(어차피 내 소속임) 에이전트 아이디 클릭시 상세페이지 이동 + 6. 가입시각 -> 가입일시로 수정 , 가운데 "T" "%"문자 제거. + 7. 관리 컬럼은 유지 타이틀 이름도 관리 유자, 내용 관리 글자 제거. + "정지"버튼 추가(클릭시 모든기능정지) "블랙"버튼 추가 (클릭시 로그인 및 PT충환전 중지) + 위 기능 구현하도록 작업 + */ + + + @GetMapping("") + public String list( HttpServletRequest request , ModelMap model, @ModelAttribute("searchVO") SiteSearch search) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + + log.info("underSiteCredit" + underSiteCredit); + + model.put("siteCredit", siteCredit); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + model.put("underSiteCredit", underSiteCredit); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + PageFormVO pageVo= new PageFormVO(); + + if(loginSite.getSiteLevel() >0) { + search.setUpperSiteId(loginSite.getSiteId()); + } + + int totalCount = siteService.getSiteListCnt(search); + if (totalCount != 0) { + PageFormVO commonForm = new PageFormVO(); + commonForm.setFunction_name("goPage"); + commonForm.setPage(search.getPage()); + commonForm.setCount_per_page(20); + if(search.getCount_per_list()==0) { + commonForm.setCount_per_list(10); + } else { + commonForm.setCount_per_list(search.getCount_per_list()); + } + commonForm.setTatal_list_count(totalCount); + pageVo = PagingUtil.setPageUtil(commonForm); + search.setLimit(pageVo.getLimit()); + search.setOffset(pageVo.getOffset()); + search.setTatal_list_count(totalCount); + + model.put("pageInfo", pageVo.getPagination()); + } + + List siteList = siteService.getSiteList(search); + model.put("siteList", siteList); + + return "admin/agent"; + } + + + @GetMapping("/detail/{siteIdx}") + public String detail( HttpServletRequest request , ModelMap model, @ModelAttribute("searchVO") SiteSearch search) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + + log.info("#-Agent::DETAIL::underSiteCredit" + underSiteCredit); + + model.put("siteCredit", siteCredit); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + model.put("underSiteCredit", underSiteCredit); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + log.info("#-Agent::DETAIL::siteIdx {}" , search.getSiteIdx()); + if(loginSite.getSiteLevel() >0) { + search.setUpperSiteId(""+loginSite.getSiteId()); + } + Site targetSite = siteService.getSiteDetail(search); + model.put("targetSite", targetSite); + + model.put("uppersiteIdx", loginSite.getSiteIdx()); + + List vederRateList = siteService.getVenderRateList(targetSite); + model.put("vederRateList", vederRateList); + log.info("#-Agent::DETAIL::vederRateList {}", vederRateList.size()); + log.info("#-Agent::DETAIL::vederRateList {}", vederRateList); + + /* + HashMap vendorParam = new HashMap<>(); + vendorParam.put("siteIdx", search.getSiteIdx()); + vendorParam.put("vendor", "nexus"); + HashMap nexusInfo = siteService.getSiteOnlyVendorInfo(vendorParam); + log.info("#-Agent::DETAIL::nexusInfo::"+nexusInfo); + model.put("nexusInfo", nexusInfo); + + vendorParam.put("vendor", "xtreem"); + HashMap xtreemInfo = siteService.getSiteOnlyVendorInfo(vendorParam); + log.info("#-Agent::DETAIL::xtreemInfo::"+xtreemInfo); + model.put("xtreemInfo", xtreemInfo); + */ + + HashMap parsEvoInfo = siteService.getParseUseYn(targetSite.getSiteIdx()); + int parsEvoAmount = (int) parsEvoInfo.get("parsEvoAmount"); + model.put("parsEvoAmount", parsEvoAmount); + + List mylist = siteService.getSiteVendorList2(targetSite.getSiteIdx()); + List vendorlist = siteService.getVendorList2(targetSite.getSiteIdx()); + model.put("mylist", mylist); + log.info("#-Agent::DETAIL::mylist::"+mylist); + model.put("vendorlist", vendorlist); + log.info("#-Agent::DETAIL::vendorlist::"+vendorlist); + + HashMap creditInfo = siteService.getSiteSubCredit(targetSite.getSiteId()); + model.put("subCreditInfo", creditInfo); + + return "admin/popup"; + } + + @RequestMapping("/saveSvcr") + public @ResponseBody JSONObject saveSvcr(HttpServletRequest request, ModelMap model, CommonParamAdmin commonParamAdmin) throws Exception { + final String LOG_PREFIX = "#-SAVE_SCVR:::"; + log.info(LOG_PREFIX + "CommonParamAdmin: " + commonParamAdmin.toString()); + + JSONObject obj = new JSONObject(); + ObjectMapper mapper = new ObjectMapper(); + HashMap paramMap = mapper.readValue(commonParamAdmin.getParam().toString(), new TypeReference() {}); + + if(paramMap.get("vendorIdx") != null) { + SiteSearch targetSearch = new SiteSearch(); + long targetSiteIdx = Long.parseLong(commonParamAdmin.getParam().get("targetSiteIdx").toString()); + targetSearch.setSiteIdx(targetSiteIdx); + Site targetSite = siteService.getSiteDetail(targetSearch); + + String siteUrl = targetSite.getSiteCbUrl() + "/gameRateChange"; + paramMap.put("siteIdx", targetSiteIdx); + + if(Integer.parseInt(paramMap.get("type").toString()) == 0) { + siteService.saveVendorRate(paramMap); + } + siteService.saveSvcr(paramMap, Integer.parseInt(paramMap.get("type").toString())); + + // 외부 API 호출 (WebClient 방식) + if(Integer.parseInt(paramMap.get("type").toString()) == 0) { + sendGameRateChange(siteUrl, paramMap); + } + + if(targetSite.getSiteLevel() < 1) { + siteService.updateVendorUseYn(paramMap); + } + } + obj.put("RES", "SUCCESS"); + return obj; + } + +@RequestMapping("/saveSvcrAll") + public @ResponseBody JSONObject saveSvcrAll(HttpServletRequest request, ModelMap model, CommonParamAdmin commonParamAdmin) throws Exception { + final String LOG_PREFIX = "#-SAVE_SCVRALL:::"; + log.info(LOG_PREFIX + "CommonParamAdmin: " + commonParamAdmin.toString()); + + JSONObject obj = new JSONObject(); + + for(int i=0; i < commonParamAdmin.getParamlist().length; i++) { + JSONObject paramData = commonParamAdmin.getParamlist()[i]; + paramData.put("siteIdx", commonParamAdmin.getParam().get("targetSiteIdx")); + ObjectMapper mapper = new ObjectMapper(); + HashMap paramMap = mapper.readValue(paramData.toString(), new TypeReference() {}); + + long targetSiteIdx = Long.parseLong(commonParamAdmin.getParam().get("targetSiteIdx").toString()); + SiteSearch targetSearch = new SiteSearch(); + targetSearch.setSiteIdx(targetSiteIdx); + Site targetSite = siteService.getSiteDetail(targetSearch); + String siteUrl = targetSite.getSiteCbUrl() + "/gameRateChange"; + + if(paramMap.get("vendorIdx") != null) { + paramMap.put("siteIdx", targetSiteIdx); + if(Integer.parseInt(paramMap.get("type").toString()) == 0) { + siteService.saveVendorRate(paramMap); + } + siteService.saveSvcr(paramMap, Integer.parseInt(paramMap.get("type").toString())); + + // 외부 API 호출 (WebClient 방식) + if(Integer.parseInt(paramMap.get("type").toString()) == 0) { + sendGameRateChange(siteUrl, paramMap); + } + + if(targetSite.getSiteLevel() < 1) { + siteService.updateVendorUseYn(paramMap); + } + } + } + obj.put("RES", "SUCCESS"); + return obj; + } + + /** + * WebClient를 이용한 외부 API 호출 공통 메서드 (동기 방식) + */ + private void sendGameRateChange(String url, HashMap paramMap) { + try { + log.info("##### WebClient gmeRateChange 시작 #####"); + + JSONObject paramBody = new JSONObject(); + paramBody.put("siteApiKey", siteService.getSiteKey(paramMap)); + paramBody.put("vendor", siteService.getVendorTitle(paramMap)); + paramBody.put("vendorIdx", paramMap.get("vendorIdx")); + paramBody.put("gameRate", Double.parseDouble(paramMap.get("rate").toString())); + + String response = webClient.post() + .uri(url) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .header("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36") + .bodyValue(paramBody.toString()) + .retrieve() + .bodyToMono(String.class) + .block(); // MVC 환경이므로 결과를 기다림(동기) + + log.info("##### WebClient 응답 완료 : {}", response); + } catch (Exception e) { + log.error("##### WebClient 호출 에러 : {}", e.getMessage()); + } + } + + @GetMapping("/add") + public String add( HttpServletRequest request , ModelMap model, @ModelAttribute("searchVO") SiteSearch search) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + + log.info("underSiteCredit" + underSiteCredit); + + model.put("siteCredit", siteCredit); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + model.put("underSiteCredit", underSiteCredit); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + return "admin/agentAdd"; + } + + + @RequestMapping("/siteUpdate") + public @ResponseBody JSONObject siteUpdate( HttpServletRequest request, ModelMap model, Site site) throws Exception { + JSONObject obj = new JSONObject(); + + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + site.setUpperSiteId(loginSite.getSiteId()); + site.setUpperSiteIdx(loginSite.getSiteIdx()); + final String LOG_PREFIX = "#-super::siteUpdate:::"; + + log.info(LOG_PREFIX+ "Site Info: " + site.toString()); + log.info(LOG_PREFIX+ "Site IP: " + site.getSiteIp()); + siteService.siteUpdate(LOG_PREFIX, site); + + obj.put("RES", "SUCCESS"); + + return obj; + } + + @RequestMapping("/agentUpdate") + public @ResponseBody JSONObject agentUpdate( HttpServletRequest request, ModelMap model, Site site) throws Exception { + JSONObject obj = new JSONObject(); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + // site.setSiteId(loginSite.getSiteId()); + final String LOG_PREFIX = "#-super::agentUpdate:::"; + + if("new".equals(site.getSiteKey())) { + String newsiteKey = makeApiKey(loginSite.getSiteId()); + site.setSiteKey(newsiteKey); + obj.put("DATA", newsiteKey); + } + + log.info(LOG_PREFIX+ "Site Info: " + site.toString()); + log.info(LOG_PREFIX+ "Site IP: " + site.getSiteIp()); + siteService.siteUpdate(LOG_PREFIX, site); + obj.put("RES", "SUCCESS"); + + return obj; + } + + @RequestMapping("/agentIpsUpdate") + public @ResponseBody JSONObject agentIpsUpdate( HttpServletRequest request, ModelMap model, Site site) throws Exception { + JSONObject obj = new JSONObject(); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + // site.setSiteId(loginSite.getSiteId()); + + + siteService.agentIpsUpdate(site) ; + + + obj.put("RES", "SUCCESS"); + + + return obj; + } + + @RequestMapping("/forDefault") + public @ResponseBody JSONObject forDefault(HttpServletRequest request, ModelMap model, SiteSearch search) throws Exception { + JSONObject obj = new JSONObject(); + + //Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + //Site site = (Site) authentication.getDetails(); + + Site site = siteService.getSiteDetail(search); + final String LOG_PREFIX = "#-Proc::forDefault::"+site.getSiteIdx()+"::"; + log.info(LOG_PREFIX + "loginSite::" + site.toString()); + log.info(LOG_PREFIX+ "Site IP: " + site.getSiteIp()); + + siteService.siteUpdate(LOG_PREFIX, site); + siteService.forDefaultProc(site); + + obj.put("RES", "SUCCESS"); + + return obj; + } + + @RequestMapping("/saveParsEvoAmount") + public @ResponseBody JSONObject saveParsEvoAmount(HttpServletRequest request, ModelMap model, SiteSearch param) throws Exception { + JSONObject obj = new JSONObject(); + final String LOG_PREFIX = "#-Proc::saveParsEvoAmount::"+param.getSiteIdx()+"::"; + log.info(LOG_PREFIX + "ParsEvoAmount::" + param.getParsEvoAmount()); + + int updResult = siteService.saveParsEvoAmount(param); + + obj.put("RES", "SUCCESS"); + + return obj; + } + + @RequestMapping("/creditRateSave") + public @ResponseBody JSONObject setSave( HttpServletRequest request, ModelMap model, CommonParamAdmin commonParamAdmin ) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + + Site loginSite = (Site)authentication.getDetails(); + + JSONObject obj = new JSONObject(); + log.info(commonParamAdmin.toString()); + + for(int i=0;i() {}); + if(paramMap.get("vendorIdx")!=null) { + siteService.saveVendorRate(paramMap); + siteService.updateVendorUseYn(paramMap); + } + } + + obj.put("RES", "SUCCESS"); + + return obj; + } + + + @RequestMapping("/insurePoinRateSave") + public @ResponseBody JSONObject insurePointRateSave( HttpServletRequest request, ModelMap model, CommonParamAdmin commonParamAdmin ) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + + Site loginSite = (Site)authentication.getDetails(); + + JSONObject obj = new JSONObject(); + log.info(commonParamAdmin.toString()); + + for(int i=0;i() {}); + siteService.saveVendorInsurePointRate(paramMap); + } + + obj.put("RES", "SUCCESS"); + + return obj; + } + + + @RequestMapping("/addProc") + public @ResponseBody JSONObject addProc( HttpServletRequest request, ModelMap model, Site site) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + + Site loginSite = (Site)authentication.getDetails(); + site.setUpperSiteId(loginSite.getSiteId()); + site.setUpperSiteIdx(loginSite.getSiteIdx()); + site.setSiteKey(makeApiKey(site.getSiteId())); + JSONObject obj = new JSONObject(); + + if(site.getIsTransfer() == null || "".equals(site.getIsTransfer())) { + site.setIsTransfer("N"); + } + + log.info(site.toString()); + + siteService.addProc(site); + obj.put("RES", "SUCCESS"); + + return obj; + } + + + @GetMapping("/transaction") + public String transaction( HttpServletRequest request , ModelMap model , @ModelAttribute("searchVO") SiteSearch search) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + + model.put("sitePoint", sitePoint); + model.put("siteCredit", siteCredit); + model.put("underSiteCredit", underSiteCredit); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + + model.put("creditWait", creditWait); + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + PageFormVO pageVo= new PageFormVO(); + search.setSiteId(loginSite.getSiteId()); + search.setSiteIdx(loginSite.getSiteIdx()); + + int totalCount = creditService.getSiteTranListCnt(search); + if(totalCount != 0) { + PageFormVO commonForm = new PageFormVO(); + commonForm.setFunction_name("goPage"); + commonForm.setPage(search.getPage()); + commonForm.setCount_per_page(20); + if(search.getCount_per_list()==0) { + commonForm.setCount_per_list(15); + } else { + commonForm.setCount_per_list(search.getCount_per_list()); + } + commonForm.setTatal_list_count(totalCount); + pageVo = PagingUtil.setPageUtil(commonForm); + search.setLimit(pageVo.getLimit()); + search.setOffset(pageVo.getOffset()); + search.setTatal_list_count(totalCount); + model.put("pageInfo", pageVo.getPagination()); + } + + List list = creditService.getSiteTranList(search); + log.debug(""+list.size()); + model.put("list", list); + + return "admin/transaction"; + } + + + @GetMapping("/gamelink") + public String gamelink( HttpServletRequest request , ModelMap model, @ModelAttribute("searchVO") SiteSearch search) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + + model.put("sitePoint", sitePoint); + model.put("siteCredit", siteCredit); + model.put("underSiteCredit", underSiteCredit); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + + model.put("creditWait", creditWait); + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + search.setSiteIdx(loginSite.getSiteIdx()); + + List mylist = siteService.getSiteVendorList(search); + List vendorlist = siteService.getVendorList(search); + + model.put("mylist", mylist); + model.put("vendorlist", vendorlist); + + return "admin/gamelink"; + } + + @GetMapping("/venderlist") + public String venderlist( HttpServletRequest request, ModelMap model, @ModelAttribute("searchVO") SiteSearch search) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + + search.setSiteIdx(loginSite.getSiteIdx()); + + return "admin/venderlist"; + } + + @GetMapping("/apiset") + public String apiset( HttpServletRequest request , ModelMap model, @ModelAttribute("searchVO") SiteSearch search) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + + model.put("sitePoint", sitePoint); + model.put("siteCredit", siteCredit); + model.put("underSiteCredit", underSiteCredit); + + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + search.setSiteIdx(loginSite.getSiteIdx()); + + return "admin/apiset"; + } + + + @RequestMapping("/siteVenderUpdate") + public @ResponseBody JSONObject siteVenderUpdate( HttpServletRequest request, ModelMap model, Vendor vendor) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + JSONObject obj = new JSONObject(); + + vendor.setSiteIdx(loginSite.getSiteIdx()); + try { + siteService.siteVenderUpdate(vendor); + obj.put("RES", "SUCCESS"); + } catch(Exception e) { + obj.put("RES", "FAIL"); + } + + return obj; + } + + + @GetMapping("/parseOnOff") + public @ResponseBody JSONObject parseOnOff(HttpServletRequest request, ModelMap model, @RequestParam("pStatus") String pStatus) throws Exception { + JSONObject obj = new JSONObject(); + + final String LOG_PREFIX = "#-Proc::parseOnOff:::"; + + log.info(LOG_PREFIX + "전체 사이트 파싱설정::" + pStatus + "::START"); + + String useYn = ""; + if("on".equals(pStatus)) { + useYn = "Y"; + } else { + useYn = "N"; + } + log.info(LOG_PREFIX + "updateParseUseYN useYn::" + useYn); + int result = siteService.updateParseUseYN(useYn); + log.info(LOG_PREFIX + "updateParseUseYN result::" + result); + + log.info(LOG_PREFIX + "전체 사이트 파싱설정::" + pStatus + "::END"); + + obj.put("RES", "SUCCESS"); + + return obj; + } + + + private String makeApiKey(String param) { + int n = 24; // n자리 쿠폰 + char[] chs = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' ,'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; + + Random rd = new Random(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < n; i++) { + char ch = chs[rd.nextInt(chs.length)]; + sb.append(ch); + } + + return sb.toString(); + } +} diff --git a/src/main/java/com/bb/admin/controller/CreditController.java b/src/main/java/com/bb/admin/controller/CreditController.java new file mode 100644 index 0000000..6b23135 --- /dev/null +++ b/src/main/java/com/bb/admin/controller/CreditController.java @@ -0,0 +1,559 @@ +package com.bb.admin.controller; + +import java.util.HashMap; +import java.util.List; + +import jakarta.servlet.http.HttpServletRequest; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.annotation.Secured; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import com.bb.model.Credit; +import com.bb.model.CreditPoint; +import com.bb.model.OTPInfo; +import com.bb.model.PageFormVO; +import com.bb.model.Site; +import com.bb.model.SiteSearch; +import com.bb.service.CreditService; +import com.bb.service.SiteService; +import com.bb.util.PagingUtil; +import com.bb.util.TOTPTokenGenerator; + +import lombok.extern.slf4j.Slf4j; +import net.sf.json.JSONObject; + +@Slf4j +@Controller +@RequestMapping(value = "/cash") +@PreAuthorize("hasRole('ADMIN')") +public class CreditController { + + @Autowired + SiteService siteService; + + @Autowired + CreditService creditService; + + @GetMapping("/charge") + public String charge(HttpServletRequest request, ModelMap model, @ModelAttribute("searchVO") SiteSearch search) + throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site) authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + log.info("underSiteCredit" + underSiteCredit); + model.put("siteCredit", siteCredit); + model.put("underSiteCredit", underSiteCredit); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + PageFormVO pageVo = new PageFormVO(); + search.setSiteId(loginSite.getSiteId()); + search.setSiteIdx(loginSite.getSiteIdx()); + search.setCreditType("CI"); + + int totalCount = creditService.getCreditListCnt(search); + if (totalCount != 0) { + PageFormVO commonForm = new PageFormVO(); + commonForm.setFunction_name("goPage"); + commonForm.setPage(search.getPage()); + commonForm.setCount_per_page(20); + if (search.getCount_per_list() == 0) { + commonForm.setCount_per_list(10); + } else { + commonForm.setCount_per_list(search.getCount_per_list()); + } + commonForm.setTatal_list_count(totalCount); + pageVo = PagingUtil.setPageUtil(commonForm); + search.setLimit(pageVo.getLimit()); + search.setOffset(pageVo.getOffset()); + search.setTatal_list_count(totalCount); + + model.put("pageInfo", pageVo.getPagination()); + } + + HashMap sum = creditService.getCreditSumToday(search); + model.put("sum", sum); + + List list = creditService.getCreditList(search); + log.info("list" + list.size()); + model.put("list", list); + + return "admin/charge"; + } + + @GetMapping("/chargeWait") + public String chargeWait(HttpServletRequest request, ModelMap model, @ModelAttribute("searchVO") SiteSearch search) + throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site) authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + log.info("underSiteCredit" + underSiteCredit); + model.put("siteCredit", siteCredit); + model.put("underSiteCredit", underSiteCredit); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + PageFormVO pageVo = new PageFormVO(); + search.setSiteId(loginSite.getSiteId()); + search.setSiteIdx(loginSite.getSiteIdx()); + search.setCreditType("CI"); + search.setCreditStatus(request.getParameter("creditStatus")); + log.info(search.getCreditStatus()); + + int totalCount = creditService.getCreditListCnt(search); + if (totalCount != 0) { + PageFormVO commonForm = new PageFormVO(); + commonForm.setFunction_name("goPage"); + commonForm.setPage(search.getPage()); + commonForm.setCount_per_page(20); + if (search.getCount_per_list() == 0) { + commonForm.setCount_per_list(10); + } else { + commonForm.setCount_per_list(search.getCount_per_list()); + } + commonForm.setTatal_list_count(totalCount); + pageVo = PagingUtil.setPageUtil(commonForm); + search.setLimit(pageVo.getLimit()); + search.setOffset(pageVo.getOffset()); + search.setTatal_list_count(totalCount); + + model.put("pageInfo", pageVo.getPagination()); + } + + log.info(search.getCreditStatus()); + List list = creditService.getCreditList(search); + log.info("" + list.size()); + model.put("list", list); + + return "admin/apply"; + } + + @GetMapping("/exchange") + public String exchange(HttpServletRequest request, ModelMap model, @ModelAttribute("searchVO") SiteSearch search) + throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site) authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + log.info("underSiteCredit" + underSiteCredit); + model.put("siteCredit", siteCredit); + model.put("underSiteCredit", underSiteCredit); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + PageFormVO pageVo = new PageFormVO(); + search.setSiteId(loginSite.getSiteId()); + search.setSiteIdx(loginSite.getSiteIdx()); + search.setCreditType("CO"); + search.setCreditStatus(request.getParameter("creditStatus")); + log.info(search.getCreditStatus()); + + int totalCount = creditService.getCreditListCnt(search); + if (totalCount != 0) { + PageFormVO commonForm = new PageFormVO(); + commonForm.setFunction_name("goPage"); + commonForm.setPage(search.getPage()); + commonForm.setCount_per_page(20); + if (search.getCount_per_list() == 0) { + commonForm.setCount_per_list(10); + } else { + commonForm.setCount_per_list(search.getCount_per_list()); + } + commonForm.setTatal_list_count(totalCount); + pageVo = PagingUtil.setPageUtil(commonForm); + search.setLimit(pageVo.getLimit()); + search.setOffset(pageVo.getOffset()); + search.setTatal_list_count(totalCount); + + model.put("pageInfo", pageVo.getPagination()); + } + + List list = creditService.getCreditList(search); + model.put("list", list); + + return "admin/exchange"; + } + + @GetMapping("/exchangeWait") + public String exchangeWait(HttpServletRequest request, ModelMap model, + @ModelAttribute("searchVO") SiteSearch search) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site) authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + log.info("underSiteCredit" + underSiteCredit); + model.put("siteCredit", siteCredit); + model.put("underSiteCredit", underSiteCredit); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + PageFormVO pageVo = new PageFormVO(); + search.setSiteId(loginSite.getSiteId()); + search.setSiteIdx(loginSite.getSiteIdx()); + search.setCreditType("CO"); + + int totalCount = creditService.getCreditListCnt(search); + if (totalCount != 0) { + PageFormVO commonForm = new PageFormVO(); + commonForm.setFunction_name("goPage"); + commonForm.setPage(search.getPage()); + commonForm.setCount_per_page(20); + if (search.getCount_per_list() == 0) { + commonForm.setCount_per_list(10); + } else { + commonForm.setCount_per_list(search.getCount_per_list()); + } + commonForm.setTatal_list_count(totalCount); + pageVo = PagingUtil.setPageUtil(commonForm); + search.setLimit(pageVo.getLimit()); + search.setOffset(pageVo.getOffset()); + search.setTatal_list_count(totalCount); + + model.put("pageInfo", pageVo.getPagination()); + } + + List list = creditService.getCreditList(search); + model.put("list", list); + + return "admin/exchangeapply"; + } + + @RequestMapping("/addProc") + public @ResponseBody JSONObject addProc(HttpServletRequest request, ModelMap model, Credit credit) + throws Exception { + + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site) authentication.getDetails(); + + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + + JSONObject obj = new JSONObject(); + // enum('AI','AO','CI','CO','DP','CD','SDP','SCD') + // inout (받는사람 기준으로 인인지 아웃인지) + // status 바로적립 1, 승인대기 0 + // siteId 타겟사이트 아이디 + final String LOG_PREFIX = "#-super::CREDIT_DEPOSIT:::"; + log.info(LOG_PREFIX + "Credit::" + credit.toString()); + + if ("AI".equals(credit.getCreditType()) || "AO".equals(credit.getCreditType())) { + OTPInfo otpManager = siteService.getOtpInfoByManger(loginSite.getSiteIdx()); + if (otpManager == null || otpManager.getAccount().equals("")) { + log.error(LOG_PREFIX + "OTP정보가 없습니다."); + obj.put("RES", "FAIL"); + obj.put("MSG", "OTP정보가 없습니다."); + return obj; + } else { + log.info(LOG_PREFIX + "OTP Info::" + otpManager.toString()); + String secret = otpManager.getSecretKey(); + if (credit.getOtp() == null || "".equals(credit.getOtp())) { + log.error(LOG_PREFIX + "OTP 번호를 입력하세요."); + obj.put("RES", "FAIL"); + obj.put("MSG", "OTP 번호를 입력하세요."); + return obj; + } + + boolean chkOtp = TOTPTokenGenerator.otpVerify(secret, Integer.parseInt(credit.getOtp())); + if (!chkOtp) { + log.error(LOG_PREFIX + "OTP 번호가 일치하지 않습니다."); + obj.put("RES", "FAIL"); + obj.put("MSG", "OTP 번호가 일치하지 않습니다."); + return obj; + } + } + + SiteSearch search = new SiteSearch(); + search.setSiteId(credit.getTargetSiteId()); + search.setSiteIdx(credit.getTargetSiteIdx()); + Site targetSite = siteService.getSiteDetail(search); + credit.setSiteLevel(targetSite.getSiteLevel()); + } + + if ("AI".equals(credit.getCreditType())) { // 관리 직접 지금 + + if (siteCredit < credit.getCreditAmt()) { + obj.put("RES", "FAIL"); + obj.put("MSG", "크레딧이 모자릅니다."); + return obj; + } + + credit.setInOut("IN"); + credit.setCreditStatus(1); + credit.setSiteIdx(loginSite.getSiteIdx()); + credit.setSiteId(loginSite.getSiteId()); + + } else if ("AO".equals(credit.getCreditType())) { // 관리자 직접환급 + + long targetSiteCredit = siteService.getSiteCredit(credit.getTargetSiteId()); + + if (targetSiteCredit < credit.getCreditAmt()) { + obj.put("RES", "FAIL"); + obj.put("MSG", "해당 에이젼시의 크레딧이 모자릅니다."); + return obj; + } + + credit.setInOut("OUT"); + credit.setCreditStatus(1); + credit.setSiteIdx(loginSite.getSiteIdx()); + credit.setSiteId(loginSite.getSiteId()); + + } else if ("CI".equals(credit.getCreditType())) { // 충전 신청 + + long targetSiteCredit = siteService.getSiteCredit(loginSite.getUpperSiteId()); + if (targetSiteCredit < credit.getCreditAmt()) { + obj.put("RES", "FAIL"); + obj.put("MSG", "싱으; 에이젼시의 크레딧이 모자릅니다. 상위 에이전시에 문의하세요"); + return obj; + } + + credit.setInOut("IN"); + credit.setCreditStatus(0); + + credit.setSiteIdx(loginSite.getUpperSiteIdx());// 상위사이트아이디 + credit.setSiteId(loginSite.getUpperSiteId()); + + credit.setTargetSiteIdx(loginSite.getSiteIdx()); // 타켓사이트 아이디; + credit.setTargetSiteId(loginSite.getSiteId()); + + credit.setCreditRate(loginSite.getSiteCreditRate()); + + } else if ("CO".equals(credit.getCreditType())) { // 환전 신청 + + if (siteCredit < credit.getCreditAmt()) { + obj.put("RES", "FAIL"); + obj.put("MSG", "크레딧이 모자릅니다."); + return obj; + } + + credit.setInOut("OUT"); + credit.setCreditStatus(0); + + credit.setSiteIdx(loginSite.getUpperSiteIdx());// 상위사이트아이디 + credit.setSiteId(loginSite.getUpperSiteId()); + + credit.setTargetSiteIdx(loginSite.getSiteIdx()); // 타켓사이트 아이디; + credit.setTargetSiteId(loginSite.getSiteId()); + + credit.setCreditRate(loginSite.getSiteCreditRate()); + + } else if ("DP".equals(credit.getCreditType())) { // 베팅크레딧 + // credit.setInOut("OUT"); + // credit.setCreditStatus(1); + + } else if ("CD".equals(credit.getCreditType())) { // 윈머니크레딧 + // cash.setInOut("IN"); + // cash.setCreditStatus(1); + } else if ("SDP".equals(credit.getCreditType())) { // 서브포인트충전 신청 + // cash.setInOut("IN"); + // cash.setCreditStatus(0); + + credit.setInOut("IN"); + credit.setCreditStatus(0); + credit.setSiteIdx(loginSite.getUpperSiteIdx());// 상위사이트아이디 + credit.setSiteId(loginSite.getUpperSiteId()); + + credit.setTargetSiteIdx(loginSite.getSiteIdx()); // 타켓사이트 아이디; + credit.setTargetSiteId(loginSite.getSiteId()); + credit.setCreditRate(loginSite.getSiteCreditRate()); + + } else if ("SCD".equals(credit.getCreditType())) { // 서브포인트환전 현재 없음 + + } + + log.info(credit.toString()); + + int res = creditService.insertCredit(credit); + + obj.put("RES", "SUCCESS"); + + return obj; + } + + @RequestMapping("/statusUpdate") + public @ResponseBody JSONObject statusUpdate(HttpServletRequest request, ModelMap model, Credit credit) + throws Exception { + + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site) authentication.getDetails(); + + // enum('AI','AO','CI','CO','DP','CD','SDP','SCD') + // inout (받는사람 기준으로 인인지 아웃인지) + // status 바로적립 1, 승인대기 0 + // siteId 타겟사이트 아이디 + + JSONObject obj = new JSONObject(); + log.info(credit.toString()); + + int res = creditService.updateStatus(credit); + + obj.put("RES", "SUCCESS"); + + return obj; + } + + @GetMapping("/point") + public String point(HttpServletRequest request, ModelMap model, @ModelAttribute("searchVO") SiteSearch search) + throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site) authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + log.info("underSiteCredit" + underSiteCredit); + model.put("siteCredit", siteCredit); + model.put("underSiteCredit", underSiteCredit); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + PageFormVO pageVo = new PageFormVO(); + search.setSiteId(loginSite.getSiteId()); + search.setSiteIdx(loginSite.getSiteIdx()); + search.setCreditType("CO"); + + int totalCount = creditService.getPointListCnt(search); + if (totalCount != 0) { + PageFormVO commonForm = new PageFormVO(); + commonForm.setFunction_name("goPage"); + commonForm.setPage(search.getPage()); + commonForm.setCount_per_page(20); + if (search.getCount_per_list() == 0) { + commonForm.setCount_per_list(10); + } else { + commonForm.setCount_per_list(search.getCount_per_list()); + } + commonForm.setTatal_list_count(totalCount); + pageVo = PagingUtil.setPageUtil(commonForm); + search.setLimit(pageVo.getLimit()); + search.setOffset(pageVo.getOffset()); + search.setTatal_list_count(totalCount); + + model.put("pageInfo", pageVo.getPagination()); + } + + List list = creditService.getPointList(search); + model.put("list", list); + + return "admin/applypoint"; + } + + @RequestMapping("/addPointProc") + public @ResponseBody JSONObject addPointProc(HttpServletRequest request, ModelMap model, CreditPoint point) + throws Exception { + + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site) authentication.getDetails(); + JSONObject resObj = new JSONObject(); + + long sitePoint = siteService.getSitePoint(point.getTargetSiteId()); + final String LOG_PREFIX = "#-addPointProc::" + loginSite.getSiteId() + "=>" + point.getTargetSiteId() + ":::"; + long time = System.currentTimeMillis(); + + log.info(LOG_PREFIX + "CreditPoint Info : " + point.toString()); + + OTPInfo otpManager = siteService.getOtpInfoByManger(loginSite.getSiteIdx()); + if (otpManager == null || otpManager.getAccount().equals("")) { + log.error(LOG_PREFIX + "OTP정보가 없습니다."); + resObj.put("RES", "FAIL"); + resObj.put("MSG", "OTP정보가 없습니다."); + return resObj; + } else { + log.info(LOG_PREFIX + "OTP Info::" + otpManager.toString()); + String secret = otpManager.getSecretKey(); + if (point.getOtp() == null || "".equals(point.getOtp())) { + log.error(LOG_PREFIX + "OTP 번호를 입력하세요."); + resObj.put("RES", "FAIL"); + resObj.put("MSG", "OTP 번호를 입력하세요."); + return resObj; + } + + boolean chkOtp = TOTPTokenGenerator.otpVerify(secret, Integer.parseInt(point.getOtp())); + if (!chkOtp) { + log.error(LOG_PREFIX + "OTP 번호가 일치하지 않습니다."); + resObj.put("RES", "FAIL"); + resObj.put("MSG", "OTP 번호가 일치하지 않습니다."); + return resObj; + } + } + + if ("POINT_DEPOSIT".equals(point.getVendor())) { + // 관리자 지급 + String tranId = "POINT_DEPOSIT-" + loginSite.getSiteId() + ">" + point.getTargetSiteId() + "-" + time; + String betId = "포인트 수동지급-" + loginSite.getSiteId() + ">" + point.getTargetSiteId() + "-" + time; + point.setSiteIdx((long) loginSite.getSiteIdx()); + point.setSiteId(loginSite.getSiteId()); + point.setTranId(tranId); + point.setBetId(betId); + point.setPrePointAmt(sitePoint); + + } else if ("POINT_WITHDRAW".equals(point.getVendor())) { + // 관리자 회수 + if (sitePoint < point.getPointAmt().intValue()) { + resObj.put("RES", "FAIL"); + resObj.put("MSG", "해당 에이젼시의 포인트가 부족합니다."); + return resObj; + } + String tranId = "POINT_WITHDRAW-" + loginSite.getSiteId() + ">" + point.getTargetSiteId() + "-" + time; + String betId = "포인트 수동회수-" + loginSite.getSiteId() + ">" + point.getTargetSiteId() + "-" + time; + point.setSiteIdx((long) loginSite.getSiteIdx()); + point.setSiteId(loginSite.getSiteId()); + point.setTranId(tranId); + point.setBetId(betId); + point.setPrePointAmt(sitePoint); + int pointAmt = point.getPointAmt().intValue() * -1; + point.setPointAmt(pointAmt); + } + + log.info(LOG_PREFIX + "CreditPoint Info : " + point.toString()); + int result = creditService.insertPoint(point); + log.info(LOG_PREFIX + "creditService.insertPoint() result : " + result); + + resObj.put("RES", "SUCCESS"); + + return resObj; + } + +} diff --git a/src/main/java/com/bb/admin/controller/GuestController.java b/src/main/java/com/bb/admin/controller/GuestController.java new file mode 100644 index 0000000..dfe9f19 --- /dev/null +++ b/src/main/java/com/bb/admin/controller/GuestController.java @@ -0,0 +1,401 @@ +package com.bb.admin.controller; + +import java.text.SimpleDateFormat; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; + +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.annotation.Secured; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.reactive.function.client.WebClientRequestException; +import org.springframework.web.reactive.function.client.WebClientResponseException; + +import com.bb.exception.ApiException; +import com.bb.model.ApiResponse; +import com.bb.model.BetParam; +import com.bb.model.NexusApiInfo; +import com.bb.model.PageFormVO; +import com.bb.model.Site; +import com.bb.model.SiteSearch; +import com.bb.model.TplusApiInfo; +import com.bb.service.SiteService; +import com.bb.service.StatService; +import com.bb.util.PagingUtil; +import com.bb.util.StringUtils; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.gson.Gson; + +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import okhttp3.OkHttpClient; + +@Slf4j +@Controller +@RequestMapping(value = "/guest") +public class GuestController { + + @Autowired + StatService statService; + + @Autowired + SiteService siteService; + + @GetMapping("/guestLogin") + public String guestLogin(HttpServletRequest request, ModelMap model) throws Exception { + + return "admin/guestLogin"; + } + + @GetMapping("/simpleReport") + //@Secured("ROLE_GUEST") + public String simpleReport(HttpServletRequest request, ModelMap model, @ModelAttribute("searchVO") SiteSearch search) + throws Exception { + final String LOG_PREFIX = "#-SUPER::simpleReport::::"; + + if(search.getSearchSiteId() != null && !"".equals(search.getSearchSiteId())) { + Site targetSite = siteService.getSiteSimpleDetail(search); + if(targetSite != null) { + search.setSearchSiteIdx(targetSite.getSiteIdx()); + } else { + search.setSearchSiteIdx(0); + } + } else { + search.setSearchSiteIdx(0); + } + + String toDay = new SimpleDateFormat("yyyy-MM-dd").format(new Date(System.currentTimeMillis())); + String startDay = ""; + String endDay = ""; + if(search.getStartDate() == null || "".equals(search.getStartDate())) { + startDay = toDay; + search.setStartDate(startDay); + } else { + startDay = search.getStartDate().substring(0, 10); + } + + if(search.getEndDate() == null || "".equals(search.getEndDate())) { + endDay = toDay; + search.setEndDate(endDay); + } else { + endDay = search.getEndDate().substring(0, 10); + } + + log.info(LOG_PREFIX+ "startDay::"+startDay); + log.info(LOG_PREFIX+ "endDay::"+endDay); + log.info(LOG_PREFIX+ "toDay::"+toDay); + search.setSiteDispYn("N"); + if(startDay.equals(toDay) || endDay.equals(toDay)) { + search.setSiteDispYn("Y"); + } + + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(search); + JSONObject reqObj = new JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + PageFormVO pageVo= new PageFormVO(); + int totalCount = statService.getAgentReportCnt(search); + if (totalCount != 0) { + PageFormVO commonForm = new PageFormVO(); + commonForm.setFunction_name("goPage"); + commonForm.setPage(search.getPage()); + commonForm.setCount_per_page(20); + commonForm.setCount_per_list(30); + commonForm.setTatal_list_count(totalCount); + pageVo = PagingUtil.setPageUtil(commonForm); + search.setLimit(pageVo.getLimit()); + search.setOffset(pageVo.getOffset()); + search.setTatal_list_count(totalCount); + + model.put("pageInfo", pageVo.getPagination()); + } + log.info(LOG_PREFIX+ "search.getStartDate {}", search.getStartDate()); + log.info(LOG_PREFIX+ "search.getEndDate {}", search.getEndDate()); + log.info(LOG_PREFIX+ "search.getSearchSiteIdx {}", search.getSearchSiteIdx()); + log.info(LOG_PREFIX+ "search.getPage {}", search.getPage()); + log.info(LOG_PREFIX+ "search.getLimit {}", search.getLimit()); + log.info(LOG_PREFIX+ "search.getOffset {}", search.getOffset()); + + List siteList = statService.getAgentReportList(search); + model.put("siteList", siteList); + HashMap siteTotal = statService.getAgentReportTotal(search); + model.put("siteTotal", siteTotal); + + return "admin/simpleReport"; + } + + /* + @ResponseBody + @GetMapping(value="/betDetail") + public ApiResponse betDetail(HttpServletRequest request, @RequestParam("betId") String betId) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + final String LOG_PREFIX = "#-CMN::BET-DETAIL::"+betId+":::"; + JSONObject saveObj = null; + JSONArray saveObjs = null; + boolean isSaveEvoDetail = false; + + try { + // apiKey 체크 + Site site = siteService.getSiteInfo(request); + if(site ==null) { + throw new ApiException("1000", "accessDinied"); + } + + // 결과보내기 + String dType = "detail_0"; + + HashMap betInfo = transService.getBetInfoByBetId(param); + log.info(LOG_PREFIX+ "betInfo {}", betInfo); + + if(betInfo == null) betInfo = transService.getSiteBetByRefIdFromOld(param); + log.info(LOG_PREFIX+ "betInfo_OLD {}", betInfo); + + if(betInfo != null) { + String category = betInfo.get("vendorCetegory").toString(); + log.info(LOG_PREFIX+ "Game category : " + category); + + if("svendor".equals(betInfo.get("vendorCode").toString()) + || "pink".equals(betInfo.get("vendorCode").toString())) { + String jsonStr = siteService.getOrgDetailData(param); + log.info(LOG_PREFIX+ "jsonStr : " + jsonStr); + if(jsonStr != null && !"".equals(jsonStr) && !"{}".equals(jsonStr)) { + dType = "detail_6"; + apiResponse.put("dType", dType); + HashMap detailMap = new Gson().fromJson(jsonStr, HashMap.class); + apiResponse.put("detail", detailMap); + } else { + isSaveEvoDetail = true; + JSONObject dataObj = svendorService.getDetail(LOG_PREFIX, betInfo); + if(dataObj == null) { + apiResponse.put("detail", "betId is not exist"); + } else { + if(dataObj.has("gameDetail") && !dataObj.isNull("gameDetail")) { + String detailType = StringUtils.getType(dataObj.getString("gameDetail")); + if(detailType.equals("URL")) { + dType = "detail_2"; + apiResponse.put("dType", dType); + String detailUrl = dataObj.getString("gameDetail"); + apiResponse.put("detail", detailUrl); + } else if(detailType.equals("JSON")) { + dType = "detail_6"; + apiResponse.put("dType", dType); + JSONObject detailObj = dataObj.getJSONObject("gameDetail"); + saveObj = detailObj; + HashMap detailMap = new Gson().fromJson(detailObj.toString(), HashMap.class); + apiResponse.put("detail", detailMap); + } else { + apiResponse.put("detail", "betId is not exist"); + } + } else { + apiResponse.put("detail", "betId is not exist"); + } + } + } + + } else if("nexus".equals(betInfo.get("vendorCode").toString()) || "ace2".equals(betInfo.get("vendorCode").toString())) { + String jsonStr = siteService.getOrgDetailData(param); + log.info(LOG_PREFIX+ "jsonStr : " + jsonStr); + if(jsonStr != null && !"".equals(jsonStr) && !"{}".equals(jsonStr)) { + dType = "detail_3"; + apiResponse.put("dType", dType); + HashMap detailMap = new Gson().fromJson(jsonStr, HashMap.class); + apiResponse.put("detail", detailMap); + } + } else if("prime".equals(betInfo.get("vendorCode").toString()) + || "dpcore".equals(betInfo.get("vendorCode").toString())) { + log.info(LOG_PREFIX+ "========== BetDetail::PRIME =========="); + dType = "detail_9"; + apiResponse.put("dType", dType); + + String jsonStr = siteService.getOrgDetailData(param); + if(jsonStr != null && !"".equals(jsonStr) && !"{}".equals(jsonStr)) { + HashMap detailMap = new Gson().fromJson(jsonStr, HashMap.class); + apiResponse.put("detail", detailMap); + } + } else if("onix".equals(betInfo.get("vendorCode").toString())) { + log.info(LOG_PREFIX+ "========== BetDetail::ONIX =========="); + dType = "detail_8"; + apiResponse.put("dType", dType); + + String apiBaseUrl = betInfo.get("vendorApiUrl").toString(); + + // Step 1: Get round info from /csapi/getBetting + String bettingUrl = apiBaseUrl + "/csapi/getBetting"; + JSONObject bettingBody = new JSONObject(); + bettingBody.put("userid", betInfo.get("memberId").toString()); + bettingBody.put("sdate", "2000-01-01 00:00:00.000"); + bettingBody.put("edate", "2099-12-31 23:59:59.999"); + bettingBody.put("pagesize", "1"); + bettingBody.put("gameid", "0"); + bettingBody.put("tranid", param.getBetId()); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + + log.info(LOG_PREFIX+ "ONIX::Step1 getBetting Url: " + bettingUrl); + log.info(LOG_PREFIX+ "ONIX::Step1 getBetting Body: " + bettingBody.toString()); + + try { + ResponseEntity bettingRes = webClient.post() + .uri(bettingUrl) + .headers(h -> h.addAll(headers)) + .bodyValue(bettingBody.toString()) + .retrieve() + .toEntity(String.class) + .block(); + if(bettingRes != null && bettingRes.getBody() != null) { + JSONObject bettingObj = new JSONObject(bettingRes.getBody()); + log.info(LOG_PREFIX+ "ONIX::Step1 getBetting Response: " + bettingObj.toString()); + + int bettingResult = bettingObj.getInt("result"); + if(bettingResult == 1 && bettingObj.has("data")) { + JSONArray dataArray = bettingObj.getJSONArray("data"); + if(dataArray.length() > 0) { + JSONObject betData = dataArray.getJSONObject(0); + String round = betData.has("round") ? betData.getString("round") : ""; + String realround = betData.has("realround") ? betData.getString("realround") : ""; + String game = betData.has("game") ? betData.getString("game") : ""; + + log.info(LOG_PREFIX+ "ONIX::Betting Info - round: " + round + ", realround: " + realround + ", game: " + game); + + // Step 2: Get detail link from /api/apigamedetail.aspx + if(!round.isEmpty() && !realround.isEmpty()) { + String gtype = game.toLowerCase().contains("slot") || game.toLowerCase().contains("prg") ? "sxprg" : "apievo"; + String detailUrl = apiBaseUrl + "/api/apigamedetail.aspx?gtype=" + gtype; + + if(gtype.equals("apievo")) { + detailUrl += "&round=" + round + "&realround=" + realround; + } else { + detailUrl += "&roundid=" + realround; + } + + log.info(LOG_PREFIX+ "ONIX::Step2 Detail Url: " + detailUrl); + + try { + ResponseEntity detailRes = webClient.get() + .uri(detailUrl) + .retrieve() + .toEntity(String.class) + .block(); + + if(detailRes != null && detailRes.getBody() != null) { + JSONObject detailObj = new JSONObject(detailRes.getBody()); + log.info(LOG_PREFIX+ "ONIX::Step2 Detail Response: " + detailObj.toString()); + + if(detailObj.getInt("result") == 1 && detailObj.has("link")) { + isSaveEvoDetail = true; + JSONObject saveData = new JSONObject(); + saveData.put("link", detailObj.getString("link")); + saveData.put("betInfo", betData); + saveObj = saveData; + + HashMap detailMap = new HashMap<>(); + detailMap.put("link", detailObj.getString("link")); + detailMap.put("betInfo", new Gson().fromJson(betData.toString(), HashMap.class)); + apiResponse.put("detail", detailMap); + log.info(LOG_PREFIX+ "ONIX::Detail loaded successfully"); + } else { + apiResponse.put("detail", "betId is not exist"); + String msg = detailObj.has("msg") ? detailObj.getString("msg") : "Unknown error"; + log.error(LOG_PREFIX+ "ONIX::Detail Error: " + msg); + } + } else { + apiResponse.put("detail", "betId is not exist"); + } + } catch(Exception detailEx) { + log.error(LOG_PREFIX+ "ONIX::Detail Exception: " + detailEx.getMessage()); + apiResponse.put("detail", "betId is not exist"); + } + } else { + // No round info, use betting data only + isSaveEvoDetail = true; + saveObj = betData; + HashMap detailMap = new Gson().fromJson(betData.toString(), HashMap.class); + apiResponse.put("detail", detailMap); + log.info(LOG_PREFIX+ "ONIX::Betting data loaded (no round info)"); + } + } else { + apiResponse.put("detail", "betId is not exist"); + } + } else { + apiResponse.put("detail", "betId is not exist"); + String errorMsg = bettingObj.has("msg") ? bettingObj.getString("msg") : "Unknown error"; + log.error(LOG_PREFIX+ "ONIX::Betting Error: " + errorMsg); + } + } else { + apiResponse.put("detail", "betId is not exist"); + log.error(LOG_PREFIX+ "ONIX::Betting Response is null"); + } + } catch(WebClientResponseException e) { + log.error(LOG_PREFIX+ "ONIX::Betting HttpClientErrorException : " + e.getMessage()); + log.error(LOG_PREFIX+ "ONIX::Betting status code : " + e.getStatusCode().value()); + log.error(LOG_PREFIX+ "ONIX::Betting response body : " + e.getResponseBodyAsString()); + JSONObject errorJson = new JSONObject(e.getResponseBodyAsString()); + String errorMsg = errorJson.has("msg") ? errorJson.getString("msg") : "Betting API error"; + log.error(LOG_PREFIX+ "ONIX::Betting error : " + errorMsg); + throw new ApiException("P209", errorMsg); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ONIX::Betting ConnectTimeoutException::" + rae.getMessage()); + } + if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "ONIX::Betting ReadTimeoutException::" + rae.getMessage()); + } + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "ONIX::Betting InterruptedException::" + rae.getMessage()); + } + throw new ApiException("P210", rae.getMessage()); + } catch(Exception e) { + log.error(LOG_PREFIX+ "ONIX::Betting Exception : " + e.getMessage()); + throw new ApiException("P211", e.getMessage()); + } + } else if("bet_radar".equals(betInfo.get("vendorCode").toString())) { + log.info(LOG_PREFIX+ "========== BetDetail::BET_RADAR =========="); + // bet_radar_log 테이블에서 조회 + String radarLogJson = siteService.getMergedBetRadarLog(param.getBetId()); + if(radarLogJson != null && !radarLogJson.isEmpty()) { + log.info(LOG_PREFIX+ "bet_radar_log found, returning merged json"); + dType = "detail_radar"; + apiResponse.put("dType", dType); + HashMap detailMap = new Gson().fromJson(radarLogJson, HashMap.class); + apiResponse.put("detail", detailMap); + apiResponse.success(); + return apiResponse; + } + } else { + apiResponse.put("dType", dType); + apiResponse.put("detail", "betId is not exist"); + } + } else { + apiResponse.put("dType", dType); + apiResponse.put("detail", "betId is not exist"); + } + + apiResponse.success(); + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]::"+e.toString()); + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + */ +} diff --git a/src/main/java/com/bb/admin/controller/InsuranceController.java b/src/main/java/com/bb/admin/controller/InsuranceController.java new file mode 100644 index 0000000..1992200 --- /dev/null +++ b/src/main/java/com/bb/admin/controller/InsuranceController.java @@ -0,0 +1,424 @@ +package com.bb.admin.controller; + +import java.util.HashMap; +import java.util.List; + +import jakarta.servlet.http.HttpServletRequest; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.annotation.Secured; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import com.bb.model.CommonParamAdmin; +import com.bb.model.Insure; +import com.bb.model.PageFormVO; +import com.bb.model.Site; +import com.bb.model.SiteSearch; +import com.bb.service.CreditService; +import com.bb.service.SiteService; +import com.bb.util.PagingUtil; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +import lombok.extern.slf4j.Slf4j; +import net.sf.json.JSONObject; + +@Slf4j +@Controller +@RequestMapping(value = "/insurance") +@PreAuthorize("hasRole('ADMIN')") +public class InsuranceController { + + @Autowired + SiteService siteService; + + @Autowired + CreditService creditService; + + + @RequestMapping("/addProc") + public @ResponseBody JSONObject addProc( HttpServletRequest request, ModelMap model, Insure insure) throws Exception { + JSONObject obj = new JSONObject(); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + insure.setSiteId(loginSite.getSiteId()); + insure.setSiteIdx(loginSite.getSiteIdx()); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + + + List vederRateList = siteService.getVenderRateList(loginSite); + if(vederRateList.size() <0) { + obj.put("RES", "FAIL"); + obj.put("MSG", "보험설정을 해주세요."); + return obj; + }else{ + + System.out.println(":dddddddddd" + vederRateList.get(0).get("insureUpSiteIdx")); + if(vederRateList.get(0).get("insureUpSiteIdx") == null || "null".equals(vederRateList.get(0).get("insureUpSiteIdx"))) { + + obj.put("RES", "FAIL"); + obj.put("MSG", "보험적용컴퍼니가 없습니다. 보험설정을 해주세요."); + return obj; + } + } + + insure.setSiteIdx(loginSite.getSiteIdx()); + insure.setSiteId(loginSite.getSiteId()); + insure.setInsureUpSiteId(vederRateList.get(0).get("insureUpSiteId").toString()); + insure.setInsureUpSiteIdx(Long.parseLong(vederRateList.get(0).get("insureUpSiteIdx").toString())); + insure.setPreCreditAmt(siteCredit); + insure.setPreCreditPoint(sitePoint); + insure.setPreInsureAmt(insureAmt); + insure.setPreInsurePoint(insurePointAmt); + insure.setStatus("0"); + insure.setRegId(loginSite.getSiteId()); + + if("TRANIN".equals(insure.getInsureType())){ //충전 신청 + + + + + + }else if("TRANOUT".equals(insure.getInsureType())){ //환전 신청 + + + } + + + + + + int res = creditService.insertInsure(insure); + + obj.put("RES", "SUCCESS"); + + return obj; + } + + @RequestMapping("/updateStatus") + public @ResponseBody JSONObject updateStatus( HttpServletRequest request, ModelMap model, Insure insure) throws Exception { + + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + insure.setSiteId(loginSite.getSiteId()); + insure.setSiteIdx(loginSite.getSiteIdx()); + // 상위 보험 관련 데이터 가져오기 + + + JSONObject obj = new JSONObject(); + + int res = creditService.updateInsureStatus(insure); + + obj.put("RES", "SUCCESS"); + + return obj; + } + + + + @GetMapping("/set") + public String index( HttpServletRequest request , ModelMap model) throws Exception { + System.out.println("index"); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + model.put("underSiteCredit", underSiteCredit); + model.put("siteCredit", siteCredit); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + + //상위 컴파니 불려오기 + + List flowList = siteService.getSiteFlow(loginSite); + model.put("flowList", flowList); + //벤더 리스트 rate 불러오기 + List vederRateList = siteService.getVenderRateList(loginSite); + + int uppersiteIdx = 0; + if(vederRateList.size()>0) { + + try { + uppersiteIdx = Integer.parseInt(vederRateList.get(0).get("insureUpSiteIdx").toString()); + }catch(Exception e) { + uppersiteIdx = 0; + + } + } + model.put("uppersiteIdx", uppersiteIdx); + + /*SELECT * FROM vendors_info vi + LEFT JOIN `site_rate_info` sri ON vi.vendorIdx = sri.vendorIdx + WHERE vi.delYn= 'N' AND vi.useYn ='Y' + AND sri.siteIdx = 1 + */ + model.put("vederRateList", vederRateList); + + return "admin/insuredSet"; + } + + @RequestMapping("/setSave") + public @ResponseBody JSONObject setSave( HttpServletRequest request, ModelMap model, CommonParamAdmin commonParamAdmin ) throws Exception { + + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + + + + + JSONObject obj = new JSONObject(); + log.info(commonParamAdmin.toString()); + + for(int i=0;i() {}); + + siteService.saveVendorInsureRate(paramMap); + } + + + + + + + obj.put("RES", "SUCCESS"); + + return obj; + } + + @GetMapping("/betList") + public String betList( HttpServletRequest request ,ModelMap model , @ModelAttribute("searchVO") SiteSearch search) throws Exception { + System.out.println("index"); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + model.put("underSiteCredit", underSiteCredit); + model.put("siteCredit", siteCredit); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + + + + + PageFormVO pageVo= new PageFormVO(); + + if("up".equals(search.getUpdown())){ + search.setSiteIdx(loginSite.getSiteIdx()); + }else if("down".equals(search.getUpdown())){ + search.setUpperSiteId(loginSite.getSiteId()); + } + search.setSearchType("BET"); + search.setStatus("1"); + + int totalCount = creditService.getInsureListCnt(search); + if (totalCount != 0) { + PageFormVO commonForm = new PageFormVO(); + commonForm.setFunction_name("goPage"); + commonForm.setPage(search.getPage()); + commonForm.setCount_per_page(20); + if(search.getCount_per_list()==0) { + commonForm.setCount_per_list(15); + } else { + commonForm.setCount_per_list(search.getCount_per_list()); + } + commonForm.setTatal_list_count(totalCount); + pageVo = PagingUtil.setPageUtil(commonForm); + search.setLimit(pageVo.getLimit()); + search.setOffset(pageVo.getOffset()); + search.setTatal_list_count(totalCount); + + model.put("pageInfo", pageVo.getPagination()); + } + + + List list = creditService.getInsureList(search); + + model.put("list", list); + + return "admin/insuredBetList"; + } + + @GetMapping("/history") + public String history( HttpServletRequest request , ModelMap model) throws Exception { + System.out.println("index"); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + model.put("underSiteCredit", underSiteCredit); + model.put("siteCredit", siteCredit); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + + + return "admin/insuredHistory"; + } + + @GetMapping("/apply") + public String apply( HttpServletRequest request , ModelMap model, @ModelAttribute("searchVO") SiteSearch search) throws Exception { + System.out.println("index"); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + model.put("underSiteCredit", underSiteCredit); + model.put("siteCredit", siteCredit); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + PageFormVO pageVo= new PageFormVO(); + search.setUpperSiteId(loginSite.getSiteId()); + search.setSearchType("TRANIN"); + + if(search.getStatus()==null || "".equals(search.getStatus())) { + search.setStatus("0"); + } + + + int totalCount = creditService.getInsureListCnt(search); + if (totalCount != 0) { + PageFormVO commonForm = new PageFormVO(); + commonForm.setFunction_name("goPage"); + commonForm.setPage(search.getPage()); + commonForm.setCount_per_page(20); + if(search.getCount_per_list()==0) { + commonForm.setCount_per_list(10); + } else { + commonForm.setCount_per_list(search.getCount_per_list()); + } + commonForm.setTatal_list_count(totalCount); + pageVo = PagingUtil.setPageUtil(commonForm); + search.setLimit(pageVo.getLimit()); + search.setOffset(pageVo.getOffset()); + search.setTatal_list_count(totalCount); + + model.put("pageInfo", pageVo.getPagination()); + } + + model.put("searchVO", search); + List list = creditService.getInsureList(search); + model.put("list", list); + + // model.addObject("long", Long.parseLong(null)); + + + return "admin/insuredApply"; + } + + + + + + @GetMapping("/exchange") + public String exchange( HttpServletRequest request , ModelMap model, @ModelAttribute("searchVO") SiteSearch search) throws Exception { + System.out.println("index"); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + model.put("underSiteCredit", underSiteCredit); + model.put("siteCredit", siteCredit); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + PageFormVO pageVo= new PageFormVO(); + search.setUpperSiteId(loginSite.getSiteId()); + search.setSearchType("TRANOUT"); + + if(search.getStatus()==null || "".equals(search.getStatus())) { + search.setStatus("0"); + } + + + int totalCount = creditService.getInsureListCnt(search); + if (totalCount != 0) { + PageFormVO commonForm = new PageFormVO(); + commonForm.setFunction_name("goPage"); + commonForm.setPage(search.getPage()); + commonForm.setCount_per_page(20); + if(search.getCount_per_list()==0) { + commonForm.setCount_per_list(10); + } else { + commonForm.setCount_per_list(search.getCount_per_list()); + } + commonForm.setTatal_list_count(totalCount); + pageVo = PagingUtil.setPageUtil(commonForm); + search.setLimit(pageVo.getLimit()); + search.setOffset(pageVo.getOffset()); + search.setTatal_list_count(totalCount); + + model.put("pageInfo", pageVo.getPagination()); + } + + model.put("searchVO", search); + List list = creditService.getInsureList(search); + model.put("list", list); + + // model.addObject("long", Long.parseLong(null)); + + + return "admin/insuredExchange"; + } + + +} diff --git a/src/main/java/com/bb/admin/controller/MainController.java b/src/main/java/com/bb/admin/controller/MainController.java new file mode 100644 index 0000000..2053d66 --- /dev/null +++ b/src/main/java/com/bb/admin/controller/MainController.java @@ -0,0 +1,274 @@ +package com.bb.admin.controller; + +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.reactive.function.client.WebClient; + +import com.bb.model.ApiTestVO; +import com.bb.model.Site; +import com.bb.service.SiteService; + +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import net.sf.json.JSONObject; + +@Slf4j +@Controller +@RequestMapping(value = "") +public class MainController { + + @Autowired + SiteService siteService; + + @Autowired + private WebClient webClient; // 싱글톤 WebClient 주입 + + @GetMapping("/") + @PreAuthorize("permitAll()") + public String first(HttpServletRequest request, ModelMap model) throws Exception { + System.out.println("error/404"); + + String code = request.getParameter("code"); + model.put("code", code); + + return "error/404"; + } + + @GetMapping("/lg") + public String loginsForm(HttpServletRequest request, ModelMap model) throws Exception { + System.out.println("login"); + + return "admin/lg"; + } + + @GetMapping("/index") + @PreAuthorize("hasRole('ADMIN')") + public String index(HttpServletRequest request, ModelMap model) throws Exception { + + System.out.println("index"); + + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site) authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + model.put("underSiteCredit", underSiteCredit); + model.put("siteCredit", siteCredit); + // long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", 0); + // HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", 0); + // pot 정보 가져오기 + + // long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + // long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", 0); + model.put("insurePointAmt", 0); + + Map dashInfo = siteService.getDashInfo(loginSite); // 베팅정보 + Map dashInfo2 = siteService.getDashInfo2(loginSite); // 하부에이전수 수. + + model.put("dashInfo", dashInfo); + model.put("dashInfo2", dashInfo2); + + return "admin/index"; + } + + @GetMapping("/mypage") + @PreAuthorize("hasRole('ADMIN')") + public String mypage(HttpServletRequest request, ModelMap model) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site) authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + log.info("underSiteCredit" + underSiteCredit); + model.put("siteCredit", siteCredit); + model.put("underSiteCredit", underSiteCredit); + Site mypageInfo = siteService.getSiteInfoMypage(loginSite); + model.put("mypageInfo", mypageInfo); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + return "admin/mypage"; + } + + @RequestMapping("/mypage/pwdUpdate") + @PreAuthorize("hasRole('ADMIN')") + public @ResponseBody JSONObject pwdUpdate(HttpServletRequest request, ModelMap model, Site site) throws Exception { + JSONObject obj = new JSONObject(); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site) authentication.getDetails(); + site.setUpperSiteId(loginSite.getSiteId()); + site.setUpperSiteIdx(loginSite.getSiteIdx()); + + Map siteParam = new HashMap(); + siteParam.put("siteId", loginSite.getSiteId()); + siteParam.put("sitePass", site.getNowPass()); + + Site checkSite = siteService.getSiteBypassword(siteParam); + + if (checkSite == null) { + + obj.put("RES", "FAIL"); + obj.put("MSG", "현재 비밀번호를 확인해주세요."); + return obj; + } else { + siteParam.put("newPass", site.getNewPass()); + siteService.updatePass(siteParam); + } + + obj.put("RES", "SUCCESS"); + + return obj; + } + + @RequestMapping("/mypage/siteUpdate") + @PreAuthorize("hasRole('ADMIN')") + public @ResponseBody JSONObject siteUpdate(HttpServletRequest request, ModelMap model, Site site) throws Exception { + JSONObject obj = new JSONObject(); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site) authentication.getDetails(); + site.setSiteId(loginSite.getSiteId()); + final String LOG_PREFIX = "#-super::mySiteUpdate:::"; + + String siteKey = loginSite.getSiteKey(); + if ("new".equals(site.getSiteKey())) { + siteKey = makeApiKey(loginSite.getSiteId()); + site.setSiteKey(siteKey); + } + + log.info(LOG_PREFIX + "Site Info: " + site.toString()); + log.info(LOG_PREFIX + "Site IP: " + site.getSiteIp()); + siteService.siteUpdate(LOG_PREFIX, site); + + obj.put("RES", "SUCCESS"); + obj.put("DATA", siteKey); + + return obj; + } + + @RequestMapping(value = "/manual/apiTest") + @PreAuthorize("hasRole('ADMIN')") + public @ResponseBody JSONObject apiTest(HttpServletRequest request, ModelMap model, ApiTestVO param) + throws Exception { + + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site) authentication.getDetails(); + JSONObject obj = new JSONObject(); + + try { + log.info("##### API Test 시작: {}", param.toString()); + + String apiUrl = param.getApiUrl(); + + // 1. 전송할 바디 데이터 구성 + JSONObject paraJson = new JSONObject(); + paraJson.put("userId", param.getUserId()); + paraJson.put("nickName", param.getNickName()); + paraJson.put("userIp", param.getUserIp()); + paraJson.put("balance", param.getBalance()); + + // 빈 값이 아닐 때만 파라미터 추가 + if (param.getVendorKey() != null && !"".equals(param.getVendorKey())) + paraJson.put("vendorKey", param.getVendorKey()); + if (param.getBetId() != null && !"".equals(param.getBetId())) + paraJson.put("betId", param.getBetId()); + if (param.getStartDate() != null && !"".equals(param.getStartDate())) + paraJson.put("startDate", param.getStartDate()); + if (param.getEndDate() != null && !"".equals(param.getEndDate())) + paraJson.put("endDate", param.getEndDate()); + if (param.getGameKey() != null && !"".equals(param.getGameKey())) + paraJson.put("gameKey", param.getGameKey()); + if (param.getIsMobile() != null && !"".equals(param.getIsMobile())) + paraJson.put("isMobile", param.getIsMobile()); + if (param.getLanguage() != null && !"".equals(param.getLanguage())) + paraJson.put("language", param.getLanguage()); + + // 2. WebClient를 이용한 호출 (동기 방식 .block()) + String responseBody = webClient.post().uri(apiUrl).contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON).header("User-Agent", "PostmanRuntime/7.28.4") + .header("Authorization", loginSite.getSiteKey()) + // 토큰이 있을 경우에만 헤더 추가 + .headers(headers -> { + if (param.getToken() != null && !"".equals(param.getToken())) { + headers.add("token", param.getToken()); + } + }).bodyValue(paraJson.toString()).retrieve().bodyToMono(String.class).block(); // 응답이 올 때까지 대기 + + // 3. 응답 결과 처리 + JSONObject resJson = JSONObject.fromObject(responseBody); + + obj.put("RES", "SUCCESS"); + obj.put("DATA", resJson); + + log.info("##### API Test 응답 완료: {}", resJson.toString()); + + } catch (Exception e) { + log.error("##### API Test 에러 발생: {}", e.toString()); + e.printStackTrace(); + obj.put("RES", "FAIL"); + obj.put("MESSAGE", e.getMessage()); // 에러 메시지도 화면에 전달 + } + + return obj; + } + + @GetMapping("/limit") + @PreAuthorize("hasRole('ADMIN')") + public String limit(HttpServletRequest request, ModelMap model) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site) authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + model.put("underSiteCredit", underSiteCredit); + model.put("siteCredit", siteCredit); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + return "admin/limit"; + } + + private String makeApiKey(String param) { + + int n = 10; // n자리 쿠폰 + char[] chs = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', + 'J', 'K', 'L', 'M', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'N', 'O', 'P', 'Q', + 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', + 'z' }; + + Random rd = new Random(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < n; i++) { + char ch = chs[rd.nextInt(chs.length)]; + sb.append(ch); + } + return param + sb.toString(); + + } +} diff --git a/src/main/java/com/bb/admin/controller/ManualController.java b/src/main/java/com/bb/admin/controller/ManualController.java new file mode 100644 index 0000000..da97856 --- /dev/null +++ b/src/main/java/com/bb/admin/controller/ManualController.java @@ -0,0 +1,246 @@ +package com.bb.admin.controller; + +import java.util.HashMap; + +import jakarta.servlet.http.HttpServletRequest; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.annotation.Secured; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; + +import com.bb.model.Site; +import com.bb.model.SiteSearch; +import com.bb.service.SiteService; + +import lombok.extern.slf4j.Slf4j; + + + +@Slf4j +@Controller +@RequestMapping(value = "") +@PreAuthorize("hasRole('ADMIN')") +public class ManualController { + + @Autowired + SiteService siteService; + + + + @GetMapping("/manual") + public String devmanual( HttpServletRequest request, ModelMap model, @ModelAttribute("searchVO") SiteSearch search) throws Exception { + + return "admin/api_doc"; + + } + + @GetMapping("/apiLogdev") + public String devApiLog( HttpServletRequest request, ModelMap model, @ModelAttribute("searchVO") SiteSearch search) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + + search.setSiteIdx(loginSite.getSiteIdx()); + + return "admin/apiLogdev"; + + } + + @GetMapping("/apiIntro") + public String devIntro( HttpServletRequest request, ModelMap model, @ModelAttribute("searchVO") SiteSearch search) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + + search.setSiteIdx(loginSite.getSiteIdx()); + + return "admin/apiIntro"; + + } + + @GetMapping("/apiGame") + public String devGame( HttpServletRequest request, ModelMap model, @ModelAttribute("searchVO") SiteSearch search) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + + search.setSiteIdx(loginSite.getSiteIdx()); + + return "admin/apiGame"; + + } + + @GetMapping("/apiGamelist") + public String devGamelist( HttpServletRequest request, ModelMap model, @ModelAttribute("searchVO") SiteSearch search) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + + search.setSiteIdx(loginSite.getSiteIdx()); + + return "admin/apiGamelist"; + + } + + @GetMapping("/apiPartner") + public String devPartner( HttpServletRequest request, ModelMap model, @ModelAttribute("searchVO") SiteSearch search) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + + search.setSiteIdx(loginSite.getSiteIdx()); + + return "admin/apiPartner"; + + } + + @GetMapping("/apiBetList") + public String devBetlist( HttpServletRequest request, ModelMap model, @ModelAttribute("searchVO") SiteSearch search) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + + + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + model.put("underSiteCredit", underSiteCredit); + model.put("siteCredit", siteCredit); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + + + return "admin/apiBetList"; + + } + + @GetMapping("/apiBetDetail") + public String devBetDe( HttpServletRequest request, ModelMap model, @ModelAttribute("searchVO") SiteSearch search) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + + + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + model.put("underSiteCredit", underSiteCredit); + model.put("siteCredit", siteCredit); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + search.setSiteIdx(loginSite.getSiteIdx()); + + return "admin/apiBetDetail"; + + } + + @GetMapping("/apiBetCallback") + public String devBetCall( HttpServletRequest request, ModelMap model, @ModelAttribute("searchVO") SiteSearch search) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + + search.setSiteIdx(loginSite.getSiteIdx()); + + return "admin/apiBetCallback"; + + } + + + @GetMapping("/apiBetInfo1") + public String devInfo1( HttpServletRequest request, ModelMap model, @ModelAttribute("searchVO") SiteSearch search) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + + search.setSiteIdx(loginSite.getSiteIdx()); + + return "admin/apiBetInfo1"; + + } + + @GetMapping("/apiBetInfo2") + public String devInfo2( HttpServletRequest request, ModelMap model, @ModelAttribute("searchVO") SiteSearch search) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + + search.setSiteIdx(loginSite.getSiteIdx()); + + return "admin/apiBetInfo2"; + + } + + + + @GetMapping({"/apiAuth"}) + public String apiAuth( HttpServletRequest request, ModelMap model, @ModelAttribute("searchVO") SiteSearch search) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + + + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + model.put("underSiteCredit", underSiteCredit); + model.put("siteCredit", siteCredit); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + return "admin/apiAuth"; + + } + + @GetMapping({"/apiPlay"}) + public String apiPlay( HttpServletRequest request, ModelMap model, @ModelAttribute("searchVO") SiteSearch search) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + + + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + model.put("underSiteCredit", underSiteCredit); + model.put("siteCredit", siteCredit); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + return "admin/apiPlay"; + + } + +} diff --git a/src/main/java/com/bb/admin/controller/StatController.java b/src/main/java/com/bb/admin/controller/StatController.java new file mode 100644 index 0000000..f775aa0 --- /dev/null +++ b/src/main/java/com/bb/admin/controller/StatController.java @@ -0,0 +1,339 @@ +package com.bb.admin.controller; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.List; + +import jakarta.servlet.http.HttpServletRequest; + +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.annotation.Secured; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; + +import com.bb.model.PageFormVO; +import com.bb.model.Site; +import com.bb.model.SiteSearch; +import com.bb.service.SiteService; +import com.bb.service.StatService; +import com.bb.util.DateTimeUtils; +import com.bb.util.PagingUtil; +import com.fasterxml.jackson.databind.ObjectMapper; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Controller +@RequestMapping(value = "/stat") +@PreAuthorize("hasRole('ADMIN')") +public class StatController { + + @Autowired + StatService statService; + + @Autowired + SiteService siteService; + + @GetMapping("") + public String loginForm(HttpServletRequest request, ModelMap model, @ModelAttribute("searchVO") SiteSearch search) + throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site) authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + model.put("underSiteCredit", underSiteCredit); + model.put("siteCredit", siteCredit); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + search.setSiteIdx(loginSite.getSiteIdx()); + + System.out.println(search.toString()); + List list = statService.getSiteDailyReportList(search); + model.put("list", list); + + System.out.println(list.size()); + + return "admin/stat"; + } + + @GetMapping("/bottom") + public String index(HttpServletRequest request, ModelMap model, @ModelAttribute("searchVO") SiteSearch search) + throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site) authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + model.put("underSiteCredit", underSiteCredit); + model.put("siteCredit", siteCredit); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + search.setUpperSiteIdx(loginSite.getSiteIdx()); + + List list = statService.getBottomSiteDailyReportList(search); + model.put("list", list); + return "admin/statBottom"; + } + + @GetMapping("/pot") + public String mypage(HttpServletRequest request, ModelMap model, @ModelAttribute("searchVO") SiteSearch search) + throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site) authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + model.put("underSiteCredit", underSiteCredit); + model.put("siteCredit", siteCredit); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + String currDate = DateTimeUtils.getYyyymmdd(); + String yyyy = currDate.substring(0, 4); + search.setSiteIdx(loginSite.getSiteIdx()); + int mm = Integer.parseInt(currDate.substring(4, 6)); + if (search.getStartDate() == null) { + + String mmm = currDate.substring(4, 6); + model.put("yyyy", yyyy); + model.put("mmm", mmm); + search.setStartDate(mmm); + } else { + + String mmm = search.getStartDate(); + model.put("yyyy", yyyy); + model.put("mmm", mmm); + search.setStartDate(mmm); + + } + + // model.put("", yyyy); + model.put("mm", mm); + + HashMap list = statService.getMonthCredit(search); + model.put("list", list); + + return "admin/statPot"; + } + + @GetMapping("/casino") + public String statCasino(HttpServletRequest request, ModelMap model, @ModelAttribute("searchVO") SiteSearch search) + throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site) authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + model.put("underSiteCredit", underSiteCredit); + model.put("siteCredit", siteCredit); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + search.setSiteIdx(loginSite.getSiteIdx()); + List list = statService.getVendorDailyReportList(search); + model.put("list", list); + + return "admin/statCasino"; + } + + @GetMapping("/user") + public String statUser(HttpServletRequest request, ModelMap model, @ModelAttribute("searchVO") SiteSearch search) + throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site) authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + model.put("underSiteCredit", underSiteCredit); + model.put("siteCredit", siteCredit); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + search.setSiteIdx(loginSite.getSiteIdx()); + + if (search.getStartDate() == null || "".equals(search.getStartDate())) { + String currDate = DateTimeUtils.getYyyymm(); + search.setStartDate(currDate.substring(0, 4)); + search.setEndDate(currDate.substring(4, 6)); + } + + System.out.println(search.getStartDate()); + List list = statService.getUserDailyReportList(search); + + model.put("list", list); + model.put("list", list); + + return "admin/statUser"; + } + + @GetMapping("/date") + public String statDate(HttpServletRequest request, ModelMap model, @ModelAttribute("searchVO") SiteSearch search) + throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site) authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + model.put("underSiteCredit", underSiteCredit); + model.put("siteCredit", siteCredit); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + search.setSiteIdx(loginSite.getSiteIdx()); + + System.out.println(search.getStartDate()); + List list = statService.getUserReportSum(search); + model.put("list", list); + + return "admin/statDate"; + } + + @GetMapping("/agentReport") + public String agentReport(HttpServletRequest request, ModelMap model, @ModelAttribute("searchVO") SiteSearch search) + throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site) authentication.getDetails(); + + final String LOG_PREFIX = "#-SUPER::agentReport::::"; + + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + model.put("underSiteCredit", underSiteCredit); + model.put("siteCredit", siteCredit); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + search.setSiteIdx(loginSite.getSiteIdx()); + search.setSiteId(loginSite.getSiteId()); + + if(search.getSearchSiteId() != null && !"".equals(search.getSearchSiteId())) { + Site targetSite = siteService.getSiteSimpleDetail(search); + if(targetSite != null) { + search.setSearchSiteIdx(targetSite.getSiteIdx()); + } else { + search.setSearchSiteIdx(0); + } + } else { + search.setSearchSiteIdx(0); + } + + String toDay = new SimpleDateFormat("yyyy-MM-dd").format(new Date(System.currentTimeMillis())); + String startDay = ""; + String endDay = ""; + if(search.getStartDate() == null || "".equals(search.getStartDate())) { + startDay = toDay; + search.setStartDate(startDay); + } else { + startDay = search.getStartDate().substring(0, 10); + } + + if(search.getEndDate() == null || "".equals(search.getEndDate())) { + endDay = toDay; + search.setEndDate(endDay); + } else { + endDay = search.getEndDate().substring(0, 10); + } + + log.info(LOG_PREFIX+ "startDay::"+startDay); + log.info(LOG_PREFIX+ "endDay::"+endDay); + log.info(LOG_PREFIX+ "toDay::"+toDay); + search.setSiteDispYn("N"); + if(startDay.equals(toDay) || endDay.equals(toDay)) { + search.setSiteDispYn("Y"); + } + + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(search); + JSONObject reqObj = new JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + PageFormVO pageVo= new PageFormVO(); + if(loginSite.getSiteLevel() > 0) { + search.setUpperSiteId(loginSite.getSiteId()); + } + + int totalCount = statService.getAgentReportCnt(search); + if (totalCount != 0) { + PageFormVO commonForm = new PageFormVO(); + commonForm.setFunction_name("goPage"); + commonForm.setPage(search.getPage()); + commonForm.setCount_per_page(20); + commonForm.setCount_per_list(30); + commonForm.setTatal_list_count(totalCount); + pageVo = PagingUtil.setPageUtil(commonForm); + search.setLimit(pageVo.getLimit()); + search.setOffset(pageVo.getOffset()); + search.setTatal_list_count(totalCount); + + model.put("pageInfo", pageVo.getPagination()); + } + log.info(LOG_PREFIX+ "search.getStartDate {}", search.getStartDate()); + log.info(LOG_PREFIX+ "search.getEndDate {}", search.getEndDate()); + log.info(LOG_PREFIX+ "search.getSearchSiteIdx {}", search.getSearchSiteIdx()); + log.info(LOG_PREFIX+ "search.getPage {}", search.getPage()); + log.info(LOG_PREFIX+ "search.getLimit {}", search.getLimit()); + log.info(LOG_PREFIX+ "search.getOffset {}", search.getOffset()); + + List siteList = statService.getAgentReportList(search); + model.put("siteList", siteList); + + return "admin/agentReport"; + } + +} diff --git a/src/main/java/com/bb/admin/controller/UserController.java b/src/main/java/com/bb/admin/controller/UserController.java new file mode 100644 index 0000000..fac52b6 --- /dev/null +++ b/src/main/java/com/bb/admin/controller/UserController.java @@ -0,0 +1,273 @@ +package com.bb.admin.controller; + +import java.text.SimpleDateFormat; +import java.util.HashMap; +import java.util.List; + +import jakarta.servlet.http.HttpServletRequest; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.annotation.Secured; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import com.bb.model.PageFormVO; +import com.bb.model.Site; +import com.bb.model.SiteSearch; +import com.bb.model.WithdrewRequest; +import com.bb.service.CreditService; +import com.bb.service.GsoftService; +import com.bb.service.SiteService; +import com.bb.service.TplusService; +import com.bb.util.PagingUtil; + +import lombok.extern.slf4j.Slf4j; +import net.sf.json.JSONObject; + + + +@Slf4j +@Controller +@RequestMapping(value = "user") +@PreAuthorize("hasRole('ADMIN')") +public class UserController { + + @Autowired + SiteService siteService; + + @Autowired + TplusService tplusService; + + @Autowired + GsoftService gsoftService; + + @Autowired + CreditService creditService; + + @GetMapping("") + public String loginForm( HttpServletRequest request, ModelMap model , @ModelAttribute("searchVO") SiteSearch search) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + model.put("underSiteCredit", 0); + model.put("siteCredit",siteCredit); + model.put("sitePoint", 0); + model.put("creditWait", 0); + model.put("insureAmt", 0); + model.put("insurePointAmt", 0); + + PageFormVO pageVo= new PageFormVO(); + log.info("#-SUPER::USER_DETAIL::Search : "+search.toString()); + + int totalCount = siteService.getSiteUserListCnt(search); + if (totalCount != 0) { + PageFormVO commonForm = new PageFormVO(); + commonForm.setFunction_name("goPage"); + commonForm.setPage(search.getPage()); + commonForm.setCount_per_page(20); + if(search.getCount_per_list()==0) { + commonForm.setCount_per_list(100); + } else { + commonForm.setCount_per_list(search.getCount_per_list()); + } + commonForm.setTatal_list_count(totalCount); + pageVo = PagingUtil.setPageUtil(commonForm); + search.setLimit(pageVo.getLimit()); + search.setOffset(pageVo.getOffset()); + search.setTatal_list_count(totalCount); + + model.put("pageInfo", pageVo.getPagination()); + } + + List list = siteService.getSiteUserList(search); + model.put("list", list); + + return "admin/user"; + } + + + @GetMapping("/parseOnOff") + public @ResponseBody JSONObject parseOnOff(HttpServletRequest request, ModelMap model, @RequestParam("memberIdx") String memberIdx, @RequestParam("pStatus") String pStatus) throws Exception { + JSONObject obj = new JSONObject(); + + final String LOG_PREFIX = "#-Proc::Evo::parseOnOff:::"; + HashMap param = new HashMap<>(); + param.put("memberIdx", memberIdx); + param.put("parseEvoYn", pStatus); + log.info(LOG_PREFIX + "전체 사이트 파싱설정::" + param.toString() + "::START"); + + int result = siteService.updateParseEvoYn(param); + log.info(LOG_PREFIX + "updateParseEvoYn result::" + result + "::END"); + + obj.put("RES", "SUCCESS"); + + return obj; + } + + + @GetMapping("/betlist") + public String index( HttpServletRequest request, ModelMap model , @ModelAttribute("searchVO") SiteSearch search) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + model.put("underSiteCredit", underSiteCredit); + model.put("siteCredit", siteCredit); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + + + PageFormVO pageVo= new PageFormVO(); + search.setSiteId(loginSite.getSiteId()); + search.setSiteIdx(loginSite.getSiteIdx()); + + + int totalCount = creditService.getSiteBetListCnt(search); + if (totalCount != 0) { + PageFormVO commonForm = new PageFormVO(); + commonForm.setFunction_name("goPage"); + commonForm.setPage(search.getPage()); + commonForm.setCount_per_page(20); + if(search.getCount_per_list()==0) { + commonForm.setCount_per_list(15); + } else { + commonForm.setCount_per_list(search.getCount_per_list()); + } + commonForm.setTatal_list_count(totalCount); + pageVo = PagingUtil.setPageUtil(commonForm); + search.setLimit(pageVo.getLimit()); + search.setOffset(pageVo.getOffset()); + search.setTatal_list_count(totalCount); + + model.put("pageInfo", pageVo.getPagination()); + } + + + List list = creditService.getSiteBetList(search); + log.debug(""+list.size()); + model.put("list", list); + + + return "admin/betlist"; + } + + + @GetMapping("/transaction") + public String mypage( HttpServletRequest request, ModelMap model ) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + model.put("underSiteCredit", underSiteCredit); + model.put("siteCredit", siteCredit); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + + + return "admin/transactionList"; + } + + + @GetMapping("/payments") + public String limit( HttpServletRequest request, ModelMap model ) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + model.put("underSiteCredit", underSiteCredit); + model.put("siteCredit", siteCredit); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + + + return "admin/payments"; + } + + + @GetMapping("/std") + public String std ( HttpServletRequest request, ModelMap model , @ModelAttribute("searchVO") SiteSearch search) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + model.put("underSiteCredit", underSiteCredit); + model.put("siteCredit", siteCredit); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + search.setSiteIdx(loginSite.getSiteIdx()); + + List venderAcountList = siteService.getTrasferVendorList(); + + + for(HashMap vendor : venderAcountList) { + String balance ="0"; + vendor.put("balance", balance); + } + + model.put("list", venderAcountList); + + return "admin/std"; + } + + + @PostMapping("/withdrawAll") + public synchronized @ResponseBody JSONObject withdrawAll(HttpServletRequest request, ModelMap model, WithdrewRequest withdrewRequest) throws Exception { + log.warn( " member withdrawAll 시작" + withdrewRequest.toString() ); + JSONObject obj = new JSONObject(); + + List allMemberList = siteService.getAllMember2(); + for(HashMap member:allMemberList) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + long reqAtL = System.currentTimeMillis(); + String reqAt = sdf.format(reqAtL); + } + + log.info( " member betCheck 끝" ); + obj.put("RES", "SUCCESS"); + return obj; + } + + +} diff --git a/src/main/java/com/bb/api/ApiAgentController.java b/src/main/java/com/bb/api/ApiAgentController.java new file mode 100644 index 0000000..909a82c --- /dev/null +++ b/src/main/java/com/bb/api/ApiAgentController.java @@ -0,0 +1,1273 @@ +package com.bb.api; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.reactive.function.client.WebClient; + +import com.bb.jwt.JwtManager; +import com.bb.model.ApiResponse; +import com.bb.model.CommonParamAdmin; +import com.bb.model.PageFormVO; +import com.bb.model.Site; +import com.bb.model.SitePwdVO; +import com.bb.model.SiteSearch; +import com.bb.model.Vendor; +import com.bb.service.CreditService; +import com.bb.service.SiteService; +import com.bb.service.StatService; +import com.bb.util.IPKit; +import com.bb.util.PagingUtil; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import net.sf.json.JSONObject; + + + +@Slf4j +@Controller +@RequiredArgsConstructor +@RequestMapping(value = "/api/v1/agent") +public class ApiAgentController { + + + @Autowired + SiteService siteService; + + @Autowired + StatService statService; + + @Autowired + CreditService creditService; + + @Autowired + private final JwtManager jwtManager; + + @Autowired + private WebClient webClient; // 싱글톤 WebClient 주입 + + @ResponseBody + @PostMapping("/list") + public ApiResponse list( @RequestHeader String token, HttpServletRequest request, @RequestBody SiteSearch search) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp() == null || "".equals(site.getSiteIp()) || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0 ) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + apiResponse.setResultMessage("access denied IP"); + return apiResponse; + } + + // TO DO 토큰체크 + Map data = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::AGENT::list::"+tokenInfo.getSid()+"::::"; + + // POJO to JSON + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(search); + org.codehaus.jettison.json.JSONObject reqObj = new org.codehaus.jettison.json.JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + // 여기서 부터 로직 + PageFormVO pageVo= new PageFormVO(); + if(search.getUpperSiteId() == null || search.getUpperSiteId().equals("")) { + search.setUpperSiteId(tokenInfo.getSid()); + } + + search.setTopId(tokenInfo.getSid()); + + //아이디 + log.info(LOG_PREFIX+ "SiteSearch::"+search.toString()); + + int totalCount = siteService.getSiteListCntForApi(search); + if (totalCount != 0) { + PageFormVO commonForm = new PageFormVO(); + commonForm.setFunction_name("goPage"); + commonForm.setPage(search.getPage()); + commonForm.setCount_per_page(20); + if(search.getCount_per_list()==0) { + commonForm.setCount_per_list(10); + } else { + commonForm.setCount_per_list(search.getCount_per_list()); + } + commonForm.setTatal_list_count(totalCount); + pageVo = PagingUtil.setPageUtil(commonForm); + search.setLimit(pageVo.getLimit()); + search.setOffset(pageVo.getOffset()); + search.setTatal_list_count(totalCount); + + data.put("pageInfo", pageVo); + } + + List siteList = siteService.getSiteListForApi(search); + data.put("siteList", siteList); + + List downSiteList = siteService.getMyDownSite(search); + data.put("downSiteList", downSiteList); + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(data); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + @ResponseBody + @GetMapping("/detail/{siteIdx}") + public ApiResponse detail( @RequestHeader String token, HttpServletRequest request, @PathVariable long siteIdx ) throws Exception { + + ApiResponse apiResponse = new ApiResponse(); + try { + log.info(token.toString()); + Site site = siteService.getSiteInfoAPI(request); + + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + + if( !( site.getSiteIp() == null || "".equals(site.getSiteIp()) || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0 ) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + apiResponse.setResultMessage("access denied IP"); + return apiResponse; + } + // TO DO 토큰체크 + Map data = new HashMap(); + + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + + log.info(tokenInfo.getSid()); + // 여기서 부터 로직 + SiteSearch search = new SiteSearch(); + log.info("siteIdx {}" , site.getSiteIdx()); + search.setUpperSiteId(""+site.getSiteId()); + + search.setSiteIdx(siteIdx); + search.setTopId(tokenInfo.getSid()); + + Site targetSite = siteService.getSiteDetailForApi(search); + data.put("targetSite", targetSite); + data.put("uppersiteIdx", site.getSiteIdx()); + + boolean isMyAgent = false; + List treeInfo = targetSite.getTreeInfo(); + for(HashMap item : treeInfo) { + if(tokenInfo.getSid().equals(item.get("upperSiteId").toString())) { + isMyAgent = true; + } + } + if(!isMyAgent) { + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + HashMap creditInfo = siteService.getCreditInfo(targetSite.getSiteId()); + data.put("creditInfo", creditInfo); + + List vederRateList = siteService.getVenderRateList(targetSite); + List vendorlist = siteService.getVendorListForApi(search); + SiteSearch mySearch = new SiteSearch(); + mySearch.setSiteIdx(site.getSiteIdx()); + List myVendorlist = siteService.getVendorListForApi(mySearch); + + data.put("vederRateList", vederRateList); + data.put("vendorlist", vendorlist); + data.put("myVendorlist", myVendorlist); + log.info("vederRateList {}", vederRateList.size()); + log.info("vederRateList {}", vederRateList); + + // TODO : 에이전트 상세 베팅통계 데이터 + + HashMap ydayBetInfo = statService.getYdayBetInfoBySite(targetSite); + log.info("ydayBetInfo {}", ydayBetInfo); + HashMap monthBetInfo = statService.getMonthBetInfoBySite(targetSite); + log.info("monthBetInfo {}", monthBetInfo); + data.put("ydayBetInfo", ydayBetInfo); // 어제 배팅통계 + data.put("monthBetInfo", monthBetInfo); // 이번달 배팅통계 + + + }catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + + apiResponse.setData(data); + apiResponse.success(); + + } catch (Exception e) { + + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + + } + + @ResponseBody + @GetMapping("/myInfo") + public ApiResponse myInfo( @RequestHeader String token, HttpServletRequest request) throws Exception { + + ApiResponse apiResponse = new ApiResponse(); + try { + log.info(token.toString()); + Site site = siteService.getSiteInfoAPI(request); + + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + + if( !( site.getSiteIp() == null || "".equals(site.getSiteIp()) || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0 ) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + apiResponse.setResultMessage("access denied IP"); + return apiResponse; + } + // TO DO 토큰체크 + Map data = new HashMap(); + + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + + log.info(tokenInfo.getSid()); + // 여기서 부터 로직 + SiteSearch search = new SiteSearch(); + log.info("siteIdx {}" , site.getSiteIdx()); + + + search.setSiteIdx(site.getSiteIdx()); + search.setTopId(tokenInfo.getSid()); + + Site targetSite = siteService.getSiteDetailForApi(search); + data.put("targetSite", targetSite); + data.put("uppersiteIdx", site.getSiteIdx()); + + HashMap creditInfo = siteService.getCreditInfo(targetSite.getSiteId()); + data.put("creditInfo", creditInfo); + + List vederRateList = siteService.getVenderRateList(targetSite); + List vendorlist = siteService.getVendorListForApi(search); + SiteSearch mySearch = new SiteSearch(); + mySearch.setSiteIdx(site.getSiteIdx()); + List myVendorlist = siteService.getVendorListForApi(mySearch); + + data.put("vederRateList", vederRateList); + data.put("vendorlist", vendorlist); + data.put("myVendorlist", myVendorlist); + log.info("vederRateList {}", vederRateList.size()); + log.info("vederRateList {}", vederRateList); + + // TODO : 에이전트 상세 베팅통계 데이터 + HashMap ydayBetInfo = statService.getYdayBetInfoBySite(targetSite); + HashMap monthBetInfo = statService.getMonthBetInfoBySite(targetSite); + data.put("ydayBetInfo", ydayBetInfo); // 어제 배팅통계 + data.put("monthBetInfo", monthBetInfo); // 이번달 배팅통계 + + + }catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + + apiResponse.setData(data); + apiResponse.success(); + + } catch (Exception e) { + + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + + } + + + + @ResponseBody + @GetMapping("/tree") + public ApiResponse tree( @RequestHeader String token, HttpServletRequest request ) throws Exception { + + ApiResponse apiResponse = new ApiResponse(); + try { + log.info(token.toString()); + Site site = siteService.getSiteInfoAPI(request); + + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + + if( !( site.getSiteIp() == null || "".equals(site.getSiteIp()) || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0 ) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + apiResponse.setResultMessage("access denied IP"); + return apiResponse; + } + // TO DO 토큰체크 + Map data = new HashMap(); + + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + + log.info(tokenInfo.getSid()); + + // 하위 사이트 여부체크 + Map checkDown = new HashMap(); + checkDown.put("me", site.getSiteId()); + checkDown.put("target", site.getSiteId()); + int downCnt = siteService.checkDownSite(checkDown); + if(downCnt ==0) { + apiResponse.setResultCode("99993"); + apiResponse.setResultMessage("agent is not valid"); + return apiResponse; + } + List treeList = siteService.getSiteTreeList(site.getSiteId()); + data.put("list", treeList); + + }catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + + apiResponse.setData(data); + apiResponse.success(); + + } catch (Exception e) { + + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + + } + + + @ResponseBody + @GetMapping("/tree/{siteId}") + public ApiResponse tree( @RequestHeader String token, HttpServletRequest request, @PathVariable String siteId ) throws Exception { + + ApiResponse apiResponse = new ApiResponse(); + try { + log.info(token.toString()); + Site site = siteService.getSiteInfoAPI(request); + + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + + if( !( site.getSiteIp() == null || "".equals(site.getSiteIp()) || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0 ) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + apiResponse.setResultMessage("access denied IP"); + return apiResponse; + } + // TO DO 토큰체크 + Map data = new HashMap(); + + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + + log.info(tokenInfo.getSid()); + + // 하위 사이트 여부체크 + Map checkDown = new HashMap(); + checkDown.put("me", site.getSiteId()); + checkDown.put("target", siteId); + int downCnt = siteService.checkDownSite(checkDown); + if(downCnt ==0) { + apiResponse.setResultCode("99993"); + apiResponse.setResultMessage("agent is not valid"); + return apiResponse; + } + List treeList = siteService.getSiteTreeList(siteId); + data.put("list", treeList); + + }catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + + apiResponse.setData(data); + apiResponse.success(); + + } catch (Exception e) { + + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + + } + + + @ResponseBody + @RequestMapping("/update") + public ApiResponse siteUpdate( @RequestHeader String token, HttpServletRequest request, ModelMap model, @RequestBody Site targetsite) throws Exception { + + ApiResponse apiResponse = new ApiResponse(); + try { + log.info(token.toString()); + Site site = siteService.getSiteInfoAPI(request); + + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + + if( !( site.getSiteIp() == null || "".equals(site.getSiteIp()) || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0 ) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + apiResponse.setResultMessage("access denied IP"); + return apiResponse; + } + // TO DO 토큰체크 + Map data = new HashMap(); + + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + + log.info(tokenInfo.getSid()); + // 여기서 부터 로직 + + targetsite.setUpperSiteId(site.getSiteId()); + targetsite.setUpperSiteIdx(site.getSiteIdx()); + targetsite.setSiteId(targetsite.getSiteId()); + + int myDownSiteCheck = siteService.getMyDownSiteCheck(targetsite); + if(myDownSiteCheck >0) { + apiResponse.setResultCode("10009"); + apiResponse.setResultMessage("not your bottom sites"); + return apiResponse; + } + siteService.siteUpdateForAPI(targetsite) ; + + + }catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + + apiResponse.setData(data); + apiResponse.success(); + + } catch (Exception e) { + + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + + + } + + + @ResponseBody + @RequestMapping("/updateSitePwd") + public ApiResponse updateSitePwd(HttpServletRequest request, @RequestHeader String token, @RequestBody SitePwdVO sitePwdVO) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::Agent::updateSitePwd::"+tokenInfo.getSid()+"::::"; + sitePwdVO.setSiteId(tokenInfo.getSid()); + + // 여기서 부터 로직 + log.info(LOG_PREFIX + "SitePwdVO::"+sitePwdVO); + + int result = siteService.updateSitePwd(sitePwdVO); + log.info(LOG_PREFIX + "updateSitePwd result::"+result); + + if(result > 0) { + log.info(LOG_PREFIX + "Site password update succ"); + apiResponse.success(); + } else { + log.error(LOG_PREFIX + "Site password update fail"); + apiResponse.fail(); + } + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @RequestMapping("/add") + public ApiResponse add(@RequestHeader String token, HttpServletRequest request, ModelMap model, @RequestBody Site addsite) throws Exception { + + ApiResponse apiResponse = new ApiResponse(); + try { + log.info(token.toString()); + Site site = siteService.getSiteInfoAPI(request); + + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + + if( !( site.getSiteIp() == null || "".equals(site.getSiteIp()) || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0 ) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + apiResponse.setResultMessage("access denied IP"); + return apiResponse; + } + // TO DO 토큰체크 + Map data = new HashMap(); + + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::AGENT_ADD::"+tokenInfo.getSid()+"::"; + + // POJO to JSON + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(addsite); + org.codehaus.jettison.json.JSONObject reqObj = new org.codehaus.jettison.json.JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + log.info(tokenInfo.getSid()); + // 하부사이트 체크 + Site targetsite = new Site(); + targetsite.setUpperSiteId(site.getSiteId()); + targetsite.setUpperSiteIdx(site.getSiteIdx()); + targetsite.setSiteId(addsite.getUpperSiteId()); + + if(addsite.getIsTransfer() == null || "".equals(addsite.getIsTransfer())) { + addsite.setIsTransfer("N"); + } + + int myDownSiteCheck = siteService.getMyDownSiteCheck(targetsite); + if(myDownSiteCheck >0) { + apiResponse.setResultCode("10009"); + apiResponse.setResultMessage("not your bottom sites"); + return apiResponse; + } + + + addsite.setUpperSiteId(addsite.getUpperSiteId()); + addsite.setUpperSiteIdx(addsite.getUpperSiteIdx()); + addsite.setSiteKey(makeApiKey(addsite.getSiteId())); + log.info(LOG_PREFIX+ "addsite {}", addsite); + + Site dupSite = siteService.getSite(addsite); + + log.info(LOG_PREFIX+ "dupSite []", dupSite); + if(dupSite!=null) { + apiResponse.setResultCode("99990"); + apiResponse.setResultMessage("already siteId"); + return apiResponse; + + } else { + + Site upperSite = new Site(); + upperSite.setSiteId(addsite.getUpperSiteId()); + upperSite = siteService.getSite(upperSite); + + addsite.setSiteLevel(upperSite.getSiteLevel()+1); + siteService.addProcAPI(addsite); + } + + } catch(Exception e) { + log.error("#-API::AGENT_ADD::"+ e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + + apiResponse.setData(data); + apiResponse.success(); + + } catch (Exception e) { + + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + + + } + + /** + * 외부 API 호출 공통 프라이빗 메서드 (중복 코드 방지용) + */ + private void sendExternalRateChange(String url, String siteKey, String vendorName, Object vendorIdx, Object rate) { + try { + log.info("##### WebClient External Call Start ##### URL: {}", url); + + JSONObject paramBody = new JSONObject(); + paramBody.put("siteApiKey", siteKey); + paramBody.put("vendor", vendorName); + paramBody.put("vendorIdx", vendorIdx); + paramBody.put("gameRate", rate); + + String response = webClient.post() + .uri(url) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .header("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36") + .bodyValue(paramBody.toString()) + .retrieve() + .bodyToMono(String.class) + .block(); // 동기 방식 + + log.info("##### WebClient Response: {}", response); + } catch (Exception e) { + log.error("##### WebClient Call Error: {}", e.getMessage()); + } + } + + @RequestMapping("/creditRateSave") + public @ResponseBody JSONObject creditRateSave(HttpServletRequest request, ModelMap model, CommonParamAdmin commonParamAdmin) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site) authentication.getDetails(); + + Site site = siteService.getSiteInfoAPI(request); + String siteUrl = site.getSiteCbUrl() + "/gameRateChange"; + + JSONObject obj = new JSONObject(); + log.info("#-CREDIT_RATE_SAVE::: CommonParamAdmin: {}", commonParamAdmin.toString()); + + for (int i = 0; i < commonParamAdmin.getParamlist().length; i++) { + JSONObject paramData = commonParamAdmin.getParamlist()[i]; + paramData.put("siteIdx", commonParamAdmin.getParam().get("targetSiteIdx")); + paramData.put("insureUpSiteIdX", loginSite.getSiteIdx()); + + ObjectMapper mapper = new ObjectMapper(); + HashMap paramMap = mapper.readValue(paramData.toString(), new TypeReference() {}); + + if (paramMap.get("vendorIdx") != null) { + int type = Integer.parseInt(paramMap.get("type").toString()); + if (type == 0) { + siteService.saveVendorRate(paramMap); + } + siteService.saveSvcr(paramMap, 1); // 1로 고정된 비즈니스 로직 유지 + + if (type == 0) { + String siteKey = siteService.getSiteKey(paramMap); + String vendorName = siteService.getVendorTitle(paramMap); + sendExternalRateChange(siteUrl, siteKey, vendorName, paramMap.get("vendorIdx"), paramMap.get("rate")); + } + + if (loginSite.getSiteLevel() < 1) { + siteService.updateVendorUseYn(paramMap); + } + } + } + obj.put("RES", "SUCCESS"); + return obj; + } + + @RequestMapping("/saveSvcr") + public @ResponseBody JSONObject saveSvcr(HttpServletRequest request, ModelMap model, CommonParamAdmin commonParamAdmin) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site) authentication.getDetails(); + + JSONObject obj = new JSONObject(); + ObjectMapper mapper = new ObjectMapper(); + HashMap paramMap = mapper.readValue(commonParamAdmin.getParam().toString(), new TypeReference() {}); + + String siteUrl = loginSite.getSiteCbUrl() + "/gameRateChange"; + + if (paramMap.get("vendorIdx") != null) { + paramMap.put("siteIdx", commonParamAdmin.getParam().get("targetSiteIdx")); + int type = Integer.parseInt(paramMap.get("type").toString()); + + if (type == 0) { + siteService.saveVendorRate(paramMap); + } + siteService.saveSvcr(paramMap, type); + + if (type == 0) { + String siteKey = siteService.getSiteKey(paramMap); + String vendorName = siteService.getVendorTitle(paramMap); + sendExternalRateChange(siteUrl, siteKey, vendorName, paramMap.get("vendorIdx"), paramMap.get("rate")); + } + + if (loginSite.getSiteLevel() < 1) { + siteService.updateVendorUseYn(paramMap); + } + } + obj.put("RES", "SUCCESS"); + return obj; + } + + @RequestMapping("/saveSvcrAll") + public @ResponseBody JSONObject saveSvcrAll(HttpServletRequest request, ModelMap model, CommonParamAdmin commonParamAdmin) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site) authentication.getDetails(); + + JSONObject obj = new JSONObject(); + String siteUrl = loginSite.getSiteCbUrl() + "/gameRateChange"; + + for (int i = 0; i < commonParamAdmin.getParamlist().length; i++) { + JSONObject paramData = commonParamAdmin.getParamlist()[i]; + paramData.put("siteIdx", commonParamAdmin.getParam().get("targetSiteIdx")); + + ObjectMapper mapper = new ObjectMapper(); + HashMap paramMap = mapper.readValue(paramData.toString(), new TypeReference() {}); + + if (paramMap.get("vendorIdx") != null) { + int type = Integer.parseInt(paramMap.get("type").toString()); + if (type == 0) { + siteService.saveVendorRate(paramMap); + } + siteService.saveSvcr(paramMap, type); + + if (type == 0) { + String siteKey = siteService.getSiteKey(paramMap); + String vendorName = siteService.getVendorTitle(paramMap); + sendExternalRateChange(siteUrl, siteKey, vendorName, paramMap.get("vendorIdx"), paramMap.get("rate")); + } + + if (loginSite.getSiteLevel() < 1) { + siteService.updateVendorUseYn(paramMap); + } + } + } + obj.put("RES", "SUCCESS"); + return obj; + } + + @RequestMapping("/siteVenderUpdate") + public @ResponseBody JSONObject siteVenderUpdate(HttpServletRequest request, ModelMap model, Vendor vendor) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site) authentication.getDetails(); + + Site site = siteService.getSiteInfoAPI(request); + String siteUrl = site.getSiteCbUrl() + "/gameRateChange"; + + JSONObject obj = new JSONObject(); + vendor.setSiteIdx(loginSite.getSiteIdx()); + + try { + siteService.siteVenderUpdate(vendor); + + String siteKey = loginSite.getSiteKey(); + String vendorName = vendor.getVendorCode(); + + // 벤더 이름 가공 로직 + if (vendorName.startsWith("gsoft_")) vendorName = "gsoft"; + if (vendorName.startsWith("trump_")) vendorName = "trump"; + if (vendorName.startsWith("ppk_")) vendorName = "ppk"; + if (vendorName.startsWith("sg_")) vendorName = "sg"; + + String venderRate = siteService.siteVenderRate(vendor); + + // 공통 메서드 호출 + sendExternalRateChange(siteUrl, siteKey, vendorName, vendor.getVendorIdx(), venderRate); + + obj.put("RES", "SUCCESS"); + } catch (Exception e) { + log.error("#-SITE_VENDOR_UPDATE Error: {}", e.toString()); + obj.put("RES", "FAIL"); + } + return obj; + } + + @RequestMapping("/insurePoinRateSave") + public @ResponseBody JSONObject insurePointRateSave( HttpServletRequest request, ModelMap model, CommonParamAdmin commonParamAdmin ) throws Exception { + + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + + + + + JSONObject obj = new JSONObject(); + log.info(commonParamAdmin.toString()); + + for(int i=0;i() {}); + + siteService.saveVendorInsurePointRate(paramMap); + } + + + + + + + obj.put("RES", "SUCCESS"); + + return obj; + } + + + @RequestMapping("/addProc") + public @ResponseBody JSONObject addProc( HttpServletRequest request, ModelMap model, Site site) throws Exception { + + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + site.setUpperSiteId(loginSite.getSiteId()); + site.setUpperSiteIdx(loginSite.getSiteIdx()); + + + + site.setSiteKey(makeApiKey(site.getSiteId())); + + + JSONObject obj = new JSONObject(); + + log.info(site.toString()); + siteService.addProcAPI(site); + + obj.put("RES", "SUCCESS"); + + return obj; + } + + @GetMapping("/transaction") + public String transaction( HttpServletRequest request , ModelMap model , @ModelAttribute("searchVO") SiteSearch search) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + model.put("siteCredit", siteCredit); + model.put("underSiteCredit", underSiteCredit); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + + String nowtime = new SimpleDateFormat("yyyy-MM-dd").format(new Date(System.currentTimeMillis())); + if(search.getStartDate() == null || "".equals(search.getStartDate())) { + search.setStartDate(nowtime); + } + + if(search.getEndDate() == null || "".equals(search.getEndDate())) { + search.setEndDate(nowtime); + } + + if(search.getSearchSiteId() == null || "".equals(search.getSearchSiteId())) { + search.setSearchSiteId(loginSite.getSiteId()); + } + + + PageFormVO pageVo= new PageFormVO(); + search.setSiteId(loginSite.getSiteId()); + search.setSiteIdx(loginSite.getSiteIdx()); + + + int totalCount = creditService.getSiteTranListCnt(search); + if (totalCount != 0) { + PageFormVO commonForm = new PageFormVO(); + commonForm.setFunction_name("goPage"); + commonForm.setPage(search.getPage()); + commonForm.setCount_per_page(20); + if(search.getCount_per_list()==0) { + commonForm.setCount_per_list(30); + } else { + commonForm.setCount_per_list(search.getCount_per_list()); + } + commonForm.setTatal_list_count(totalCount); + pageVo = PagingUtil.setPageUtil(commonForm); + search.setLimit(pageVo.getLimit()); + search.setOffset(pageVo.getOffset()); + search.setTatal_list_count(totalCount); + + model.put("pageInfo", pageVo); + } + + + List list = creditService.getSiteTranList(search); + log.debug(""+list.size()); + model.put("list", list); + + List downSiteList = siteService.getMyDownSite(search); + model.put("downSiteList", downSiteList); + + + return "admin/transaction"; + } + + + @GetMapping("/gamelink") + public String gamelink( HttpServletRequest request , ModelMap model, @ModelAttribute("searchVO") SiteSearch search) throws Exception { + + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + model.put("siteCredit", siteCredit); + model.put("underSiteCredit", underSiteCredit); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + search.setSiteIdx(loginSite.getSiteIdx()); + List mylist = siteService.getSiteVendorListForApi(search); + + + List vendorlist = siteService.getVendorListForApi(search); + + model.put("mylist", mylist); + model.put("vendorlist", vendorlist); + + return "admin/gamelink"; + } + + @GetMapping("/venderset") + public String venderset( HttpServletRequest request , ModelMap model, @ModelAttribute("searchVO") SiteSearch search) throws Exception { + + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + model.put("siteCredit", siteCredit); + model.put("underSiteCredit", underSiteCredit); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + search.setSiteIdx(loginSite.getSiteIdx()); + List mylist = siteService.getSiteVendorListForApi(search); + + + List vendorlist = siteService.getVendorListForApi(search); + + model.put("mylist", mylist); + model.put("vendorlist", vendorlist); + + return "admin/venderset"; + } + + @GetMapping("/gameCompanySet") + public String gameCompanySet( HttpServletRequest request , ModelMap model, @ModelAttribute("searchVO") SiteSearch search) throws Exception { + + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + model.put("siteCredit", siteCredit); + model.put("underSiteCredit", underSiteCredit); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + search.setSiteIdx(loginSite.getSiteIdx()); + List mylist = siteService.getSiteVendorListForApi(search); + + + List vendorlist = siteService.getVendorListForApi(search); + + model.put("mylist", mylist); + model.put("vendorlist", vendorlist); + + return "admin/gameCompanySet"; + } + + @GetMapping("/gameSet") + public String gameSet( HttpServletRequest request , ModelMap model, @ModelAttribute("searchVO") SiteSearch search) throws Exception { + + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + model.put("siteCredit", siteCredit); + model.put("underSiteCredit", underSiteCredit); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + search.setSiteIdx(loginSite.getSiteIdx()); + List mylist = siteService.getSiteVendorListForApi(search); + + + List vendorlist = siteService.getVendorListForApi(search); + + model.put("mylist", mylist); + model.put("vendorlist", vendorlist); + + return "admin/gameSet"; + } + + + + @GetMapping("/betlimit") + public String betlimit( HttpServletRequest request , ModelMap model, @ModelAttribute("searchVO") SiteSearch search) throws Exception { + + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + model.put("siteCredit", siteCredit); + model.put("underSiteCredit", underSiteCredit); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + search.setSiteIdx(loginSite.getSiteIdx()); + List mylist = siteService.getSiteVendorListForApi(search); + + search.setSearchType("union"); + search.setSiteIdx(loginSite.getSiteIdx()); + List vendorMaplist = siteService.getVendorMapList(search); + + model.put("mylist", mylist); + model.put("vendorlist", vendorMaplist); + + return "admin/betlimit"; + } + + @RequestMapping("/betlimitUpdate") + public @ResponseBody JSONObject betlimitUpdate( HttpServletRequest request, ModelMap model, Vendor vendor) throws Exception { + + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + + JSONObject obj = new JSONObject(); + + vendor.setSiteIdx(loginSite.getSiteIdx()); + try { + siteService.siteVenderLobbyUpdate(vendor); + + obj.put("RES", "SUCCESS"); + }catch(Exception e) { + System.out.print(e.toString()); + obj.put("RES", "FAIL"); + } + return obj; + } + + @GetMapping("/gamemanage") + public String gameManage( HttpServletRequest request , ModelMap model, @ModelAttribute("searchVO") SiteSearch search) throws Exception { + + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + model.put("loginSite", loginSite); + long siteCredit = siteService.getSiteCredit(loginSite.getSiteId()); + long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId()); + long sitePoint = siteService.getSitePoint(loginSite.getSiteId()); + model.put("sitePoint", sitePoint); + model.put("siteCredit", siteCredit); + model.put("underSiteCredit", underSiteCredit); + HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx()); + model.put("creditWait", creditWait); + + long insureAmt = siteService.getInsureAmt(loginSite.getSiteId()); + long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId()); + model.put("insureAmt", insureAmt); + model.put("insurePointAmt", insurePointAmt); + + search.setSiteIdx(loginSite.getSiteIdx()); + List mylist = siteService.getSiteVendorListForApi(search); + + + List vendorlist = siteService.getVendorListForApi(search); + + model.put("mylist", mylist); + model.put("vendorlist", vendorlist); + + return "admin/gameManage"; + } + + + @RequestMapping("/getMyDownSite") + public @ResponseBody JSONObject getMyDownSite( HttpServletRequest request, ModelMap model, SiteSearch search) throws Exception { + + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Site loginSite = (Site)authentication.getDetails(); + + JSONObject obj = new JSONObject(); + search.setSiteId(loginSite.getSiteId()); + + try { + List downSiteList = siteService.getMyDownSite(search); + obj.put("downSiteList", downSiteList); + obj.put("RES", "SUCCESS"); + }catch(Exception e) { + obj.put("RES", "FAIL"); + } + return obj; + } + + + + + + + + + private String makeApiKey(String param) { + + int n = 24; // n자리 쿠폰 + char[] chs = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' ,'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; + + + Random rd = new Random(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < n; i++) { + char ch = chs[rd.nextInt(chs.length)]; + sb.append(ch); + } + return sb.toString(); + + + } + + +} diff --git a/src/main/java/com/bb/api/ApiBlockGameController.java b/src/main/java/com/bb/api/ApiBlockGameController.java new file mode 100644 index 0000000..fd2575c --- /dev/null +++ b/src/main/java/com/bb/api/ApiBlockGameController.java @@ -0,0 +1,734 @@ +package com.bb.api; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import jakarta.servlet.http.HttpServletRequest; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import com.bb.jwt.JwtManager; +import com.bb.model.ApiResponse; +import com.bb.model.BlockGameVO; +import com.bb.model.CmnSearch; +import com.bb.model.Game; +import com.bb.model.GameVo; +import com.bb.model.Site; +import com.bb.service.CommonService; +import com.bb.service.SettingService; +import com.bb.service.SiteService; +import com.bb.util.IPKit; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Controller +@RequiredArgsConstructor +@RequestMapping(value = "/api/v1/block") +public class ApiBlockGameController { + + @Autowired + SiteService siteService; + + @Autowired + SettingService settingService; + + @Autowired + CommonService commonService; + + @Autowired + private final JwtManager jwtManager; + + + @ResponseBody + @PostMapping("/vendor-selectbox") + public ApiResponse vendorSelectBox(@RequestHeader String token, HttpServletRequest request) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::BLOCK::vendorSelectBox::"+tokenInfo.getSid()+"::::"; + + // 여기서 부터 로직 + List> list = settingService.getBlockVendorSelectBoxList("CASINO"); + log.info(LOG_PREFIX + "Block-Vendor-SelectBoxList cnt::"+list.size()); + + responseData.put("list", list); + + + } catch(Exception e) { + e.printStackTrace(); + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(responseData); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping("/table-selectbox") + public ApiResponse tableSelectBox(@RequestHeader String token, HttpServletRequest request, @RequestBody CmnSearch search) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::BLOCK::tableSelectBox::"+tokenInfo.getSid()+"::::"; + search.setSiteIdx((long) site.getSiteIdx()); + + // 여기서 부터 로직 + log.info(LOG_PREFIX + "Request Param::"+search); + List> list = settingService.getBlockTableSelectBoxList(search); + log.info(LOG_PREFIX + "Block-Table-SelectBoxList cnt::"+list.size()); + + responseData.put("list", list); + + + } catch(Exception e) { + e.printStackTrace(); + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(responseData); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping("/table-list") + public ApiResponse blockTableList(@RequestHeader String token, HttpServletRequest request, @RequestBody CmnSearch search) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::BLOCK::blockTableList::"+tokenInfo.getSid()+"::::"; + search.setSiteIdx((long) site.getSiteIdx()); + + // 여기서 부터 로직 + log.info(LOG_PREFIX + "Request Param::"+search); + List> list = settingService.getBlockTableSelectBoxList(search); + List> mylist = new ArrayList>(); + String blockTableIds = settingService.getBlockTableIds(search); + if(blockTableIds == null) blockTableIds = ""; + //String[] blockTableArr = blockTableIds.split("|"); + for(HashMap item : list) { + String tableId = item.get("tableId").toString()+"|"; + if(!"".equals(blockTableIds) && blockTableIds.contains(tableId)) { + mylist.add(item); + } + } + + responseData.put("list", mylist); + responseData.put("blockTableIds", blockTableIds); + + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(responseData); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping("/table/save") + public ApiResponse blockGameSave(@RequestHeader String token, HttpServletRequest request, @RequestBody BlockGameVO param) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::BLOCK::blockGameSave::"+tokenInfo.getSid()+"::::"; + param.setSiteIdx((long) site.getSiteIdx()); + + // 여기서 부터 로직 + log.info(LOG_PREFIX + "BF::BlockGameVO::"+param); + CmnSearch search = new CmnSearch(); + search.setSiteIdx(param.getSiteIdx()); + search.setVendorIdx(param.getVendorIdx()); + + String vendorTitle = settingService.getVendorTitle(search); + if(vendorTitle == null || "".equals(vendorTitle)) { + log.error(LOG_PREFIX+ "VendorTitle is not null or empty"); + apiResponse.setResultCode("99"); + apiResponse.setResultMessage("VendorTitle is not null or empty"); + return apiResponse; + } + param.setVendorTitle(vendorTitle); + + String blockTableIds = settingService.getBlockTableIds(search); + if(blockTableIds == null) blockTableIds = ""; + log.info(LOG_PREFIX +"BF::blockTableIds::" + blockTableIds); + + if(!"".equals(blockTableIds) && blockTableIds.contains(param.getBlockTableId())) { + log.info(LOG_PREFIX + param.getBlockTableId() + " is already saved"); + } else { + blockTableIds = blockTableIds + param.getBlockTableId() + "|"; + log.info(LOG_PREFIX +"AF::blockTableIds::" + blockTableIds); + param.setBlockTableIds(blockTableIds); + log.info(LOG_PREFIX +"AF::BlockGameVO::" + param); + int saveResult = settingService.blockTableIdSave(param); + log.info(LOG_PREFIX + "blockTableIdSave result::"+saveResult); + } + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping("/table/delete") + public ApiResponse blockGameDelete(@RequestHeader String token, HttpServletRequest request, @RequestBody BlockGameVO param) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::BLOCK::blockGameDelete::"+tokenInfo.getSid()+"::::"; + param.setSiteIdx((long) site.getSiteIdx()); + + // 여기서 부터 로직 + log.info(LOG_PREFIX + "BF::BlockGameVO::"+param); + CmnSearch search = new CmnSearch(); + search.setSiteIdx(param.getSiteIdx()); + search.setVendorIdx(param.getVendorIdx()); + + String vendorTitle = settingService.getVendorTitle(search); + if(vendorTitle == null || "".equals(vendorTitle)) { + log.error(LOG_PREFIX+ "VendorTitle is not null or empty"); + apiResponse.setResultCode("99"); + apiResponse.setResultMessage("VendorTitle is not null or empty"); + return apiResponse; + } + param.setVendorTitle(vendorTitle); + + String blockTableIds = settingService.getBlockTableIds(search); + if(blockTableIds == null) blockTableIds = ""; + log.info(LOG_PREFIX +"BF::blockTableIds::" + blockTableIds); + + if(!"".equals(blockTableIds) && !blockTableIds.contains(param.getBlockTableId())) { + log.info(LOG_PREFIX + param.getBlockTableId() + " is not found"); + } else { + blockTableIds = blockTableIds.replace(param.getBlockTableId() + "|", ""); + log.info(LOG_PREFIX +"AF::blockTableIds::" + blockTableIds); + param.setBlockTableIds(blockTableIds); + log.info(LOG_PREFIX +"AF::BlockGameVO::" + param); + int saveResult = settingService.blockTableIdSave(param); + log.info(LOG_PREFIX + "blockTableIdSave result::"+saveResult); + } + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping("/slotVendors") + public ApiResponse slotVendors(@RequestHeader String token, HttpServletRequest request) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::BLOCK::slotVendors::"+tokenInfo.getSid()+"::::"; + + CmnSearch search = new CmnSearch(); + search.setSiteIdx((long) site.getSiteIdx()); + search.setCategory("SLOT"); + + // 여기서 부터 로직 + List> list = settingService.getBlockVendorSelectBoxList2(search); + + responseData.put("list", list); + + + } catch(Exception e) { + e.printStackTrace(); + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(responseData); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping("/slotGames") + public ApiResponse slotGames(@RequestHeader String token, HttpServletRequest request, @RequestBody CmnSearch search) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::BLOCK::slotGames::"+tokenInfo.getSid()+"::::"; + search.setSiteIdx((long) site.getSiteIdx()); + + // 여기서 부터 로직 + log.info(LOG_PREFIX + "Request Param::"+search); + + HashMap apiInfo = commonService.getVendorApiInfo(search); + log.info(LOG_PREFIX + "API Info::"+apiInfo.toString()); + // -- grand, svendor, tower, tplus + List gameList = null; + if("grand".equals(apiInfo.get("vendorTitle").toString())) { + gameList = commonService.getGrandGameList(LOG_PREFIX, apiInfo); + } else if("svendor".equals(apiInfo.get("vendorTitle").toString())) { + gameList = commonService.getSevenGameList(LOG_PREFIX, apiInfo); + } else if("pink".equals(apiInfo.get("vendorTitle").toString())) { + gameList = commonService.getSevenGameList(LOG_PREFIX, apiInfo); + } else if("tplus".equals(apiInfo.get("vendorTitle").toString())) { + gameList = commonService.getTplusGameList(LOG_PREFIX, apiInfo); + } else if("pracp".equals(apiInfo.get("vendorTitle").toString())) { + gameList = commonService.getPracpGameList(LOG_PREFIX, apiInfo); + } else if("nexus".equals(apiInfo.get("vendorTitle").toString())) { + gameList = commonService.getNexusGameList(LOG_PREFIX, apiInfo); + } else if("ace2".equals(apiInfo.get("vendorTitle").toString())) { + gameList = commonService.getNexusGameList(LOG_PREFIX, apiInfo); + } else if("tower".equals(apiInfo.get("vendorTitle").toString())) { + gameList = commonService.getTowerGameList(LOG_PREFIX, apiInfo); + } else { + log.error(LOG_PREFIX + "Not found vendor company"); + } + + responseData.put("list", gameList); + + } catch(Exception e) { + e.printStackTrace(); + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(responseData); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping("/slot-block/gameList") + public ApiResponse slotBlockGameList(@RequestHeader String token, HttpServletRequest request, @RequestBody CmnSearch search) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::BLOCK::slotGames::"+tokenInfo.getSid()+"::::"; + search.setSiteIdx((long) site.getSiteIdx()); + + // 여기서 부터 로직 + log.info(LOG_PREFIX + "Request Param::"+search); + + HashMap apiInfo = commonService.getVendorApiInfo(search); + log.info(LOG_PREFIX + "API Info::"+apiInfo.toString()); + // -- grand, svendor, tower, tplus + List gameList = null; + if("grand".equals(apiInfo.get("vendorTitle").toString())) { + gameList = commonService.getGrandGameList(LOG_PREFIX, apiInfo); + } else if("svendor".equals(apiInfo.get("vendorTitle").toString())) { + gameList = commonService.getSevenGameList(LOG_PREFIX, apiInfo); + } else if("pink".equals(apiInfo.get("vendorTitle").toString())) { + gameList = commonService.getSevenGameList(LOG_PREFIX, apiInfo); + } else if("tplus".equals(apiInfo.get("vendorTitle").toString())) { + gameList = commonService.getTplusGameList(LOG_PREFIX, apiInfo); + } else if("pracp".equals(apiInfo.get("vendorTitle").toString())) { + gameList = commonService.getPracpGameList(LOG_PREFIX, apiInfo); + } else if("nexus".equals(apiInfo.get("vendorTitle").toString())) { + gameList = commonService.getNexusGameList(LOG_PREFIX, apiInfo); + } else if("ace2".equals(apiInfo.get("vendorTitle").toString())) { + gameList = commonService.getNexusGameList(LOG_PREFIX, apiInfo); + } else if("tower".equals(apiInfo.get("vendorTitle").toString())) { + gameList = commonService.getTowerGameList(LOG_PREFIX, apiInfo); + } else { + log.error(LOG_PREFIX + "Not found vendor company"); + } + + List mylist = new ArrayList<>(); + String blockTableIds = settingService.getBlockTableIds(search); + if(blockTableIds == null) blockTableIds = ""; + //String[] blockTableArr = blockTableIds.split("|"); + for(GameVo item : gameList) { + String tableId = item.getGameId()+"|"; + if(!"".equals(blockTableIds) && blockTableIds.contains(tableId)) { + mylist.add(item); + } + } + + responseData.put("list", mylist); + responseData.put("blockTableIds", blockTableIds); + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(responseData); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping("/slot-block/save") + public ApiResponse SlotBlockSave(@RequestHeader String token, HttpServletRequest request, @RequestBody BlockGameVO param) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::BLOCK::SlotBlockSave::"+tokenInfo.getSid()+"::::"; + param.setSiteIdx((long) site.getSiteIdx()); + + // 여기서 부터 로직 + log.info(LOG_PREFIX + "BF::BlockGameVO::"+param); + CmnSearch search = new CmnSearch(); + search.setSiteIdx(param.getSiteIdx()); + search.setVendorIdx(param.getVendorIdx()); + + String blockTableIds = settingService.getBlockTableIds(search); + if(blockTableIds == null) blockTableIds = ""; + log.info(LOG_PREFIX +"BF::blockTableIds::" + blockTableIds); + + if(!"".equals(blockTableIds) && blockTableIds.contains(param.getBlockTableId())) { + log.info(LOG_PREFIX + param.getBlockTableId() + " is already saved"); + } else { + blockTableIds = blockTableIds + param.getBlockTableId() + "|"; + log.info(LOG_PREFIX +"AF::blockTableIds::" + blockTableIds); + param.setBlockTableIds(blockTableIds); + log.info(LOG_PREFIX +"AF::BlockGameVO::" + param); + int saveResult = settingService.blockTableIdSave(param); + log.info(LOG_PREFIX + "blockTableIdSave result::"+saveResult); + } + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping("/slot-block/delete") + public ApiResponse SlotBlockDelete(@RequestHeader String token, HttpServletRequest request, @RequestBody BlockGameVO param) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::BLOCK::SlotBlockDelete::"+tokenInfo.getSid()+"::::"; + param.setSiteIdx((long) site.getSiteIdx()); + + // 여기서 부터 로직 + log.info(LOG_PREFIX + "BF::BlockGameVO::"+param); + CmnSearch search = new CmnSearch(); + search.setSiteIdx(param.getSiteIdx()); + search.setVendorIdx(param.getVendorIdx()); + + String blockTableIds = settingService.getBlockTableIds(search); + if(blockTableIds == null) blockTableIds = ""; + log.info(LOG_PREFIX +"BF::blockTableIds::" + blockTableIds); + + if(!"".equals(blockTableIds) && !blockTableIds.contains(param.getBlockTableId())) { + log.info(LOG_PREFIX + param.getBlockTableId() + " is not found"); + } else { + blockTableIds = blockTableIds.replace(param.getBlockTableId() + "|", ""); + log.info(LOG_PREFIX +"AF::blockTableIds::" + blockTableIds); + param.setBlockTableIds(blockTableIds); + log.info(LOG_PREFIX +"AF::BlockGameVO::" + param); + int saveResult = settingService.blockTableIdSave(param); + log.info(LOG_PREFIX + "blockTableIdSave result::"+saveResult); + } + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + +} diff --git a/src/main/java/com/bb/api/ApiCallbackSpeedTestController.java b/src/main/java/com/bb/api/ApiCallbackSpeedTestController.java new file mode 100644 index 0000000..75c2adb --- /dev/null +++ b/src/main/java/com/bb/api/ApiCallbackSpeedTestController.java @@ -0,0 +1,301 @@ +package com.bb.api; + +import java.security.SecureRandom; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.Valid; + +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.bb.jwt.JwtManager; +import com.bb.model.ApiResponse; +import com.bb.model.CallbackTestResult; +import com.bb.model.Site; +import com.bb.service.CallBackTestService; +import com.bb.service.SiteService; +import com.bb.util.IPKit; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/api/v1/spdtest") +public class ApiCallbackSpeedTestController { + + @Autowired + SiteService siteService; + + @Autowired + CallBackTestService callBackService; + + @Autowired + private final JwtManager jwtManager; + + private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + private static final SecureRandom random = new SecureRandom(); + + public static List generateRandomStrings(int stringLength, int count) { + Set uniqueStrings = new HashSet<>(); + + while (uniqueStrings.size() < count) { + StringBuilder sb = new StringBuilder(stringLength); + for (int i = 0; i < stringLength; i++) { + sb.append(CHARACTERS.charAt(random.nextInt(CHARACTERS.length()))); + } + + // 시간 기반으로 중복 확률 줄이기 (나노타임 일부 추가) + sb.append(Long.toHexString(System.nanoTime()).substring(0, 4)); + + uniqueStrings.add(sb.toString()); + } + + return new ArrayList<>(uniqueStrings); + } + + + @GetMapping("/testBalance") + public ApiResponse testBalance(HttpServletRequest request, @RequestHeader String token, @Valid @RequestParam String memberId) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + log.error("#-API::SPD_TEST::testBalance::Authorization apiKey check"); + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("#-API::SPD_TEST::testBalance::site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + if(token == null || token.equals("")) { + log.error("#-API::SPD_TEST::testBalance::Authorization apiKey check"); + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization token check"); + return apiResponse; + } + + try { + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::SPD_TEST::testBalance::"+tokenInfo.getSid()+"::"; + + // 여기서 부터 로직 + List resultList = new ArrayList<>(); + + log.info(LOG_PREFIX+ "callBackService.getTestBalance() START--"); + JSONObject responseObj = callBackService.getTestBalance(LOG_PREFIX, memberId, token, request.getHeader("Authorization").toString()); + log.info(LOG_PREFIX+ "callBackService.getTestBalance() END--"); + + JSONObject dataObj = responseObj.getJSONObject("data"); + JSONArray resultArray = dataObj.getJSONArray("resultList"); + for(int i=0; i= 0) ) { + log.error("#-API::SPD_TEST::testCasino::site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + if(token == null || token.equals("")) { + log.error("#-API::SPD_TEST::testCasino::Authorization apiKey check"); + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization token check"); + return apiResponse; + } + + try { + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::SPD_TEST::testCasino::"+tokenInfo.getSid()+"::"; + + // 여기서 부터 로직 + List resultList = new ArrayList<>(); + + log.info(LOG_PREFIX+ "callBackService.getTestChangeBalance() START--"); + JSONObject responseObj = callBackService.getTestChangeBalance(LOG_PREFIX, memberId, token, request.getHeader("Authorization").toString()); + log.info(LOG_PREFIX+ "callBackService.getTestChangeBalance() END--"); + + JSONObject dataObj = responseObj.getJSONObject("data"); + JSONArray resultArray = dataObj.getJSONArray("resultList"); + for(int i=0; i= 0) ) { + log.error("#-API::SPD_TEST::testSlot::site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + if(token == null || token.equals("")) { + log.error("#-API::SPD_TEST::testSlot::Authorization apiKey check"); + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization token check"); + return apiResponse; + } + + try { + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::SPD_TEST::testSlot::"+tokenInfo.getSid()+"::"; + + // 여기서 부터 로직 + List resultList = new ArrayList<>(); + + log.info(LOG_PREFIX+ "callBackService.getTestChangeBalanceSlot() START--"); + JSONObject responseObj = callBackService.getTestChangeBalanceSlot(LOG_PREFIX, memberId, token, request.getHeader("Authorization").toString()); + log.info(LOG_PREFIX+ "callBackService.getTestChangeBalanceSlot() END--"); + + JSONObject dataObj = responseObj.getJSONObject("data"); + JSONArray resultArray = dataObj.getJSONArray("resultList"); + for(int i=0; i= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::CB_TEST::testBalance::"+tokenInfo.getSid()+"::"; + + // 여기서 부터 로직 + List resultList = new ArrayList<>(); + + JSONObject requestBody = new JSONObject(); + requestBody.put("userId", memberId); + JSONObject responseObj = callBackService.getBalance(LOG_PREFIX, site.getSiteCbUrl(), requestBody); + int resultCode = responseObj.getInt("result_code"); + CallbackTestResult result = new CallbackTestResult(); + if(resultCode == 0) { + result.setIndex(1); + result.setStatus("SUCCESS"); + result.setMsg("[balance] 성공"); + } else { + result.setIndex(1); + result.setStatus("FAIL"); + result.setMsg("[balance] 실패"); + } + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + + apiResponse.setData(responseData); + apiResponse.success(); + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @GetMapping("/testBet") + public ApiResponse testBet(HttpServletRequest request, @RequestHeader String token, @Valid @RequestParam String memberId) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::CB_TEST::testBet::"+tokenInfo.getSid()+"::"; + + // 여기서 부터 로직 + List resultList = new ArrayList<>(); + + int balance = 0; + int betAmt = 100; + int winAmt = 200; + + // 2-1 call balance + JSONObject requestBody = new JSONObject(); + requestBody.put("userId", memberId); + JSONObject responseObj = callBackService.getBalance(LOG_PREFIX, site.getSiteCbUrl(), requestBody); + int resultCode = responseObj.getInt("result_code"); + CallbackTestResult result = new CallbackTestResult(); + if(resultCode == 0) { + result.setIndex(1); + result.setStatus("SUCCESS"); + result.setMsg("[balance] 성공"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + balance = responseObj.getInt("balance"); + } else { + result.setIndex(1); + result.setStatus("FAIL"); + result.setMsg("[balance] 실패"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + long ctms = System.currentTimeMillis(); + String betId = "B"+site.getSiteIdx()+ctms+memberId; + String tranId = "D"+site.getSiteIdx()+ctms+memberId; + + // 2-2 call bet + requestBody = new JSONObject(); + requestBody.put("betId", betId); + requestBody.put("tranId", tranId); + requestBody.put("userId", memberId); + requestBody.put("vendorIdx", 1); + requestBody.put("vendorKey", "C01"); + requestBody.put("vendor", "nexus"); + requestBody.put("gameIdx", 1); + requestBody.put("gameKey", "코리안 스피드 바카라 A"); + requestBody.put("gameId", ""); + requestBody.put("tranType", "debit"); + requestBody.put("debit", betAmt); + requestBody.put("credit", 0); + requestBody.put("isCancel", 0); + requestBody.put("isBonus", 0); + requestBody.put("requestAt", sdf.format(System.currentTimeMillis())); + responseObj = callBackService.changeBalance(LOG_PREFIX, site.getSiteCbUrl(), requestBody); + resultCode = responseObj.getInt("result_code"); + result = new CallbackTestResult(); + if(resultCode == 0) { + int balanceAfter = balance - betAmt; + int balanceResult = responseObj.getInt("balance"); + if(balanceAfter == balanceResult) { + result.setIndex(2); + result.setStatus("SUCCESS"); + result.setMsg("[bet] 성공"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + } else { + result.setIndex(2); + result.setStatus("FAIL"); + result.setMsg("[bet] 실패: 잔액이 맞지 않습니다."); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + } else { + result.setIndex(2); + result.setStatus("FAIL"); + result.setMsg("[bet] 실패"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + + // 2-3 call bet 중복 + responseObj = callBackService.changeBalance(LOG_PREFIX, site.getSiteCbUrl(), requestBody); + resultCode = responseObj.getInt("result_code"); + result = new CallbackTestResult(); + if(resultCode == 98) { + int balanceAfter = balance - betAmt; + int balanceResult = responseObj.getInt("balance"); + if(balanceAfter == balanceResult) { + result.setIndex(3); + result.setStatus("SUCCESS"); + result.setMsg("[bet 중복] 성공"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + } else { + result.setIndex(3); + result.setStatus("FAIL"); + result.setMsg("[bet 중복] 실패: 잔액이 맞지 않습니다."); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + } else { + result.setIndex(3); + result.setStatus("FAIL"); + result.setMsg("[bet 중복] 실패: 배팅중복 시 result_code=98 입니다."); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + + // 2-4 call win + tranId = "C"+site.getSiteIdx()+ctms+memberId; + requestBody = new JSONObject(); + requestBody.put("betId", betId); + requestBody.put("tranId", tranId); + requestBody.put("userId", memberId); + requestBody.put("vendorIdx", 1); + requestBody.put("vendorKey", "C01"); + requestBody.put("vendor", "nexus"); + requestBody.put("gameIdx", 1); + requestBody.put("gameKey", "코리안 스피드 바카라 A"); + requestBody.put("gameId", ""); + requestBody.put("tranType", "credit"); + requestBody.put("debit", 0); + requestBody.put("credit", winAmt); + requestBody.put("isCancel", 0); + requestBody.put("isBonus", 0); + requestBody.put("requestAt", sdf.format(System.currentTimeMillis())); + responseObj = callBackService.changeBalance(LOG_PREFIX, site.getSiteCbUrl(), requestBody); + resultCode = responseObj.getInt("result_code"); + result = new CallbackTestResult(); + if(resultCode == 0) { + int balanceAfter = balance - betAmt + winAmt; + int balanceResult = responseObj.getInt("balance"); + if(balanceAfter == balanceResult) { + result.setIndex(4); + result.setStatus("SUCCESS"); + result.setMsg("[win] 성공"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + } else { + result.setIndex(4); + result.setStatus("FAIL"); + result.setMsg("[win] 실패: 잔액이 맞지 않습니다."); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + } else { + result.setIndex(4); + result.setStatus("FAIL"); + result.setMsg("[win] 실패"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @GetMapping("/testBetOver") + public ApiResponse testBetOver(HttpServletRequest request, @RequestHeader String token, @Valid @RequestParam String memberId) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::CB_TEST::testBetOver::"+tokenInfo.getSid()+"::"; + + // 여기서 부터 로직 + List resultList = new ArrayList<>(); + + int balance = 0; + + // 3-1 call balance + JSONObject requestBody = new JSONObject(); + requestBody.put("userId", memberId); + JSONObject responseObj = callBackService.getBalance(LOG_PREFIX, site.getSiteCbUrl(), requestBody); + int resultCode = responseObj.getInt("result_code"); + CallbackTestResult result = new CallbackTestResult(); + if(resultCode == 0) { + result.setIndex(1); + result.setStatus("SUCCESS"); + result.setMsg("[balance] 성공"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + balance = responseObj.getInt("balance"); + } else { + result.setIndex(1); + result.setStatus("FAIL"); + result.setMsg("[balance] 실패"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + long ctms = System.currentTimeMillis(); + String betId = "B"+site.getSiteIdx()+ctms+memberId; + String tranId = "D"+site.getSiteIdx()+ctms+memberId; + + + int betAmt = balance + 100; + // 3-2 call bet + requestBody = new JSONObject(); + requestBody.put("betId", betId); + requestBody.put("tranId", tranId); + requestBody.put("userId", memberId); + requestBody.put("vendorIdx", 1); + requestBody.put("vendorKey", "C01"); + requestBody.put("vendor", "nexus"); + requestBody.put("gameIdx", 1); + requestBody.put("gameKey", "코리안 스피드 바카라 A"); + requestBody.put("gameId", ""); + requestBody.put("tranType", "debit"); + requestBody.put("debit", betAmt); + requestBody.put("credit", 0); + requestBody.put("isCancel", 0); + requestBody.put("isBonus", 0); + requestBody.put("requestAt", sdf.format(System.currentTimeMillis())); + responseObj = callBackService.changeBalance(LOG_PREFIX, site.getSiteCbUrl(), requestBody); + resultCode = responseObj.getInt("result_code"); + result = new CallbackTestResult(); + if(resultCode == 80) { + int balanceAfter = balance; + int balanceResult = responseObj.getInt("balance"); + if(balanceAfter == balanceResult) { + result.setIndex(2); + result.setStatus("SUCCESS"); + result.setMsg("[bet over] 성공"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + } else { + result.setIndex(2); + result.setStatus("FAIL"); + result.setMsg("[bet over] 실패: 잔액이 맞지 않습니다."); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + } else { + result.setIndex(2); + result.setStatus("FAIL"); + result.setMsg("[bet over] 실패: 배팅금 초과 시 result_code=80 입니다."); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @GetMapping("/testWin") + public ApiResponse testWin(HttpServletRequest request, @RequestHeader String token, @Valid @RequestParam String memberId) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::CB_TEST::testWin::"+tokenInfo.getSid()+"::"; + + // 여기서 부터 로직 + List resultList = new ArrayList<>(); + + int balance = 0; + int betAmt = 100; + int winAmt = 200; + + // 4-1 call balance + JSONObject requestBody = new JSONObject(); + requestBody.put("userId", memberId); + JSONObject responseObj = callBackService.getBalance(LOG_PREFIX, site.getSiteCbUrl(), requestBody); + int resultCode = responseObj.getInt("result_code"); + CallbackTestResult result = new CallbackTestResult(); + if(resultCode == 0) { + result.setIndex(1); + result.setStatus("SUCCESS"); + result.setMsg("[balance] 성공"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + balance = responseObj.getInt("balance"); + } else { + result.setIndex(1); + result.setStatus("FAIL"); + result.setMsg("[balance] 실패"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + long ctms = System.currentTimeMillis(); + String betId = "B"+site.getSiteIdx()+ctms+memberId; + String tranId = "D"+site.getSiteIdx()+ctms+memberId; + + // 4-2 call bet + requestBody = new JSONObject(); + requestBody.put("betId", betId); + requestBody.put("tranId", tranId); + requestBody.put("userId", memberId); + requestBody.put("vendorIdx", 1); + requestBody.put("vendorKey", "C01"); + requestBody.put("vendor", "nexus"); + requestBody.put("gameIdx", 1); + requestBody.put("gameKey", "코리안 스피드 바카라 A"); + requestBody.put("gameId", ""); + requestBody.put("tranType", "debit"); + requestBody.put("debit", betAmt); + requestBody.put("credit", 0); + requestBody.put("isCancel", 0); + requestBody.put("isBonus", 0); + requestBody.put("requestAt", sdf.format(System.currentTimeMillis())); + responseObj = callBackService.changeBalance(LOG_PREFIX, site.getSiteCbUrl(), requestBody); + resultCode = responseObj.getInt("result_code"); + result = new CallbackTestResult(); + if(resultCode == 0) { + int balanceAfter = balance - betAmt; + int balanceResult = responseObj.getInt("balance"); + if(balanceAfter == balanceResult) { + result.setIndex(2); + result.setStatus("SUCCESS"); + result.setMsg("[bet] 성공"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + } else { + result.setIndex(2); + result.setStatus("FAIL"); + result.setMsg("[bet] 실패: 잔액이 맞지 않습니다."); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + } else { + result.setIndex(2); + result.setStatus("FAIL"); + result.setMsg("[bet] 실패"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + + // 4-3 call win + tranId = "C"+site.getSiteIdx()+ctms+memberId; + requestBody = new JSONObject(); + requestBody.put("betId", betId); + requestBody.put("tranId", tranId); + requestBody.put("userId", memberId); + requestBody.put("vendorIdx", 1); + requestBody.put("vendorKey", "C01"); + requestBody.put("vendor", "nexus"); + requestBody.put("gameIdx", 1); + requestBody.put("gameKey", "코리안 스피드 바카라 A"); + requestBody.put("gameId", ""); + requestBody.put("tranType", "credit"); + requestBody.put("debit", 0); + requestBody.put("credit", winAmt); + requestBody.put("isCancel", 0); + requestBody.put("isBonus", 0); + requestBody.put("requestAt", sdf.format(System.currentTimeMillis())); + responseObj = callBackService.changeBalance(LOG_PREFIX, site.getSiteCbUrl(), requestBody); + resultCode = responseObj.getInt("result_code"); + result = new CallbackTestResult(); + if(resultCode == 0) { + int balanceAfter = balance - betAmt + winAmt; + int balanceResult = responseObj.getInt("balance"); + if(balanceAfter == balanceResult) { + result.setIndex(3); + result.setStatus("SUCCESS"); + result.setMsg("[win] 성공"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + } else { + result.setIndex(3); + result.setStatus("FAIL"); + result.setMsg("[win] 실패: 잔액이 맞지 않습니다."); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + } else { + result.setIndex(3); + result.setStatus("FAIL"); + result.setMsg("[win] 실패"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + + // 4-4 call win 중복 + responseObj = callBackService.changeBalance(LOG_PREFIX, site.getSiteCbUrl(), requestBody); + resultCode = responseObj.getInt("result_code"); + result = new CallbackTestResult(); + if(resultCode == 98) { + int balanceAfter = balance - betAmt + winAmt; + int balanceResult = responseObj.getInt("balance"); + if(balanceAfter == balanceResult) { + result.setIndex(4); + result.setStatus("SUCCESS"); + result.setMsg("[win 중복] 성공"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + } else { + result.setIndex(4); + result.setStatus("FAIL"); + result.setMsg("[win 중복] 실패: 잔액이 맞지 않습니다."); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + } else { + result.setIndex(4); + result.setStatus("FAIL"); + result.setMsg("[win 중복] 실패: 결과중복 시 result_code=98 입니다."); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @GetMapping("/testCancel") + public ApiResponse testCancel(HttpServletRequest request, @RequestHeader String token, @Valid @RequestParam String memberId) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::CB_TEST::testCancel::"+tokenInfo.getSid()+"::"; + + // 여기서 부터 로직 + List resultList = new ArrayList<>(); + + int balance = 0; + int betAmt = 100; + int winAmt = 100; + + // 5-1 call balance + JSONObject requestBody = new JSONObject(); + requestBody.put("userId", memberId); + JSONObject responseObj = callBackService.getBalance(LOG_PREFIX, site.getSiteCbUrl(), requestBody); + int resultCode = responseObj.getInt("result_code"); + CallbackTestResult result = new CallbackTestResult(); + if(resultCode == 0) { + result.setIndex(1); + result.setStatus("SUCCESS"); + result.setMsg("[balance] 성공"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + balance = responseObj.getInt("balance"); + } else { + result.setIndex(1); + result.setStatus("FAIL"); + result.setMsg("[balance] 실패"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + long ctms = System.currentTimeMillis(); + String betId = "B"+site.getSiteIdx()+ctms+memberId; + String tranId = "D"+site.getSiteIdx()+ctms+memberId; + + // 5-2 call bet + requestBody = new JSONObject(); + requestBody.put("betId", betId); + requestBody.put("tranId", tranId); + requestBody.put("userId", memberId); + requestBody.put("vendorIdx", 1); + requestBody.put("vendorKey", "C01"); + requestBody.put("vendor", "nexus"); + requestBody.put("gameIdx", 1); + requestBody.put("gameKey", "코리안 스피드 바카라 A"); + requestBody.put("gameId", ""); + requestBody.put("tranType", "debit"); + requestBody.put("debit", betAmt); + requestBody.put("credit", 0); + requestBody.put("isCancel", 0); + requestBody.put("isBonus", 0); + requestBody.put("requestAt", sdf.format(System.currentTimeMillis())); + responseObj = callBackService.changeBalance(LOG_PREFIX, site.getSiteCbUrl(), requestBody); + resultCode = responseObj.getInt("result_code"); + result = new CallbackTestResult(); + if(resultCode == 0) { + int balanceAfter = balance - betAmt; + int balanceResult = responseObj.getInt("balance"); + if(balanceAfter == balanceResult) { + result.setIndex(2); + result.setStatus("SUCCESS"); + result.setMsg("[bet] 성공"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + } else { + result.setIndex(2); + result.setStatus("FAIL"); + result.setMsg("[bet] 실패: 잔액이 맞지 않습니다."); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + } else { + result.setIndex(2); + result.setStatus("FAIL"); + result.setMsg("[bet] 실패"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + + // 5-3 call Cancel + tranId = "C"+site.getSiteIdx()+ctms+memberId; + requestBody = new JSONObject(); + requestBody.put("betId", betId); + requestBody.put("tranId", tranId); + requestBody.put("userId", memberId); + requestBody.put("vendorIdx", 1); + requestBody.put("vendorKey", "C01"); + requestBody.put("vendor", "nexus"); + requestBody.put("gameIdx", 1); + requestBody.put("gameKey", "코리안 스피드 바카라 A"); + requestBody.put("gameId", ""); + requestBody.put("tranType", "credit"); + requestBody.put("debit", 0); + requestBody.put("credit", winAmt); + requestBody.put("isCancel", 1); + requestBody.put("isBonus", 0); + requestBody.put("requestAt", sdf.format(System.currentTimeMillis())); + responseObj = callBackService.changeBalance(LOG_PREFIX, site.getSiteCbUrl(), requestBody); + resultCode = responseObj.getInt("result_code"); + result = new CallbackTestResult(); + if(resultCode == 0) { + int balanceAfter = balance - betAmt + winAmt; + int balanceResult = responseObj.getInt("balance"); + if(balanceAfter == balanceResult) { + result.setIndex(3); + result.setStatus("SUCCESS"); + result.setMsg("[cancel] 성공"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + } else { + result.setIndex(3); + result.setStatus("FAIL"); + result.setMsg("[cancel] 실패: 잔액이 맞지 않습니다."); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + } else { + result.setIndex(3); + result.setStatus("FAIL"); + result.setMsg("[cancel] 실패"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + + // 5-4 call Cancel 중복 + responseObj = callBackService.changeBalance(LOG_PREFIX, site.getSiteCbUrl(), requestBody); + resultCode = responseObj.getInt("result_code"); + result = new CallbackTestResult(); + if(resultCode == 98) { + int balanceAfter = balance - betAmt + winAmt; + int balanceResult = responseObj.getInt("balance"); + if(balanceAfter == balanceResult) { + result.setIndex(4); + result.setStatus("SUCCESS"); + result.setMsg("[cancel 중복] 성공"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + } else { + result.setIndex(4); + result.setStatus("FAIL"); + result.setMsg("[cancel 중복] 실패: 잔액이 맞지 않습니다."); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + } else { + result.setIndex(4); + result.setStatus("FAIL"); + result.setMsg("[cancel 중복] 실패: 결과중복 시 result_code=98 입니다."); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @GetMapping("/testAdjust") + public ApiResponse testAdjust(HttpServletRequest request, @RequestHeader String token, @Valid @RequestParam String memberId) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::CB_TEST::testAdjust::"+tokenInfo.getSid()+"::"; + + // 여기서 부터 로직 + List resultList = new ArrayList<>(); + + int balance = 0; + int betAmt = 100; + int winAmt = 200; + int adjustAmt1 = 50; + int adjustAmt2 = -50; + + // 6-1 call balance + JSONObject requestBody = new JSONObject(); + requestBody.put("userId", memberId); + JSONObject responseObj = callBackService.getBalance(LOG_PREFIX, site.getSiteCbUrl(), requestBody); + int resultCode = responseObj.getInt("result_code"); + CallbackTestResult result = new CallbackTestResult(); + if(resultCode == 0) { + result.setIndex(1); + result.setStatus("SUCCESS"); + result.setMsg("[balance] 성공"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + balance = responseObj.getInt("balance"); + } else { + result.setIndex(1); + result.setStatus("FAIL"); + result.setMsg("[balance] 실패"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + long ctms = System.currentTimeMillis(); + String betId = "B"+site.getSiteIdx()+ctms+memberId; + String tranId = "D"+site.getSiteIdx()+ctms+memberId; + + // 6-2 call bet + requestBody = new JSONObject(); + requestBody.put("betId", betId); + requestBody.put("tranId", tranId); + requestBody.put("userId", memberId); + requestBody.put("vendorIdx", 1); + requestBody.put("vendorKey", "C01"); + requestBody.put("vendor", "nexus"); + requestBody.put("gameIdx", 1); + requestBody.put("gameKey", "코리안 스피드 바카라 A"); + requestBody.put("gameId", ""); + requestBody.put("tranType", "debit"); + requestBody.put("debit", betAmt); + requestBody.put("credit", 0); + requestBody.put("isCancel", 0); + requestBody.put("isBonus", 0); + requestBody.put("requestAt", sdf.format(System.currentTimeMillis())); + responseObj = callBackService.changeBalance(LOG_PREFIX, site.getSiteCbUrl(), requestBody); + resultCode = responseObj.getInt("result_code"); + result = new CallbackTestResult(); + if(resultCode == 0) { + int balanceAfter = balance - betAmt; + int balanceResult = responseObj.getInt("balance"); + if(balanceAfter == balanceResult) { + result.setIndex(2); + result.setStatus("SUCCESS"); + result.setMsg("[bet] 성공"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + } else { + result.setIndex(2); + result.setStatus("FAIL"); + result.setMsg("[bet] 실패: 잔액이 맞지 않습니다."); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + } else { + result.setIndex(2); + result.setStatus("FAIL"); + result.setMsg("[bet] 실패"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + + // 6-3 call win + tranId = "C"+site.getSiteIdx()+ctms+memberId; + requestBody = new JSONObject(); + requestBody.put("betId", betId); + requestBody.put("tranId", tranId); + requestBody.put("userId", memberId); + requestBody.put("vendorIdx", 1); + requestBody.put("vendorKey", "C01"); + requestBody.put("vendor", "nexus"); + requestBody.put("gameIdx", 1); + requestBody.put("gameKey", "코리안 스피드 바카라 A"); + requestBody.put("gameId", ""); + requestBody.put("tranType", "credit"); + requestBody.put("debit", 0); + requestBody.put("credit", winAmt); + requestBody.put("isCancel", 0); + requestBody.put("isBonus", 0); + requestBody.put("requestAt", sdf.format(System.currentTimeMillis())); + responseObj = callBackService.changeBalance(LOG_PREFIX, site.getSiteCbUrl(), requestBody); + resultCode = responseObj.getInt("result_code"); + result = new CallbackTestResult(); + if(resultCode == 0) { + int balanceAfter = balance - betAmt + winAmt; + int balanceResult = responseObj.getInt("balance"); + if(balanceAfter == balanceResult) { + result.setIndex(3); + result.setStatus("SUCCESS"); + result.setMsg("[win] 성공"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + } else { + result.setIndex(3); + result.setStatus("FAIL"); + result.setMsg("[win] 실패: 잔액이 맞지 않습니다."); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + } else { + result.setIndex(3); + result.setStatus("FAIL"); + result.setMsg("[win] 실패"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + + // 6-4 call adjust 잔액증가 + ctms = System.currentTimeMillis(); + tranId = "C"+site.getSiteIdx()+ctms+memberId; + requestBody = new JSONObject(); + requestBody.put("betId", betId); + requestBody.put("tranId", tranId); + requestBody.put("userId", memberId); + requestBody.put("vendorIdx", 1); + requestBody.put("vendorKey", "C01"); + requestBody.put("vendor", "nexus"); + requestBody.put("gameIdx", 1); + requestBody.put("gameKey", "코리안 스피드 바카라 A"); + requestBody.put("gameId", ""); + requestBody.put("tranType", "adjust"); + requestBody.put("debit", 0); + requestBody.put("credit", adjustAmt1); + requestBody.put("isCancel", 0); + requestBody.put("isBonus", 0); + requestBody.put("requestAt", sdf.format(System.currentTimeMillis())); + responseObj = callBackService.changeBalance(LOG_PREFIX, site.getSiteCbUrl(), requestBody); + resultCode = responseObj.getInt("result_code"); + result = new CallbackTestResult(); + if(resultCode == 0) { + int balanceAfter = balance - betAmt + winAmt + adjustAmt1; + int balanceResult = responseObj.getInt("balance"); + if(balanceAfter == balanceResult) { + result.setIndex(4); + result.setStatus("SUCCESS"); + result.setMsg("[adjust 잔액증가] 성공"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + } else { + result.setIndex(4); + result.setStatus("FAIL"); + result.setMsg("[adjust 잔액증가] 실패: 잔액이 맞지 않습니다."); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + } else { + result.setIndex(4); + result.setStatus("FAIL"); + result.setMsg("[adjust 잔액증가] 실패"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + + // 6-5 call adjust 잔액증가 중복 + responseObj = callBackService.changeBalance(LOG_PREFIX, site.getSiteCbUrl(), requestBody); + resultCode = responseObj.getInt("result_code"); + result = new CallbackTestResult(); + if(resultCode == 98) { + int balanceAfter = balance - betAmt + winAmt + adjustAmt1; + int balanceResult = responseObj.getInt("balance"); + if(balanceAfter == balanceResult) { + result.setIndex(5); + result.setStatus("SUCCESS"); + result.setMsg("[adjust 잔액증가 중복] 성공"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + } else { + result.setIndex(5); + result.setStatus("FAIL"); + result.setMsg("[adjust 잔액증가 중복] 실패: 잔액이 맞지 않습니다."); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + + balance = responseObj.getInt("balance"); + } else { + result.setIndex(5); + result.setStatus("FAIL"); + result.setMsg("[adjust 잔액증가 중복] 실패: 결과중복 시 result_code=98 입니다."); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + + + ctms = System.currentTimeMillis(); + betId = "B"+site.getSiteIdx()+ctms+memberId; + tranId = "D"+site.getSiteIdx()+ctms+memberId; + + // 6-6 call bet + requestBody = new JSONObject(); + requestBody.put("betId", betId); + requestBody.put("tranId", tranId); + requestBody.put("userId", memberId); + requestBody.put("vendorIdx", 1); + requestBody.put("vendorKey", "C01"); + requestBody.put("vendor", "nexus"); + requestBody.put("gameIdx", 1); + requestBody.put("gameKey", "코리안 스피드 바카라 A"); + requestBody.put("gameId", ""); + requestBody.put("tranType", "debit"); + requestBody.put("debit", betAmt); + requestBody.put("credit", 0); + requestBody.put("isCancel", 0); + requestBody.put("isBonus", 0); + requestBody.put("requestAt", sdf.format(System.currentTimeMillis())); + responseObj = callBackService.changeBalance(LOG_PREFIX, site.getSiteCbUrl(), requestBody); + resultCode = responseObj.getInt("result_code"); + result = new CallbackTestResult(); + if(resultCode == 0) { + int balanceAfter = balance - betAmt; + int balanceResult = responseObj.getInt("balance"); + if(balanceAfter == balanceResult) { + result.setIndex(6); + result.setStatus("SUCCESS"); + result.setMsg("[bet] 성공"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + } else { + result.setIndex(6); + result.setStatus("FAIL"); + result.setMsg("[bet] 실패: 잔액이 맞지 않습니다."); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + } else { + result.setIndex(6); + result.setStatus("FAIL"); + result.setMsg("[bet] 실패"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + + // 6-7 call win + tranId = "C"+site.getSiteIdx()+ctms+memberId; + requestBody = new JSONObject(); + requestBody.put("betId", betId); + requestBody.put("tranId", tranId); + requestBody.put("userId", memberId); + requestBody.put("vendorIdx", 1); + requestBody.put("vendorKey", "C01"); + requestBody.put("vendor", "nexus"); + requestBody.put("gameIdx", 1); + requestBody.put("gameKey", "코리안 스피드 바카라 A"); + requestBody.put("gameId", ""); + requestBody.put("tranType", "credit"); + requestBody.put("debit", 0); + requestBody.put("credit", winAmt); + requestBody.put("isCancel", 0); + requestBody.put("isBonus", 0); + requestBody.put("requestAt", sdf.format(System.currentTimeMillis())); + responseObj = callBackService.changeBalance(LOG_PREFIX, site.getSiteCbUrl(), requestBody); + resultCode = responseObj.getInt("result_code"); + result = new CallbackTestResult(); + if(resultCode == 0) { + int balanceAfter = balance - betAmt + winAmt; + int balanceResult = responseObj.getInt("balance"); + if(balanceAfter == balanceResult) { + result.setIndex(7); + result.setStatus("SUCCESS"); + result.setMsg("[win] 성공"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + } else { + result.setIndex(7); + result.setStatus("FAIL"); + result.setMsg("[win] 실패: 잔액이 맞지 않습니다."); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + } else { + result.setIndex(7); + result.setStatus("FAIL"); + result.setMsg("[win] 실패"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + + // 6-8 call adjust 잔액감소 + ctms = System.currentTimeMillis(); + tranId = "C"+site.getSiteIdx()+ctms+memberId; + requestBody = new JSONObject(); + requestBody.put("betId", betId); + requestBody.put("tranId", tranId); + requestBody.put("userId", memberId); + requestBody.put("vendorIdx", 1); + requestBody.put("vendorKey", "C01"); + requestBody.put("vendor", "nexus"); + requestBody.put("gameIdx", 1); + requestBody.put("gameKey", "코리안 스피드 바카라 A"); + requestBody.put("gameId", ""); + requestBody.put("tranType", "adjust"); + requestBody.put("debit", 0); + requestBody.put("credit", adjustAmt2); + requestBody.put("isCancel", 0); + requestBody.put("isBonus", 0); + requestBody.put("requestAt", sdf.format(System.currentTimeMillis())); + responseObj = callBackService.changeBalance(LOG_PREFIX, site.getSiteCbUrl(), requestBody); + resultCode = responseObj.getInt("result_code"); + result = new CallbackTestResult(); + if(resultCode == 0) { + int balanceAfter = balance - betAmt + winAmt + adjustAmt2; + int balanceResult = responseObj.getInt("balance"); + if(balanceAfter == balanceResult) { + result.setIndex(8); + result.setStatus("SUCCESS"); + result.setMsg("[adjust] 잔액감소 성공"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + } else { + result.setIndex(8); + result.setStatus("FAIL"); + result.setMsg("[adjust] 잔액감소 실패: 잔액이 맞지 않습니다."); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + } else { + result.setIndex(8); + result.setStatus("FAIL"); + result.setMsg("[adjust] 잔액감소 실패"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + + // 6-9 call adjust 잔액감소 중복 + responseObj = callBackService.changeBalance(LOG_PREFIX, site.getSiteCbUrl(), requestBody); + resultCode = responseObj.getInt("result_code"); + result = new CallbackTestResult(); + if(resultCode == 98) { + int balanceAfter = balance - betAmt + winAmt + adjustAmt2; + int balanceResult = responseObj.getInt("balance"); + if(balanceAfter == balanceResult) { + result.setIndex(9); + result.setStatus("SUCCESS"); + result.setMsg("[adjust 중복] 잔액감소 성공"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + } else { + result.setIndex(9); + result.setStatus("FAIL"); + result.setMsg("[adjust 중복] 잔액감소 실패: 잔액이 맞지 않습니다."); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + } else { + result.setIndex(9); + result.setStatus("FAIL"); + result.setMsg("[adjust 중복] 잔액감소 실패: 결과중복 시 result_code=98 입니다."); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + return apiResponse; + } + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + +} diff --git a/src/main/java/com/bb/api/ApiCommonController.java b/src/main/java/com/bb/api/ApiCommonController.java new file mode 100644 index 0000000..d03ded5 --- /dev/null +++ b/src/main/java/com/bb/api/ApiCommonController.java @@ -0,0 +1,635 @@ +package com.bb.api; + +import java.nio.charset.Charset; +import java.security.MessageDigest; +import java.util.Arrays; +import java.util.Base64; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Controller; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.WebClientRequestException; +import org.springframework.web.reactive.function.client.WebClientResponseException; +import org.springframework.web.util.UriComponentsBuilder; + +import com.bb.exception.ApiException; +import com.bb.jwt.JwtManager; +import com.bb.model.ApiResponse; +import com.bb.model.BanGameSearch; +import com.bb.model.CmnSearch; +import com.bb.model.Site; +import com.bb.service.CommonService; +import com.bb.service.SiteService; +import com.bb.util.IPKit; + +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Controller +@RequiredArgsConstructor +@RequestMapping(value = "/api/v1/cmn") +public class ApiCommonController { + + @Autowired + SiteService siteService; + + @Autowired + CommonService commonService; + + @Autowired + WebClient webClient; + + @Autowired + private final JwtManager jwtManager; + + @ResponseBody + @PostMapping("/code/category") + public ApiResponse gameCategoryList(@RequestHeader String token, HttpServletRequest request) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if (site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if (!(site.getSiteIp() == null || "".equals(site.getSiteIp()) || "3.3.3.3".equals(site.getSiteIp()) + || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0)) { + log.error("site.getSiteIp(" + site.getSiteIp() + "), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::CMN::gameCategoryList::" + tokenInfo.getSid() + "::::"; + + // 여기서 부터 로직 + log.info(LOG_PREFIX); + + List> list = commonService.getGameCategoryList(); + responseData.put("list", list); + + } catch (Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(responseData); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + @ResponseBody + @PostMapping("/code/vendor") + public ApiResponse gameVendorList(@RequestHeader String token, HttpServletRequest request, + @RequestBody CmnSearch search) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if (site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if (!(site.getSiteIp() == null || "".equals(site.getSiteIp()) || "3.3.3.3".equals(site.getSiteIp()) + || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0)) { + log.error("site.getSiteIp(" + site.getSiteIp() + "), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::CMN::gameVendorList::" + tokenInfo.getSid() + "::::"; + + // 여기서 부터 로직 + log.info(LOG_PREFIX); + + List> list = commonService.getGameVendorList(search); + responseData.put("list", list); + + } catch (Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(responseData); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + @ResponseBody + @GetMapping("/banGameSet/{vendorTitle}/{vendorIdx}/{skin}") + public ApiResponse banGameSetByGet(@RequestHeader String token, HttpServletRequest request, + @PathVariable("vendorTitle") String vendorTitle, @PathVariable("vendorIdx") Long vendorIdx, + @PathVariable("skin") String skin) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if (site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if (!(site.getSiteIp() == null || "".equals(site.getSiteIp()) || "3.3.3.3".equals(site.getSiteIp()) + || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0)) { + log.error("site.getSiteIp(" + site.getSiteIp() + "), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::CMN::banGameSetByGet::" + tokenInfo.getSid() + "::::"; + + BanGameSearch search = new BanGameSearch(); + search.setVendorTitle(vendorTitle); + search.setVendorIdx(vendorIdx); + search.setSkin(skin); + + // 여기서 부터 로직 + log.info(LOG_PREFIX + "BanGameSearch : " + search.toString()); + + if (search.getVendorTitle() == null || "".equals(search.getVendorTitle())) { + apiResponse.setResultCode("-1"); + apiResponse.setResultMessage("vendorTitle is not empty"); + return apiResponse; + } + + List> banGameList = commonService.getBanGameList(search); + if (banGameList == null || banGameList.size() == 0) { + apiResponse.setResultCode("-2"); + apiResponse.setResultMessage("banGameList empty"); + return apiResponse; + } + + log.info(LOG_PREFIX + "BanGameSearch : " + banGameList.toString()); + + if ("nexus".equals(search.getVendorTitle())) { + HashMap apiInfo = banGameList.get(0); + String apiBaseUrl = apiInfo.get("apiBaseUrl").toString(); + String apiAgentId = apiInfo.get("apiAgentId").toString(); + String apiKey = apiInfo.get("apiSecretKey").toString(); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8"))); + + for (HashMap item : banGameList) { + String apiVendorKey = item.get("apiVendorCode").toString(); + String vendorCetegory = item.get("vendorCetegory").toString(); + + JSONObject bodyObj = new JSONObject(); + bodyObj.put("vendorKey", apiVendorKey); + if (vendorCetegory.equals("CASINO")) { + if (search.getSkin() == null || search.getSkin().equals("")) + search.setSkin("B"); + bodyObj.put("skin", search.getSkin()); + } else if (vendorCetegory.equals("SLOT")) { + bodyObj.put("skin", "SLOT"); + bodyObj.put("type", "Slot"); + search.setSkin(""); + } else { + + } + String bodyJson = bodyObj.toString(); + log.info(LOG_PREFIX + "bodyJson::" + bodyJson); + + String hashCode = getHashCode(LOG_PREFIX, bodyJson, apiKey); + headers.set("hash", hashCode); + headers.set("agent", apiAgentId); + log.info(LOG_PREFIX + "HttpHeaders::" + headers.toString()); + + UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(apiBaseUrl + "/games"); + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("vendorKey", apiVendorKey); + if (vendorCetegory.equals("CASINO")) { + params.add("skin", search.getSkin()); + } else if (vendorCetegory.equals("SLOT")) { + params.add("skin", "SLOT"); + params.add("type", "Slot"); + } else { + + } + + try { + String responseBody = webClient.post().uri(uriBuilder.toUriString()) + .headers(h -> h.addAll(headers)).bodyValue(params).retrieve() + .bodyToMono(String.class).block(); + + JSONObject resObj = new JSONObject(responseBody); + if (resObj.getInt("code") == 0) { + JSONArray games = resObj.getJSONArray("games"); + int length = games.length(); + + for (int i = 0; i < length; i++) { + JSONObject objGame = games.getJSONObject(i); + JSONObject objName = objGame.getJSONObject("names"); + + String gameType = objGame.getString("type"); + String gameId = objGame.getString("id"); + String gameKey = objGame.getString("key"); + String gameTitleEn = objName.getString("en"); + String gameTitleKo = objName.getString("ko"); + + item.put("banGameType", gameType); + item.put("banGameId", gameId); + item.put("banGameName", gameTitleEn + "||" + gameTitleKo); + item.put("banGameNameEng", gameTitleEn); + item.put("banGameKey", gameKey); + item.put("skin", search.getSkin()); + + log.info(LOG_PREFIX + "item : " + item.toString()); + int result = commonService.insertBanGameInfo(item); + log.info(LOG_PREFIX + "insertBanGameInfo result : " + result); + /* + * if(apiVendorKey.equals("evolution_casino")) { result = + * commonService.insertNexusGameInfo(item); log.info(LOG_PREFIX+ + * "insertNexusGameInfo result : " + result); } + */ + } + + } else { + apiResponse.setResultCode("-99"); + apiResponse.setResultMessage("api fail"); + return apiResponse; + } + } catch (WebClientResponseException e) { + log.error(LOG_PREFIX + "WebClientResponseException : " + e.getMessage()); + throw new ApiException("E901", "API call failed"); + } catch (WebClientRequestException e) { + log.error(LOG_PREFIX + "WebClientRequestException : " + e.getMessage()); + throw new ApiException("E902", "Network error"); + } + } + + } else if ("ace2".equals(search.getVendorTitle())) { + HashMap apiInfo = banGameList.get(0); + String apiBaseUrl = apiInfo.get("apiBaseUrl").toString(); + String apiAgentId = apiInfo.get("apiAgentId").toString(); + String apiKey = apiInfo.get("apiSecretKey").toString(); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8"))); + + for (HashMap item : banGameList) { + String apiVendorKey = item.get("apiVendorCode").toString(); + String vendorCetegory = item.get("vendorCetegory").toString(); + + JSONObject bodyObj = new JSONObject(); + bodyObj.put("vendorKey", apiVendorKey); + if (vendorCetegory.equals("CASINO")) { + if (search.getSkin() == null || search.getSkin().equals("")) + search.setSkin("B"); + bodyObj.put("skin", search.getSkin()); + } else if (vendorCetegory.equals("SLOT")) { + bodyObj.put("skin", "SLOT"); + bodyObj.put("type", "Slot"); + search.setSkin(""); + } else { + + } + String bodyJson = bodyObj.toString(); + log.info(LOG_PREFIX + "bodyJson::" + bodyJson); + + String hashCode = getHashCode(LOG_PREFIX, bodyJson, apiKey); + headers.set("hash", hashCode); + headers.set("agent", apiAgentId); + log.info(LOG_PREFIX + "HttpHeaders::" + headers.toString()); + + UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(apiBaseUrl + "/games"); + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("vendorKey", apiVendorKey); + if (vendorCetegory.equals("CASINO")) { + params.add("skin", search.getSkin()); + } else if (vendorCetegory.equals("SLOT")) { + params.add("skin", "SLOT"); + params.add("type", "Slot"); + } else { + + } + + try { + String responseBody = webClient.post().uri(uriBuilder.toUriString()) + .headers(h -> h.addAll(headers)).bodyValue(params).retrieve() + .bodyToMono(String.class).block(); + + JSONObject resObj = new JSONObject(responseBody); + if (resObj.getInt("code") == 0) { + JSONArray games = resObj.getJSONArray("games"); + int length = games.length(); + + for (int i = 0; i < length; i++) { + JSONObject objGame = games.getJSONObject(i); + JSONObject objName = objGame.getJSONObject("names"); + + String gameType = objGame.getString("type"); + String gameId = objGame.getString("id"); + String gameKey = objGame.getString("key"); + String gameTitleEn = objName.getString("en"); + String gameTitleKo = objName.getString("ko"); + + item.put("banGameType", gameType); + item.put("banGameId", gameId); + item.put("banGameName", gameTitleEn + "||" + gameTitleKo); + item.put("banGameNameEng", gameTitleEn); + item.put("banGameKey", gameKey); + item.put("skin", search.getSkin()); + + log.info(LOG_PREFIX + "item : " + item.toString()); + int result = commonService.insertBanGameInfo(item); + log.info(LOG_PREFIX + "insertBanGameInfo result : " + result); + /* + * if(apiVendorKey.equals("evolution_casino")) { result = + * commonService.insertNexusGameInfo(item); log.info(LOG_PREFIX+ + * "insertNexusGameInfo result : " + result); } + */ + } + + } else { + apiResponse.setResultCode("-99"); + apiResponse.setResultMessage("api fail"); + return apiResponse; + } + } catch (WebClientResponseException e) { + log.error(LOG_PREFIX + "WebClientResponseException : " + e.getMessage()); + throw new ApiException("E901", "API call failed"); + } catch (WebClientRequestException e) { + log.error(LOG_PREFIX + "WebClientRequestException : " + e.getMessage()); + throw new ApiException("E902", "Network error"); + } + } + + } else if ("dpcore".equals(search.getVendorTitle())) { + HashMap apiInfo = banGameList.get(0); + String apiBaseUrl = apiInfo.get("apiBaseUrl").toString(); + String apiAgentId = apiInfo.get("apiAgentId").toString(); + String apiKey = "Bearer " + apiInfo.get("apiSecretKey").toString(); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.set("Authorization", apiKey); + String gameUrl = apiBaseUrl + "/api/gameList"; + + for (HashMap item : banGameList) { + String apiVendorKey = item.get("apiVendorCode").toString(); + JSONObject prams = new JSONObject(); + + log.info(LOG_PREFIX + "DPCORE::Game List Url: " + gameUrl); + log.info(LOG_PREFIX + "DPCORE::Game List Headers: " + headers.toString()); + + try { + String responseBody = webClient.post().uri(gameUrl).headers(h -> h.addAll(headers)) + .bodyValue(prams.toString()).retrieve().bodyToMono(String.class).block(); + + JSONArray games = new JSONArray(responseBody); + int length = games.length(); + + for (int i = 0; i < length; i++) { + JSONObject objGame = games.getJSONObject(i); + String gameType = objGame.getString("gameType"); + String gameId = objGame.getString("tableId"); + String gameKey = objGame.getString("tableId"); + String gameTitleEn = objGame.getString("tableName"); + String gameTitleKo = objGame.getString("tableName"); + + item.put("banGameType", gameType); + item.put("banGameId", gameId); + item.put("banGameName", gameTitleEn + "||" + gameTitleKo); + item.put("banGameNameEng", gameTitleEn); + item.put("banGameKey", gameKey); + item.put("skin", search.getSkin()); + + log.info(LOG_PREFIX + "item : " + item.toString()); + int result = commonService.insertBanGameInfo(item); + log.info(LOG_PREFIX + "insertBanGameInfo result : " + result); + } + } catch (WebClientResponseException e) { + log.error(LOG_PREFIX + "WebClientResponseException : " + e.getMessage()); + throw new ApiException("E901", "API call failed"); + } catch (WebClientRequestException e) { + log.error(LOG_PREFIX + "WebClientRequestException : " + e.getMessage()); + throw new ApiException("E902", "Network error"); + } + } + } else if ("pink".equals(search.getVendorTitle())) { + HashMap apiInfo = banGameList.get(0); + String apiBaseUrl = apiInfo.get("apiBaseUrl").toString(); + String apiAgentId = apiInfo.get("apiAgentId").toString(); + String apiKey = apiInfo.get("apiSecretKey").toString(); + String apiVendorCode = apiInfo.get("apiVendorCode").toString(); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + headers.set("Authorization", apiKey); + + UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(apiBaseUrl + "/gamelist"); + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("vendor", apiVendorCode); + params.add("type", "all"); + + log.info(LOG_PREFIX + "HttpHeaders::" + headers.toString()); + log.info(LOG_PREFIX + "params::" + params.toString()); + + try { + String responseBody = webClient.post().uri(uriBuilder.toUriString()) + .headers(h -> h.addAll(headers)).bodyValue(params).retrieve().bodyToMono(String.class) + .block(); + JSONObject resObj = new JSONObject(responseBody); + + if (resObj.getInt("code") == 0) { + log.info(LOG_PREFIX + "gameList::Response::code::" + resObj.getInt("code")); + log.info(LOG_PREFIX + "gameList::Response::msg::" + resObj.getString("msg")); + JSONArray games = resObj.getJSONArray("data"); + int length = games.length(); + + for (int i = 0; i < length; i++) { + JSONObject objGame = games.getJSONObject(i); + String gameType = objGame.getString("type"); + String gameId = objGame.getString("game"); + String gameKey = objGame.getString("game"); + String gameTitleEn = objGame.getString("name"); + String gameTitleKo = objGame.getString("kname"); + + apiInfo.put("banGameType", gameType); + apiInfo.put("banGameId", gameId); + apiInfo.put("banGameName", gameTitleEn + "||" + gameTitleKo); + apiInfo.put("banGameNameEng", gameTitleEn); + apiInfo.put("banGameKey", gameKey); + apiInfo.put("skin", search.getSkin()); + + log.info(LOG_PREFIX + "item : " + apiInfo.toString()); + int result = commonService.insertBanGameInfo(apiInfo); + log.info(LOG_PREFIX + "insertBanGameInfo result : " + result); + } + } else { + apiResponse.setResultCode("-99"); + apiResponse.setResultMessage("api fail"); + return apiResponse; + } + } catch (WebClientResponseException e) { + log.error(LOG_PREFIX + "WebClientResponseException : " + e.getMessage()); + throw new ApiException("E901", "API call failed"); + } catch (WebClientRequestException e) { + log.error(LOG_PREFIX + "WebClientRequestException : " + e.getMessage()); + throw new ApiException("E902", "Network error"); + } + } else if ("onix".equals(search.getVendorTitle())) { + HashMap apiInfo = banGameList.get(0); + String apiBaseUrl = apiInfo.get("apiBaseUrl").toString(); + String apiAgentId = apiInfo.get("apiAgentId").toString(); + String apiKey = "Bearer " + apiInfo.get("apiSecretKey").toString(); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.set("Authorization", apiKey); + String gameUrl = apiBaseUrl + "/csapi/Provider"; + + for (HashMap item : banGameList) { + String apiVendorKey = item.get("apiVendorCode").toString(); + JSONObject prams = new JSONObject(); + prams.put("type", "0"); + prams.put("gameid", "SxCasino"); + prams.put("code", "evolution"); + prams.put("gametype", "live"); + + log.info(LOG_PREFIX + "ONIX::Game List Url: " + gameUrl); + log.info(LOG_PREFIX + "ONIX::Game List Headers: " + headers.toString()); + + try { + String responseBody = webClient.post().uri(gameUrl).headers(h -> h.addAll(headers)) + .bodyValue(prams.toString()).retrieve().bodyToMono(String.class).block(); + JSONObject resObj = new JSONObject(responseBody); + int resultCode = resObj.getInt("result"); + + if(resultCode == 1) { + JSONArray games = resObj.getJSONArray("data"); + int length = games.length(); + + for (int i = 0; i < length; i++) { + JSONObject objGame = games.getJSONObject(i); + String gameType = objGame.getString("type"); + String gameId = objGame.getString("subcode"); + String gameTitleEn = objGame.getString("name_eng"); + String gameTitleKo = objGame.getString("name_kor"); + + item.put("banGameType", gameType); + item.put("banGameId", gameId); + item.put("banGameName", gameTitleEn + "||" + gameTitleKo); + item.put("banGameNameEng", gameTitleEn); + item.put("skin", search.getSkin()); + + log.info(LOG_PREFIX + "item : " + item.toString()); + int result = commonService.insertBanGameInfo(item); + log.info(LOG_PREFIX + "insertBanGameInfo result : " + result); + } + } + } catch (WebClientResponseException e) { + log.error(LOG_PREFIX + "WebClientResponseException : " + e.getMessage()); + throw new ApiException("E901", "API call failed"); + } catch (WebClientRequestException e) { + log.error(LOG_PREFIX + "WebClientRequestException : " + e.getMessage()); + throw new ApiException("E902", "Network error"); + } + } + } + + } catch (Exception e) { + log.error("#-API::CMN::banGameSet::" + e.toString()); + e.printStackTrace(); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(responseData); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + private String getHashCode(String LOG_PREFIX, String body, String secretKey) { + String hashCode = ""; + LOG_PREFIX = LOG_PREFIX + "::getHashCode::"; + try { + // Json String Body + Secret Key + String result = body + secretKey; + // String result = + // "{\"username\":\"057007mptest01\",\"nickname\":\"007mptest01\",\"siteUsername\":\"057007mptest01\"}"; + log.info(LOG_PREFIX + "Body + Secret Key::" + result); + // SHA-256 Hash make + MessageDigest digestObj = MessageDigest.getInstance("SHA-256"); + byte[] hash_data = digestObj.digest(result.getBytes("UTF-8")); + + // Base64 encoding + hashCode = Base64.getEncoder().encodeToString(hash_data); + log.info(LOG_PREFIX + "hashCode::" + hashCode); + } catch (Exception e) { + log.error("#-NexusService::getHashCode::Exception::" + e.getMessage()); + } + + return hashCode; + } + +} diff --git a/src/main/java/com/bb/api/ApiCreditController.java b/src/main/java/com/bb/api/ApiCreditController.java new file mode 100644 index 0000000..80ef1b5 --- /dev/null +++ b/src/main/java/com/bb/api/ApiCreditController.java @@ -0,0 +1,580 @@ +package com.bb.api; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.Valid; + +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import com.bb.jwt.JwtManager; +import com.bb.model.ApiResponse; +import com.bb.model.Credit; +import com.bb.model.CreditPointSearch; +import com.bb.model.CreditSearchVO; +import com.bb.model.PageFormVO; +import com.bb.model.Site; +import com.bb.service.CreditService; +import com.bb.service.SiteService; +import com.bb.util.IPKit; +import com.bb.util.PagingUtil; +import com.bb.util.StringUtils; +import com.fasterxml.jackson.databind.ObjectMapper; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Controller +@RequiredArgsConstructor +@RequestMapping(value = "/api/v1/credit") +public class ApiCreditController { + + @Autowired + SiteService siteService; + + @Autowired + CreditService creditService; + + @Autowired + private final JwtManager jwtManager; + + + @ResponseBody + @PostMapping("/list") + public ApiResponse creditList(@RequestHeader String token, HttpServletRequest request, @RequestBody CreditSearchVO search) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::CREDIT::creditList::"+tokenInfo.getSid()+"::::"; + + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(search); + JSONObject reqObj = new JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + // 여기서 부터 로직 + PageFormVO pageVo= new PageFormVO(); + if(search.getSiteIdx() == null || search.getSiteId() == null || search.getSiteId().equals("")) { + search.setSiteId(site.getSiteId()); + search.setSiteIdx((long) site.getSiteIdx()); + } + + if(search.getOrderStr() == null || search.getOrderStr().equals("")) { + search.setOrderStr("UPDATE_DESC"); + } + + search.setTransType(search.getTransType().trim()); + + if(search.getTransType().equals("AD-AI") || search.getTransType().equals("AD-AO") || search.getTransType().equals("AD")) { + // 관리자 지급/회수 + search.setUpperSiteIdx((long) 2); + search.setUpperSiteId("tripleSuper"); + search.setTargetSiteIdx(search.getSiteIdx()); + search.setTargetSiteId(search.getSiteId()); + + search.setSearchSiteId(""); + } else if(search.getTransType().equals("UP-AI") || search.getTransType().equals("UP-AO") || search.getTransType().equals("UP")) { + // 상부가 지급/회수 + search.setTargetSiteIdx(search.getSiteIdx()); + search.setTargetSiteId(search.getSiteId()); + } else if(search.getTransType().equals("DW-AI") || search.getTransType().equals("DW-AO") || search.getTransType().equals("DW")) { + // 하부에 지급/회수 + search.setUpperSiteIdx(search.getSiteIdx()); + search.setUpperSiteId(search.getSiteId()); + } else if(search.getTransType().equals("MAI") || search.getTransType().equals("MAO") || search.getTransType().equals("MAIO")) { + // 회원에 충전/환전 + search.setUpperSiteIdx(search.getSiteIdx()); + search.setUpperSiteId(search.getSiteId()); + } else { + // 전체 검색 + search.setUpperSiteIdx(search.getSiteIdx()); + search.setUpperSiteId(search.getSiteId()); + search.setTargetSiteIdx(search.getSiteIdx()); + search.setTargetSiteId(search.getSiteId()); + } + + log.info(LOG_PREFIX+ "CreditSearchVO::"+search.toString()); + + int totalCount = creditService.getTransCreditListCnt(search); + if (totalCount != 0) { + PageFormVO commonForm = new PageFormVO(); + commonForm.setFunction_name("goPage"); + commonForm.setPage(search.getPage()); + commonForm.setCount_per_page(20); + if(search.getCount_per_list()==0) { + commonForm.setCount_per_list(30); + } else { + commonForm.setCount_per_list(search.getCount_per_list()); + } + commonForm.setTatal_list_count(totalCount); + pageVo = PagingUtil.setPageUtil(commonForm); + search.setLimit(pageVo.getLimit()); + search.setOffset(pageVo.getOffset()); + search.setTatal_list_count(totalCount); + + responseData.put("pageInfo", pageVo); + } + + List> list = creditService.getTransCreditList(search); + responseData.put("list", list); + + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(responseData); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping("/transaction") + public ApiResponse transaction(@RequestHeader String token, HttpServletRequest request, @RequestBody CreditSearchVO search) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::CREDIT::transaction::"+tokenInfo.getSid()+"::::"; + + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(search); + JSONObject reqObj = new JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + // 여기서 부터 로직 + PageFormVO pageVo= new PageFormVO(); + if(search.getSiteIdx() == null || search.getSiteId() == null || search.getSiteId().equals("")) { + search.setSiteId(site.getSiteId()); + search.setSiteIdx((long) site.getSiteIdx()); + } + + if(search.getOrderStr() == null || search.getOrderStr().equals("")) { + search.setOrderStr("UPDATE_DESC"); + } + + search.setTransType(search.getTransType().trim()); + + search.setStartDatePartition(StringUtils.convertToDateOnly(search.getStartDate())); + search.setEndDatePartition(StringUtils.convertToDateOnly(search.getEndDate())); + + if(search.getTransType().equals("AD-AI") || search.getTransType().equals("AD-AO") || search.getTransType().equals("AD")) { + // 관리자 지급/회수 + search.setUpperSiteIdx((long) 2); + search.setUpperSiteId("tripleSuper"); + search.setTargetSiteIdx(search.getSiteIdx()); + search.setTargetSiteId(search.getSiteId()); + + search.setSearchSiteId(""); + } else if(search.getTransType().equals("UP-AI") || search.getTransType().equals("UP-AO") || search.getTransType().equals("UP")) { + // 상부가 지급/회수 + search.setTargetSiteIdx(search.getSiteIdx()); + search.setTargetSiteId(search.getSiteId()); + } else if(search.getTransType().equals("DW-AI") || search.getTransType().equals("DW-AO") || search.getTransType().equals("DW")) { + // 하부에 지급/회수 + search.setUpperSiteIdx(search.getSiteIdx()); + search.setUpperSiteId(search.getSiteId()); + } else if(search.getTransType().equals("MAI") || search.getTransType().equals("MAO") || search.getTransType().equals("MAIO")) { + // 회원에 충전/환전 + search.setUpperSiteIdx(search.getSiteIdx()); + search.setUpperSiteId(search.getSiteId()); + } else if(search.getTransType().equals("DP") || search.getTransType().equals("CD") || search.getTransType().equals("CDP")) { + // 회원 베팅/결과 + search.setUpperSiteIdx(search.getSiteIdx()); + search.setUpperSiteId(search.getSiteId()); + } else { + // 전체 검색 + search.setUpperSiteIdx(search.getSiteIdx()); + search.setUpperSiteId(search.getSiteId()); + search.setTargetSiteIdx(search.getSiteIdx()); + search.setTargetSiteId(search.getSiteId()); + } + + log.info(LOG_PREFIX+ "CreditSearchVO::"+search.toString()); + + int totalCount = creditService.getTotalTransactionListCnt(search); + if (totalCount != 0) { + PageFormVO commonForm = new PageFormVO(); + commonForm.setFunction_name("goPage"); + commonForm.setPage(search.getPage()); + commonForm.setCount_per_page(20); + if(search.getCount_per_list()==0) { + commonForm.setCount_per_list(30); + } else { + commonForm.setCount_per_list(search.getCount_per_list()); + } + commonForm.setTatal_list_count(totalCount); + pageVo = PagingUtil.setPageUtil(commonForm); + search.setLimit(pageVo.getLimit()); + search.setOffset(pageVo.getOffset()); + search.setTatal_list_count(totalCount); + + responseData.put("pageInfo", pageVo); + } + + List> list = creditService.getTotalTransactionList(search); + responseData.put("list", list); + + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(responseData); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping("/addProc") + public ApiResponse addProc(@RequestHeader String token, HttpServletRequest request, @RequestBody Credit credit) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map data = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::CREDIT::addProc::"+tokenInfo.getSid()+"::::"; + + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(credit); + JSONObject reqObj = new JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + // 여기서 부터 로직 + if("tripleSuper".equals(site.getSiteId())){ + apiResponse.setResultCode("9991"); + apiResponse.setResultMessage("Super admin is not allow"); + return apiResponse; + } + + if("AI".equals(credit.getCreditType())) { + // 관리자 or 상부 직접 지급 + long siteCredit = siteService.getSiteCredit(tokenInfo.getSid()); + if(siteCredit < credit.getCreditAmt()) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("크레딧이 모자릅니다"); + return apiResponse; + } + + if(credit.getTargetSiteId() == null || credit.getTargetSiteId().equals("")) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("대상이 존재하지 않습니다"); + return apiResponse; + } + + credit.setInOut("IN"); + credit.setCreditStatus(1); + credit.setSiteIdx(site.getSiteIdx()); + credit.setSiteId(site.getSiteId()); + + + + } else if("AO".equals(credit.getCreditType())) { + // 관리자 or 상부 직접환급 + + if(credit.getTargetSiteId() == null || credit.getTargetSiteId().equals("")) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("대상이 존재하지 않습니다"); + return apiResponse; + } + + long targetSiteCredit = siteService.getSiteCredit(credit.getTargetSiteId()); + if(targetSiteCredit < credit.getCreditAmt()) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("해당 에이젼시의 크레딧이 모자릅니다"); + return apiResponse; + } + + credit.setInOut("OUT"); + credit.setCreditStatus(1); + credit.setSiteIdx(site.getSiteIdx()); + credit.setSiteId(site.getSiteId()); + + } else { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("알 수 없는 요청"); + return apiResponse; + } + + log.info(LOG_PREFIX+ "Credit::AF::"+credit.toString()); + + int result = creditService.insertCredit(credit); + + + log.info(LOG_PREFIX+ "insertCredit result::"+result); + + + } catch(Exception e) { + log.error(e.toString()); + e.printStackTrace(); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(data); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping("/pointList") + public ApiResponse pointList(@RequestHeader String token, HttpServletRequest request, @Valid @RequestBody CreditPointSearch search) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::TRANS::betlist::"+tokenInfo.getSid()+"::::"; + + // 여기서 부터 로직 + + PageFormVO pageVo = new PageFormVO(); + search.setSearchSiteId(site.getSiteId()); + search.setSearchSiteIdx((long) site.getSiteIdx()); + search.setStartDate(search.getStartDate()+".000"); + search.setEndDate(search.getEndDate()+".999"); + + if(search.getOrderStr() == null || search.getOrderStr().equals("")) { + search.setOrderStr("BETDATE_DESC"); + } + + log.info(LOG_PREFIX+ "CreditPointSearch::"+search.toString()); + + int totalCount = creditService.getCreditPointListCnt(search); + if (totalCount != 0) { + PageFormVO commonForm = new PageFormVO(); + commonForm.setFunction_name("goPage"); + commonForm.setPage(search.getPage()); + commonForm.setCount_per_page(20); + if(search.getCount_per_list()==0) { + commonForm.setCount_per_list(30); + } else { + commonForm.setCount_per_list(search.getCount_per_list()); + } + commonForm.setTatal_list_count(totalCount); + pageVo = PagingUtil.setPageUtil(commonForm); + search.setLimit(pageVo.getLimit()); + search.setOffset(pageVo.getOffset()); + search.setTatal_list_count(totalCount); + + responseData.put("pageInfo", pageVo); + } + + List> list = creditService.getCreditPointList(search); + responseData.put("list", list); + + } catch(Exception e) { + log.info(e.toString()); + e.printStackTrace(); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(responseData); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping("/betList") + public ApiResponse betList(@RequestHeader String token, HttpServletRequest request, @Valid @RequestBody CreditPointSearch search) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::TRANS::betlist::"+tokenInfo.getSid()+"::::"; + + // 여기서 부터 로직 + + PageFormVO pageVo = new PageFormVO(); + search.setSearchSiteId(site.getSiteId()); + search.setSearchSiteIdx((long) site.getSiteIdx()); + search.setStartDate(search.getStartDate()+".000"); + search.setEndDate(search.getEndDate()+".999"); + + if(search.getOrderStr() == null || search.getOrderStr().equals("")) { + search.setOrderStr("BETDATE_DESC"); + } + + log.info(LOG_PREFIX+ "CreditPointSearch::"+search.toString()); + + search.setStartDatePartition(StringUtils.convertToDateOnly(search.getStartDate())); + search.setEndDatePartition(StringUtils.convertToDateOnly(search.getEndDate())); + + int totalCount = creditService.getCreditBetListCnt(search); + if (totalCount != 0) { + PageFormVO commonForm = new PageFormVO(); + commonForm.setFunction_name("goPage"); + commonForm.setPage(search.getPage()); + commonForm.setCount_per_page(20); + if(search.getCount_per_list()==0) { + commonForm.setCount_per_list(30); + } else { + commonForm.setCount_per_list(search.getCount_per_list()); + } + commonForm.setTatal_list_count(totalCount); + pageVo = PagingUtil.setPageUtil(commonForm); + search.setLimit(pageVo.getLimit()); + search.setOffset(pageVo.getOffset()); + search.setTatal_list_count(totalCount); + + responseData.put("pageInfo", pageVo); + } + + List> list = creditService.getCreditBetList(search); + responseData.put("list", list); + + } catch(Exception e) { + log.info(e.toString()); + e.printStackTrace(); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(responseData); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } +} diff --git a/src/main/java/com/bb/api/ApiMainController.java b/src/main/java/com/bb/api/ApiMainController.java new file mode 100644 index 0000000..a603add --- /dev/null +++ b/src/main/java/com/bb/api/ApiMainController.java @@ -0,0 +1,382 @@ +package com.bb.api; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import jakarta.servlet.http.HttpServletRequest; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +import com.bb.jwt.JwtClame; +import com.bb.jwt.JwtManager; +import com.bb.model.ApiResponse; +import com.bb.model.BoardSearch; +import com.bb.model.PageFormVO; +import com.bb.model.Site; +import com.bb.model.SiteSearch; +import com.bb.service.SiteService; +import com.bb.service.StatService; +import com.bb.util.IPKit; +import com.bb.util.PagingUtil; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import net.sf.json.JSONObject; + +@Slf4j +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/api/v1") +public class ApiMainController { + + @Autowired + private final JwtManager jwtManager; + + @Autowired + SiteService siteService; + + + @Autowired + StatService statService; + + + @ResponseBody + @PostMapping(value="/login") + public ApiResponse agentBalance(HttpServletRequest request, @RequestBody JSONObject requestBody) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + final String LOG_PREFIX = "#-NSOFT::LOGIN::"+requestBody.getString("apiId")+":::"; + try { + // apiKey 체크 + log.info(LOG_PREFIX+ "Request Body: "+requestBody.toString()); + String agentId = requestBody.getString("apiId"); + if(agentId != null && "tripleSuper".equals(agentId)){ + apiResponse.setResultCode("9991"); + apiResponse.setResultMessage("Super admin login is not allow"); + return apiResponse; + } + + if("".equals(agentId)) { + apiResponse.setResultCode("9998"); + apiResponse.setResultMessage("apiId is not null"); + return apiResponse; + } + + String agentPwd = requestBody.getString("apiPwd"); + if("".equals(agentPwd)) { + apiResponse.setResultCode("9998"); + apiResponse.setResultMessage("agentPwd is not null"); + return apiResponse; + } + Map loginParam = new HashMap(); + loginParam.put("siteId", agentId); + loginParam.put("sitePwd", agentPwd); + + Site siteLogin = siteService.getSiteLoginApi(loginParam); + if(siteLogin == null) { + apiResponse.setResultCode("9997"); + apiResponse.setResultMessage("agent info check"); + return apiResponse; + } + + log.info(siteLogin.getIps() +","+IPKit.getIpAddressByRequest(request) ); + if( !( siteLogin.getIps() == null || "".equals(siteLogin.getIps()) || "3.3.3.3".equals(siteLogin.getIps()) || siteLogin.getIps().indexOf(IPKit.getIpAddressByRequest(request)) >= 0 ) ) { + log.error("#API::LOGIN::"+siteLogin.getSiteId() +"::siteLogin.getIps("+siteLogin.getIps()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + apiResponse.setResultMessage("access denied IP"); + return apiResponse; + } + + JwtClame jwtinfo = new JwtClame(); + jwtinfo.setSiteId(siteLogin.getSiteId()); + String token = jwtManager.generateTokenAdmin(jwtinfo); + String refresh_token = jwtManager.generateTokenRefresh(jwtinfo); + + Map data = new HashMap(); + data.put("siteKey", siteLogin.getSiteKey()); + data.put("token", token); + data.put("refresh_token", refresh_token); + data.put("isTransfer", siteLogin.getIsTransfer()); + data.put("useParseStatMenu", siteLogin.getUseParseStatMenu()); + log.info("#API::LOGIN::data::" + data.toString()); + + apiResponse.setData(data); + apiResponse.success(); + + } catch (Exception e) { + + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping(value="/myCredit") + public ApiResponse myCredit(@RequestHeader String token, HttpServletRequest request) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + try { + log.info(token.toString()); + Site site = siteService.getSiteInfoAPI(request); + + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + + if( !( site.getSiteIp() == null || "".equals(site.getSiteIp()) || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0 ) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + apiResponse.setResultMessage("access denied IP"); + return apiResponse; + } + //토큰체크 + Map data = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + + log.info(tokenInfo.getSid()); + long siteCredit = siteService.getSiteCredit(tokenInfo.getSid()); + long sitePoint = siteService.getSitePoint(tokenInfo.getSid()); + data.put("credit", siteCredit); + data.put("point", sitePoint); + data.put("siteLevel", site.getSiteLevel()); + if(site.getSiteLevel() == 1) { + HashMap creditInfo = siteService.getSiteSubCredit(tokenInfo.getSid()); + data.put("subCreditInfo", creditInfo); + } else { + data.put("subCreditInfo", null); + } + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(data); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping(value="/myBetInfo") + public ApiResponse myBetInfo(@RequestHeader String token, HttpServletRequest request, @RequestBody JSONObject param) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + try { + log.info(token.toString()); + String authorization = request.getHeader("Authorization").toString(); + log.info("#-myBetInfo::Authorization::"+authorization); + log.info("#-myBetInfo::param::"+param); + Site site = siteService.getSiteInfoAPI(request); + + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp() == null || "".equals(site.getSiteIp()) || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0 ) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + apiResponse.setResultMessage("access denied IP"); + return apiResponse; + } + // TO DO 토큰체크 + Map data = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + + log.info("#-myBetInfo::site::"+tokenInfo.getSid()); + + SiteSearch search = new SiteSearch(); + search.setSiteIdx(site.getSiteIdx()); + search.setStartDate(param.getString("targetDate")); + log.info("#-myBetInfo::search::"+search); + List stat = statService.getDashBoardList(search) ; + data.put("info", stat); + + List statM = statService.getDashBoardMonth(search) ; + data.put("infoM", statM); + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(data); + apiResponse.success(); + + } catch (Exception e) { + log.error("#-myBetInfo::Exception::"+ e.getMessage()); + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping("/board/list") + public ApiResponse boardList(@RequestHeader String token, HttpServletRequest request, @RequestBody BoardSearch search) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::MAIN::boardList::"+tokenInfo.getSid()+"::::"; + + // 여기서 부터 로직 + search.setSiteIdx(site.getSiteIdx()); + search.setSiteId(tokenInfo.getSid()); + log.info(LOG_PREFIX + "BoardSearch::"+search); + + if(search.getViewType() == null || search.getViewType().equals("")) { + search.setViewType("main"); + } + + if(search.getBoardType() == null || search.getBoardType().equals("")) { + search.setBoardType("notice"); + } + + if(search.getViewType().equals("main")) { + List> list = siteService.getBoardList(search); + responseData.put("boardList", list); + } else { + PageFormVO pageVo = new PageFormVO(); + int totalCount = siteService.getBoardListCnt(search); + if (totalCount != 0) { + PageFormVO commonForm = new PageFormVO(); + commonForm.setFunction_name("goPage"); + commonForm.setPage(search.getPage()); + commonForm.setCount_per_page(20); + if(search.getCount_per_list()==0) { + commonForm.setCount_per_list(30); + } else { + commonForm.setCount_per_list(search.getCount_per_list()); + } + commonForm.setTatal_list_count(totalCount); + pageVo = PagingUtil.setPageUtil(commonForm); + search.setLimit(pageVo.getLimit()); + search.setOffset(pageVo.getOffset()); + search.setTatal_list_count(totalCount); + + responseData.put("pageInfo", pageVo); + } + + List> list = siteService.getBoardList(search); + responseData.put("boardList", list); + } + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(responseData); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @GetMapping("/board/{boardIdx}") + public ApiResponse boardList(@RequestHeader String token, HttpServletRequest request, @PathVariable long boardIdx) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::MAIN::boardList::"+tokenInfo.getSid()+"::::"; + + // 여기서 부터 로직 + log.info(LOG_PREFIX + "BoardIdx::"+boardIdx); + + HashMap detail = siteService.getBoardDetail(boardIdx); + responseData.put("boardDetail", detail); + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(responseData); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } +} diff --git a/src/main/java/com/bb/api/ApiSettingController.java b/src/main/java/com/bb/api/ApiSettingController.java new file mode 100644 index 0000000..0d8e1c7 --- /dev/null +++ b/src/main/java/com/bb/api/ApiSettingController.java @@ -0,0 +1,407 @@ +package com.bb.api; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import jakarta.servlet.http.HttpServletRequest; + +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import com.bb.jwt.JwtManager; +import com.bb.model.ApiResponse; +import com.bb.model.CmnSearch; +import com.bb.model.Site; +import com.bb.model.SiteVendorSkinVO; +import com.bb.service.BetRadarService; +import com.bb.service.SettingService; +import com.bb.service.SiteService; +import com.bb.util.IPKit; +import com.fasterxml.jackson.databind.ObjectMapper; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Controller +@RequiredArgsConstructor +@RequestMapping(value = "/api/v1/setting") +public class ApiSettingController { + + @Autowired + SiteService siteService; + + @Autowired + SettingService settingService; + + @Autowired + BetRadarService betRadarService; + + @Autowired + private final JwtManager jwtManager; + + + @ResponseBody + @PostMapping("/vendor") + public ApiResponse settingVendorList(@RequestHeader String token, HttpServletRequest request, @RequestBody CmnSearch search) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::SETTING::settingVendorList::"+tokenInfo.getSid()+"::::"; + + // POJO to JSON + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(search); + JSONObject reqObj = new JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + // 여기서 부터 로직 + if(search.getSiteIdx() == null || search.getSiteIdx() == 0) { + search.setSiteIdx((long) site.getSiteIdx()); + search.setSiteId(tokenInfo.getSid()); + } + log.info(LOG_PREFIX + "CmnSearch::"+search.toString()); + + List> list = settingService.getSettingVendorList(search); + for(HashMap item : list) { + Long vendorIdx = (Long) item.get("vendorIdx"); + String vendorTitle = item.get("vendorTitle").toString(); + search.setVendorIdx(vendorIdx); + search.setVendorTitle(vendorTitle); + List> skinList = settingService.getSettingSkinList(search); + item.put("skinList", skinList); + } + responseData.put("list", list); + + + } catch(Exception e) { + e.printStackTrace(); + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(responseData); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping("/skin") + public ApiResponse settingSkinList(@RequestHeader String token, HttpServletRequest request, @RequestBody CmnSearch search) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::SETTING::settingSkinList::"+tokenInfo.getSid()+"::::"; + + // POJO to JSON + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(search); + JSONObject reqObj = new JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + // 여기서 부터 로직 + log.info(LOG_PREFIX + "CmnSearch::"+search.toString()); + + List> list = settingService.getSettingSkinList(search); + responseData.put("list", list); + + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(responseData); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping("/vendor/save") + public ApiResponse settingVendorSave(@RequestHeader String token, HttpServletRequest request, @RequestBody List param) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::SETTING::settingSkinList::"+tokenInfo.getSid()+"::::"; + + // POJO to JSON + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(param); + JSONArray reqObj = new JSONArray(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + // 여기서 부터 로직 + log.info(LOG_PREFIX + "List::"+param.toString()); + + for(SiteVendorSkinVO item : param) { + if(!item.getCategory().equals("CASINO") && !item.getCategory().equals("HCASINO")) { + item.setSkinType("A"); + } + + switch (item.getSkinType()) { + case "A": item.setNexusSkinType("A"); + item.setExtrSkinType("1"); + break; + case "B": item.setNexusSkinType("B"); + item.setExtrSkinType("2"); + break; + case "C": item.setNexusSkinType("C"); + item.setExtrSkinType("3"); + break; + case "D": item.setNexusSkinType("D"); + item.setExtrSkinType("4"); + break; + case "E": item.setNexusSkinType("E"); + item.setExtrSkinType("5"); + break; + case "F": item.setNexusSkinType("E"); + item.setExtrSkinType("6"); + break; + case "G": item.setNexusSkinType("E"); + item.setExtrSkinType("7"); + break; + case "H": item.setNexusSkinType("E"); + item.setExtrSkinType("8"); + break; + case "I": item.setNexusSkinType("E"); + item.setExtrSkinType("9"); + break; + case "J": item.setNexusSkinType("E"); + item.setExtrSkinType("10"); + break; + default: item.setNexusSkinType("A"); + item.setExtrSkinType("1"); + break; + } + + + int saveResult = settingService.settingVendorSkinSave(item); + log.info(LOG_PREFIX + "vendorIdx::"+item.getVendorIdx()+"::saveResult::"+saveResult); + } + + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping("/whiteIp") + public ApiResponse whiteIpList(@RequestHeader String token, HttpServletRequest request, @RequestBody CmnSearch search) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::SETTING::whiteIpList::"+tokenInfo.getSid()+"::::"; + + // POJO to JSON + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(search); + JSONObject reqObj = new JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + // 여기서 부터 로직 + if(search.getSiteIdx() == null || search.getSiteIdx() == 0) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("대상이 존재하지 않습니다"); + return apiResponse; + } + log.info(LOG_PREFIX + "CmnSearch::"+search.toString()); + + List list = settingService.getWhiteIpList(search); + responseData.put("list", list); + + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(responseData); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + @ResponseBody + @PostMapping("/getSportsSetting") + public ApiResponse getSportsSetting(@RequestHeader String token, HttpServletRequest request) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::SETTING::getSportsSetting::"+tokenInfo.getSid()+"::::"; + + // 여기서 부터 로직 + HashMap apiInfo = settingService.getBetRadarApiInfo(tokenInfo.getSid()); + if(apiInfo == null || apiInfo.get("apiKey") == null) { + apiResponse.setResultCode("8888"); + apiResponse.setResultMessage("Not found 'BetRadar' settings.."); + log.info(LOG_PREFIX+ "Not found 'BetRadar' settings.."); + return apiResponse; + } + log.info(LOG_PREFIX + "ApiInfo::"+apiInfo.toString()); + + String url = betRadarService.getSportsSetting(LOG_PREFIX, apiInfo); + responseData.put("url", url); + + + } catch(Exception e) { + e.printStackTrace(); + log.info("#-API::SETTING::getSportsSetting::"+ e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(responseData); + apiResponse.success(); + + } catch (Exception e) { + log.info("#-API::SETTING::getSportsSetting::"+ e.toString()); + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } +} diff --git a/src/main/java/com/bb/api/ApiStatController.java b/src/main/java/com/bb/api/ApiStatController.java new file mode 100644 index 0000000..707add6 --- /dev/null +++ b/src/main/java/com/bb/api/ApiStatController.java @@ -0,0 +1,1058 @@ +package com.bb.api; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import com.bb.jwt.JwtManager; +import com.bb.model.ApiResponse; +import com.bb.model.PageFormVO; +import com.bb.model.ReportSearch; +import com.bb.model.Site; +import com.bb.model.SiteSearch; +import com.bb.service.CreditService; +import com.bb.service.SiteService; +import com.bb.service.StatService; +import com.bb.util.DateTimeUtils; +import com.bb.util.IPKit; +import com.bb.util.PagingUtil; +import com.fasterxml.jackson.databind.ObjectMapper; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Controller +@RequiredArgsConstructor +@RequestMapping(value = "/api/v1/stat") +public class ApiStatController { + + @Autowired + StatService statService; + + @Autowired + SiteService siteService; + + @Autowired + CreditService creditService; + + @Autowired + private final JwtManager jwtManager; + + + @ResponseBody + @PostMapping("/error") + public ApiResponse error(@RequestHeader String token, HttpServletRequest request, @RequestBody SiteSearch search) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map data = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::STAT::statMain::"+tokenInfo.getSid()+"::::"; + + // POJO to JSON + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(search); + JSONObject reqObj = new JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + String nowtime = new SimpleDateFormat("yyyy-MM-dd").format(new Date(System.currentTimeMillis())); + if(search.getStartDate() == null || "".equals(search.getStartDate())) { + search.setStartDate(nowtime); + } + + if(search.getEndDate() == null || "".equals(search.getEndDate())) { + search.setEndDate(nowtime); + } + + PageFormVO pageVo= new PageFormVO(); + search.setSiteId(site.getSiteId()); + search.setSiteIdx(site.getSiteIdx()); + + log.info(LOG_PREFIX+ "SiteSearch {}", search); + int totalCount = siteService.getSiteCallbackErrLogListCnt(search); + if (totalCount != 0) { + PageFormVO commonForm = new PageFormVO(); + commonForm.setFunction_name("goPage"); + commonForm.setPage(search.getPage()); + commonForm.setCount_per_page(20); + if(search.getCount_per_list()==0) { + commonForm.setCount_per_list(10); + } else { + commonForm.setCount_per_list(search.getCount_per_list()); + } + commonForm.setTatal_list_count(totalCount); + pageVo = PagingUtil.setPageUtil(commonForm); + search.setLimit(pageVo.getLimit()); + search.setOffset(pageVo.getOffset()); + search.setTatal_list_count(totalCount); + + data.put("pageInfo", pageVo); + } + + log.info(LOG_PREFIX+ "SiteSearch {}", search); + List errorList = siteService.getSiteCallbackErrLogList(search); + data.put("list", errorList); + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(data); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + + @ResponseBody + @PostMapping("/credit") + public ApiResponse credit(@RequestHeader String token, HttpServletRequest request, @RequestBody SiteSearch search) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map data = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::STAT::statMain::credit::"+tokenInfo.getSid()+"::::"; + + // POJO to JSON + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(search); + JSONObject reqObj = new JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + String nowtime = new SimpleDateFormat("yyyy-MM-dd").format(new Date(System.currentTimeMillis())); + if(search.getStartDate() == null || "".equals(search.getStartDate())) { + search.setStartDate(nowtime); + } + + if(search.getEndDate() == null || "".equals(search.getEndDate())) { + search.setEndDate(nowtime); + } + + log.info(LOG_PREFIX+ "BF::SiteSearch {}", search); + + PageFormVO pageVo= new PageFormVO(); + + if(search.getSearchSiteId() == null || "".equals(search.getSearchSiteId())) { + search.setSiteIdx(site.getSiteIdx()); + search.setSiteId(site.getSiteId()); + } else { + Site tergetSite = new Site(); + tergetSite.setSiteId(search.getSearchSiteId()); + tergetSite = siteService.getSite(tergetSite); + search.setSiteIdx(tergetSite.getSiteIdx()); + search.setSiteId(search.getSearchSiteId()); + log.info(LOG_PREFIX+ "tergetSite {}", tergetSite); + } + + log.info(LOG_PREFIX+ "AF::SiteSearch {}", search); + + + int totalCount = creditService.getStatCreditListCnt(search); + if (totalCount != 0) { + PageFormVO commonForm = new PageFormVO(); + commonForm.setFunction_name("goPage"); + commonForm.setPage(search.getPage()); + commonForm.setCount_per_page(20); + if(search.getCount_per_list()==0) { + commonForm.setCount_per_list(10); + } else { + commonForm.setCount_per_list(search.getCount_per_list()); + } + commonForm.setTatal_list_count(totalCount); + pageVo = PagingUtil.setPageUtil(commonForm); + search.setLimit(pageVo.getLimit()); + search.setOffset(pageVo.getOffset()); + search.setTatal_list_count(totalCount); + + data.put("pageInfo", pageVo); + } + + List creditList = creditService.getStatCreditList(search); + /* + List adminBotttomList = creditService.getStatCreditAdminBotttomList(search); + long adminBottomInSum = 0; + long adminBottomOutSum = 0; + for(HashMap item : creditList) { + long tempIn = 0; + long tmpOut = 0; + String aDate = item.get("date").toString(); + for(HashMap botItem : adminBotttomList) { + String bDate = botItem.get("date").toString(); + if(aDate.equals(bDate)) { + item.put("adminBottomIn", botItem.get("adminBottomIn").toString()); + item.put("adminBottomOut", botItem.get("adminBottomOut").toString()); + tempIn = Long.parseLong(botItem.get("adminBottomIn").toString()); + tmpOut = Long.parseLong(botItem.get("adminBottomOut").toString()); + } + } + adminBottomInSum = adminBottomInSum + tempIn; + adminBottomOutSum = adminBottomOutSum + tmpOut; + } + */ + HashMap creditTotal = creditService.getStatCreditTotal(search); + /* + creditTotal.put("adminBottomInSum", Long.toString(adminBottomInSum)); + creditTotal.put("adminBottomOutSum", Long.toString(adminBottomOutSum)); + */ + data.put("list", creditList); + data.put("sum", creditTotal); + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(data); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + + @ResponseBody + @PostMapping("/report") + public ApiResponse report(@RequestHeader String token, HttpServletRequest request, @RequestBody SiteSearch search) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map data = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::STAT::statMain::report::"+tokenInfo.getSid()+"::::"; + + // POJO to JSON + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(search); + JSONObject reqObj = new JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + search.setSiteIdx(site.getSiteIdx()); + if(search.getSearchSiteId()==null || "".equals(search.getSearchSiteId())) { + search.setSiteId(site.getSiteId()); + } else { + search.setSiteId(search.getSearchSiteId()); + } + + if(search.getWithBottomYN() == null || !"Y".equals(search.getWithBottomYN())) { + search.setWithBottomYN("N"); + } + + log.info(LOG_PREFIX+ "SiteSearch::"+search.toString()); + + String startDay = search.getStartDate().substring(0, 10); + String endDay = search.getEndDate().substring(0, 10); + String toDay = new SimpleDateFormat("yyyy-MM-dd").format(new Date(System.currentTimeMillis())); + + log.info(LOG_PREFIX+ "startDay::"+startDay); + log.info(LOG_PREFIX+ "endDay::"+endDay); + log.info(LOG_PREFIX+ "toDay::"+toDay); + + if(startDay.equals(endDay) && startDay.equals(toDay)) { + // 오늘날짜 한정 특별 검색 + List list = statService.getSiteReportListToDay(search); + data.put("list", list); + + List listSum = statService.getSiteReportListSumToDay(search); + data.put("sum",listSum); + } else { + if(search.getSearchMemId()==null || "".equals(search.getSearchMemId())) { + List list = statService.getSiteReportList(search); + data.put("list", list); + + List listSum = statService.getSiteReportListSum(search); + data.put("sum",listSum); + } else { + List list = statService.getSiteReportMemList(search); + data.put("list", list); + + List listSum = statService.getSiteReportMemListSum(search); + data.put("sum",listSum); + } + } + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(data); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + + @ResponseBody + @PostMapping("") + public ApiResponse statMain(@RequestHeader String token, HttpServletRequest request, @RequestBody SiteSearch search) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map data = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::STAT::statMain::"+tokenInfo.getSid()+"::::"; + + // POJO to JSON + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(search); + JSONObject reqObj = new JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + search.setSiteIdx(site.getSiteIdx()); + log.info(LOG_PREFIX+ "SiteSearch::"+search.toString()); + + String prev = statService.getlastMonth(search); + data.put("prev", prev); + + List list = statService.getSiteDailyReportList(search); + data.put("list", list); + + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(data); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping("/bottom") + public ApiResponse bottom(@RequestHeader String token, HttpServletRequest request, @RequestBody SiteSearch search) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map data = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::STAT::bottom::"+tokenInfo.getSid()+"::::"; + + // POJO to JSON + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(search); + JSONObject reqObj = new JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + search.setUpperSiteIdx(site.getSiteIdx()); + log.info(LOG_PREFIX+ "SiteSearch::"+search.toString()); + + String prev = statService.getlastMonth(search); + data.put("prev", prev); + + List list = statService.getBottomSiteDailyReportList(search); + data.put("list", list); + + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(data); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping("/pot") + public ApiResponse mypage(@RequestHeader String token, HttpServletRequest request, @RequestBody SiteSearch search) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map data = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::STAT::pot::"+tokenInfo.getSid()+"::::"; + + // POJO to JSON + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(search); + JSONObject reqObj = new JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + String currDate = DateTimeUtils.getYyyymmdd(); + String yyyy = currDate.substring(0, 4); + search.setSiteIdx(site.getSiteIdx()); + int mm = Integer.parseInt(currDate.substring(4, 6)); + + if(search.getStartDate() == null) { + String mmm = currDate.substring(4, 6); + data.put("yyyy", yyyy); + data.put("mmm", mmm); + search.setStartDate(mmm); + } else { + String mmm = search.getStartDate(); + data.put("yyyy", yyyy); + data.put("mmm", mmm); + search.setStartDate(mmm); + } + + log.info(LOG_PREFIX+ "SiteSearch::"+search.toString()); + + data.put("mm", mm); + + HashMap list = statService.getMonthCredit(search); + data.put("list", list); + + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(data); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping("/casino") + public ApiResponse statCasino(@RequestHeader String token, HttpServletRequest request, @RequestBody SiteSearch search) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map data = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::STAT::pot::"+tokenInfo.getSid()+"::::"; + + // POJO to JSON + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(search); + JSONObject reqObj = new JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + // 여기서 부터 로직 + String nowtime = new SimpleDateFormat("yyyy-MM-dd").format(new Date(System.currentTimeMillis())); + if(search.getStartDate() == null || "".equals(search.getStartDate())) { + search.setStartDate(nowtime); + } + if(search.getEndDate() == null || "".equals(search.getEndDate())) { + search.setEndDate(nowtime); + } + + search.setSiteIdx(site.getSiteIdx()); + log.info(LOG_PREFIX+ "SiteSearch::"+search.toString()); + + List list = statService.getVendorDailyReportList(search); + data.put("list", list); + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(data); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping("/user") + public ApiResponse statUser(@RequestHeader String token, HttpServletRequest request, @RequestBody SiteSearch search) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map data = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::STAT::pot::"+tokenInfo.getSid()+"::::"; + + // POJO to JSON + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(search); + JSONObject reqObj = new JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + // 여기서 부터 로직 + if(search.getStartDate() == null || "".equals(search.getStartDate())) { + String currDate = DateTimeUtils.getYyyymm(); + search.setStartDate(currDate.substring(0, 4)); + search.setEndDate(currDate.substring(4, 6)); + } + + search.setSiteIdx(site.getSiteIdx()); + log.info(LOG_PREFIX+ "SiteSearch::"+search.toString()); + + List list = statService.getUserDailyReportList(search); + data.put("list", list); + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(data); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping("/date") + public ApiResponse statDate(@RequestHeader String token, HttpServletRequest request, @RequestBody SiteSearch search) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map data = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::STAT::pot::"+tokenInfo.getSid()+"::::"; + + // POJO to JSON + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(search); + JSONObject reqObj = new JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + // 여기서 부터 로직 + String nowtime = new SimpleDateFormat("yyyy-MM-dd").format(new Date(System.currentTimeMillis())); + if(search.getStartDate() == null || "".equals(search.getStartDate())) { + search.setStartDate(nowtime); + } + if(search.getEndDate() == null || "".equals(search.getEndDate())) { + search.setEndDate(nowtime); + } + + search.setSiteIdx(site.getSiteIdx()); + log.info(LOG_PREFIX+ "SiteSearch::"+search.toString()); + + List list = statService.getUserReportSum(search); + data.put("list", list); + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(data); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping("/reportday") + public ApiResponse reportDay(@RequestHeader String token, HttpServletRequest request, @RequestBody SiteSearch search) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map data = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::STAT::pot::"+tokenInfo.getSid()+"::::"; + + // POJO to JSON + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(search); + JSONObject reqObj = new JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + // 여기서 부터 로직 + String nowmonth = new SimpleDateFormat("yyyy-MM").format(new Date(System.currentTimeMillis())); + String nowtime = new SimpleDateFormat("yyyy-MM-dd").format(new Date(System.currentTimeMillis())); + if(search.getStartDate() == null || "".equals(search.getStartDate())) { + search.setStartDate(nowmonth+"-01"); + } + if(search.getEndDate() == null || "".equals(search.getEndDate())) { + search.setEndDate(nowtime); + } + + search.setSiteIdx(site.getSiteIdx()); + log.info(LOG_PREFIX+ "SiteSearch::"+search.toString()); + + List list = statService.getVendorDailyReportListDay(search); + List listSUM = statService.getVendorDailyReportListDaySUM(search); + data.put("list", list); + data.put("listSUM", listSUM); + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(data); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping("/reportmonth") + public ApiResponse reportMonth(@RequestHeader String token, HttpServletRequest request, @RequestBody SiteSearch search) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map data = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::STAT::pot::"+tokenInfo.getSid()+"::::"; + + // POJO to JSON + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(search); + JSONObject reqObj = new JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + // 여기서 부터 로직 + String nowmonth = new SimpleDateFormat("yyyy-MM").format(new Date(System.currentTimeMillis())); + String nowtime = new SimpleDateFormat("yyyy-MM-dd").format(new Date(System.currentTimeMillis())); + if(search.getYear() == null || "".equals(search.getYear())) { + search.setStartDate(nowmonth +"-01"); + + String nowmonthArr[] = nowmonth.split("-"); + search.setYear(nowmonthArr[0]); + search.setMonth(nowmonthArr[1]); + } else { + search.setStartDate(search.getYear() +"-"+ search.getMonth() +"-01"); + } + + search.setSiteIdx(site.getSiteIdx()); + log.info(LOG_PREFIX+ "SiteSearch::"+search.toString()); + + List list = statService.getVendorDailyReportListMonth(search); + List listSUM = statService.getVendorDailyReportListMonthSUM(search); + data.put("list", list); + data.put("listSUM", listSUM); + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(data); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping("/std") + public ApiResponse std(@RequestHeader String token, HttpServletRequest request, @RequestBody SiteSearch search) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map data = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::STAT::pot::"+tokenInfo.getSid()+"::::"; + + // POJO to JSON + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(search); + JSONObject reqObj = new JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + // 여기서 부터 로직 + String nowtime = new SimpleDateFormat("yyyy-MM-dd").format(new Date(System.currentTimeMillis())); + if(search.getStartDate() == null || "".equals(search.getStartDate())) { + search.setStartDate(nowtime); + } + if(search.getEndDate() == null || "".equals(search.getEndDate())) { + search.setEndDate(nowtime); + } + + search.setSiteIdx(site.getSiteIdx()); + log.info(LOG_PREFIX+ "SiteSearch::"+search.toString()); + + List list = statService.getUserReportSum(search); + data.put("list", list); + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(data); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping("/hybridReport") + public ApiResponse hybridReport(@RequestHeader String token, HttpServletRequest request, @Valid @RequestBody ReportSearch search) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map data = new HashMap(); + + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::STAT::hybridReport::"+tokenInfo.getSid()+"::::"; + + try { + String toDay = new SimpleDateFormat("yyyy-MM-dd").format(new Date(System.currentTimeMillis())); + String startDay = search.getStartDate().substring(0, 10); + String endDay = search.getEndDate().substring(0, 10); + + search.setIsToday("N"); + if(startDay.equals(toDay) || endDay.equals(toDay)) { + search.setIsToday("Y"); + } + + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(search); + JSONObject reqObj = new JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + if(search.getWithBottomYN().equals("Y")) { + HashMap report = statService.getHybridReport(search); + HashMap reportTotal = statService.getHybridReportTotal(search); + //List list = statService.getHybridReportList(search); + data.put("hReport", report); + data.put("hReportTotal", reportTotal); + data.put("hReportList", null); + } else { + HashMap report = statService.getHybridReport(search); + data.put("hReport", report); + data.put("hReportTotal", null); + data.put("hReportList", null); + } + + } catch(Exception e) { + log.error(LOG_PREFIX+ "EXCEPTION::"+e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(data); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + +} diff --git a/src/main/java/com/bb/api/ApiTransController.java b/src/main/java/com/bb/api/ApiTransController.java new file mode 100644 index 0000000..2e2bf94 --- /dev/null +++ b/src/main/java/com/bb/api/ApiTransController.java @@ -0,0 +1,1710 @@ +package com.bb.api; + +import java.nio.charset.Charset; +import java.security.MessageDigest; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Base64; +import java.util.Calendar; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.WebClientRequestException; +import org.springframework.web.reactive.function.client.WebClientResponseException; +import org.springframework.web.util.UriComponentsBuilder; + +import com.bb.exception.ApiException; +import com.bb.jwt.JwtManager; +import com.bb.model.ApiResponse; +import com.bb.model.BetParam; +import com.bb.model.NexusApiInfo; +import com.bb.model.PageFormVO; +import com.bb.model.Site; +import com.bb.model.TransSearchVO; +import com.bb.service.AsyncSiteService; +import com.bb.service.PandaService; +import com.bb.service.SiteService; +import com.bb.service.ThenutService; +import com.bb.service.TransService; +import com.bb.util.AesUtil; +import com.bb.util.IPKit; +import com.bb.util.PagingUtil; +import com.bb.util.StringUtils; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.gson.Gson; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import okhttp3.OkHttpClient; + +@Slf4j +@Controller +@RequiredArgsConstructor +@RequestMapping(value = "/api/v1/trans") +public class ApiTransController { + + @Autowired + SiteService siteService; + + @Autowired + TransService transService; + + @Autowired + ThenutService thenutService; + + @Autowired + PandaService pandaService; + + @Autowired + WebClient webClient; + + @Autowired + private final JwtManager jwtManager; + + @Autowired + private AsyncSiteService asyncSiteService; + + + @ResponseBody + @PostMapping("/betList") + public ApiResponse betList(@RequestHeader String token, HttpServletRequest request, @Valid @RequestBody TransSearchVO search) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::TRANS::betlist::"+tokenInfo.getSid()+"::::"; + + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(search); + JSONObject reqObj = new JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + // 여기서 부터 로직 + PageFormVO pageVo = new PageFormVO(); + search.setSiteId(site.getSiteId()); + search.setSiteIdx((long) site.getSiteIdx()); + + if(search.getOrderStr() == null || search.getOrderStr().equals("")) { + search.setOrderStr("BETDATE_DESC"); + } + + if(search.getBetWinAmt() == null || search.getBetWinAmt().equals("")) { + search.setBetWinAmt("0"); + } + + search.setTopId(tokenInfo.getSid()); + + + search.setStartDatePartition(StringUtils.convertToDateOnly(search.getStartDate())); + search.setEndDatePartition(StringUtils.convertToDateOnly(search.getEndDate())); + + log.info(LOG_PREFIX+ "TransSearchVO::"+search.toString()); + + if(search.getBetWinAmt().equals("0") && search.getOldYN().equals("N") && search.getWithBottomYN().equals("N") + && (search.getResultInfo()==null || search.getResultInfo().equals(""))) { + // Fast Search + log.info(LOG_PREFIX+ "BetList Fast Search!!!"); + int totalCount = transService.getTransBetFastListCnt(search); + if (totalCount != 0) { + PageFormVO commonForm = new PageFormVO(); + commonForm.setFunction_name("goPage"); + commonForm.setPage(search.getPage()); + commonForm.setCount_per_page(20); + if(search.getCount_per_list()==0) { + commonForm.setCount_per_list(30); + } else { + commonForm.setCount_per_list(search.getCount_per_list()); + } + commonForm.setTatal_list_count(totalCount); + pageVo = PagingUtil.setPageUtil(commonForm); + search.setLimit(pageVo.getLimit()); + search.setOffset(pageVo.getOffset()); + search.setTatal_list_count(totalCount); + + responseData.put("pageInfo", pageVo); + } + + List> fastList = transService.getTransBetFastList(search); + List> list = new ArrayList>(); + for(HashMap item : fastList) { + String refId = item.get("betId"); + search.setRefId(refId); + HashMap betItem = transService.getBetListItem(search); + list.add(betItem); + } + + responseData.put("list", list); + HashMap listSum = transService.getTransBetFastListSum(search); + responseData.put("listSum", listSum); + + log.info(LOG_PREFIX+ "BetList Total count::"+totalCount); + log.info(LOG_PREFIX+ "BetList list count::"+list.size()); + log.info(LOG_PREFIX+ "BetList listSum::"+listSum); + } else { + // ORG Search + log.info(LOG_PREFIX+ "BetList ORG Search!!!"); + int totalCount = transService.getTransBetListCnt(search); + if (totalCount != 0) { + PageFormVO commonForm = new PageFormVO(); + commonForm.setFunction_name("goPage"); + commonForm.setPage(search.getPage()); + commonForm.setCount_per_page(20); + if(search.getCount_per_list()==0) { + commonForm.setCount_per_list(30); + } else { + commonForm.setCount_per_list(search.getCount_per_list()); + } + commonForm.setTatal_list_count(totalCount); + pageVo = PagingUtil.setPageUtil(commonForm); + search.setLimit(pageVo.getLimit()); + search.setOffset(pageVo.getOffset()); + search.setTatal_list_count(totalCount); + + responseData.put("pageInfo", pageVo); + } + + List> list = transService.getTransBetList(search); + responseData.put("list", list); + HashMap listSum = transService.getTransBetListSum(search); + responseData.put("listSum", listSum); + + log.info(LOG_PREFIX+ "BetList Total count::"+totalCount); + log.info(LOG_PREFIX+ "BetList list count::"+list.size()); + log.info(LOG_PREFIX+ "BetList listSum::"+listSum); + } + + } catch(Exception e) { + log.info(e.toString()); + e.printStackTrace(); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(responseData); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping(value="/betDetail") + public ApiResponse betDetail(@RequestHeader String token, HttpServletRequest request, @RequestBody BetParam param) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + JSONObject saveObj = null; + JSONArray saveObjs = null; + boolean isSaveEvoDetail = false; + + try { + // apiKey 체크 + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::TRANS::betDetail::"+tokenInfo.getSid()+"::::"; + + // 여기서 부터 로직 + log.info(LOG_PREFIX+ "BetParam::"+param.toString()); + responseData.put("betId", param.getBetId()); + String dType = "detail_0"; + + HashMap betInfo = transService.getBetInfoByBetId(param); + + if(betInfo == null) { + betInfo = transService.getSiteBetByRefIdFromOld(param); + log.info(LOG_PREFIX+ "betInfo_OLD {}", betInfo); + } + + log.info(LOG_PREFIX+ "betINfp {}", betInfo); + if(betInfo != null) { + param.setBetId(betInfo.get("refId").toString()); + + String category = betInfo.get("vendorCetegory").toString(); + log.info(LOG_PREFIX+ "Game category : " + category); + + if("pragmatic".equals(betInfo.get("vendorCode").toString())) { + dType = "detail_2"; + responseData.put("dType", dType); + + String detailURL = transService.getPragmaticDetails(LOG_PREFIX, betInfo); + if(detailURL != null && !detailURL.equals("")) { + HashMap url = new HashMap(); + url.put("url", detailURL); + responseData.put("detail", url); + } else { + responseData.put("detail", "betId is not exist"); + } + + } else if("svendor".equals(betInfo.get("vendorCode").toString()) + || "pink".equals(betInfo.get("vendorCode").toString())) { + String jsonStr = siteService.getOrgDetailData(param); + log.info(LOG_PREFIX+ "jsonStr : " + jsonStr); + if(jsonStr != null && !"".equals(jsonStr) && !"{}".equals(jsonStr)) { + dType = "detail_6"; + responseData.put("dType", dType); + HashMap detailMap = new Gson().fromJson(jsonStr, HashMap.class); + responseData.put("detail", detailMap); + } else { + isSaveEvoDetail = true; + JSONObject dataObj = transService.getSvendorDetail(LOG_PREFIX, betInfo); + if(dataObj == null) { + responseData.put("detail", "betId is not exist"); + } else { + if(dataObj.has("gameDetail") && !dataObj.isNull("gameDetail")) { + String detailType = StringUtils.getType(dataObj.getString("gameDetail")); + if(detailType.equals("URL")) { + dType = "detail_2"; + responseData.put("dType", dType); + String detailUrl = dataObj.getString("gameDetail"); + HashMap url = new HashMap(); + url.put("url", detailUrl); + responseData.put("detail", url); + } else if(detailType.equals("JSON")) { + dType = "detail_6"; + responseData.put("dType", dType); + JSONObject detailObj = dataObj.getJSONObject("gameDetail"); + saveObj = detailObj; + HashMap detailMap = new Gson().fromJson(detailObj.toString(), HashMap.class); + responseData.put("detail", detailMap); + } else { + apiResponse.put("detail", "betId is not exist"); + } + } else { + responseData.put("detail", "betId is not exist"); + } + } + } + } else if(Integer.parseInt(betInfo.get("vendorIdx").toString())==17 && "tower".equals(betInfo.get("vendorCode").toString())) { + dType = "detail_2"; + responseData.put("dType", dType); + String detailUrl = + betInfo.get("vendorApiUrl").toString() + +"/v2/detail_url" + + "?site_code="+betInfo.get("vendorApiId").toString() + + "&user_id="+betInfo.get("siteHex").toString()+betInfo.get("memberId").toString() + + "&transaction_id="+betInfo.get("transactionId").toString() + + "&vendorCode=pp" + + "&gameCode="+betInfo.get("gameIdx").toString(); + log.info(LOG_PREFIX+" {}" ,detailUrl); + OkHttpClient client = new OkHttpClient().newBuilder().build(); + okhttp3.Request requestok2 = new okhttp3.Request.Builder() + .url(detailUrl) + .method("GET", null)// + .addHeader("User-agent", "Mozilla") + .addHeader("Authorization", betInfo.get("vendorApiKey").toString()) + .build(); + okhttp3.Response response = client.newCall(requestok2).execute(); + + if(response.isSuccessful()){ + okhttp3.ResponseBody body = response.body(); + String responseString = body.string(); + + log.info(LOG_PREFIX+ responseString+" {}" ,StringUtils.extractLink(responseString)); + + HashMap url = new HashMap(); + url.put("url", StringUtils.extractLink(responseString)); + responseData.put("detail", url); + } else { + responseData.put("detail", "betId is not exist"); + } + + } else if(Integer.parseInt(betInfo.get("vendorIdx").toString())==83 && "splus".equals(betInfo.get("vendorCode").toString())) { + log.info(LOG_PREFIX+ "========== BetDetail::Splus =========="); + dType = "detail_1"; + responseData.put("dType", dType); + + HashMap d = new HashMap(); + List splusDetail = siteService.getSplusDetailData(param); + for(HashMap ttype : splusDetail) { + log.info(LOG_PREFIX+ "{}, {}", ttype.get("tranType").toString(), ttype.get("data").toString()); + HashMap detailMap = new Gson().fromJson(ttype.get("data").toString(), HashMap.class); + d.put(ttype.get("tranType").toString(), detailMap); + } + + responseData.put("detail", d); + + } else if("nexus".equals(betInfo.get("vendorCode").toString()) || "ace2".equals(betInfo.get("vendorCode").toString())) { + log.info(LOG_PREFIX+ "========== BetDetail::Hlink or Xtreem =========="); + + String jsonStr = siteService.getOrgDetailData(param); + log.info(LOG_PREFIX+ "jsonStr : " + jsonStr); + if(jsonStr != null && !"".equals(jsonStr) && !"{}".equals(jsonStr)) { + dType = "detail_3"; + responseData.put("dType", dType); + + JSONObject detailObj = new JSONObject(jsonStr); + String gameType = detailObj.optString("gameType"); + JSONArray participants = detailObj.optJSONArray("participants"); + if (participants != null) { + for (int i = 0; i < participants.length(); i++) { + // result 객체 가져오기 (없으면 생성) + JSONObject participant = participants.optJSONObject(i); + JSONObject result = participant.optJSONObject("result"); + if (result == null) { + result = new JSONObject(); + participant.put("result", result); + } + + // link 값 세팅 + String raw = "betId="+param.getBetId()+"&gameType="+gameType; + String encrypted = AesUtil.encrypt(raw); + result.put("link", "https://fst.tx-direction.cc/detailsPage/"+encrypted); + } + } + HashMap detailMap = new Gson().fromJson(detailObj.toString(), HashMap.class); + responseData.put("detail", detailMap); + } else { + isSaveEvoDetail = true; + long siteIdx = (long) betInfo.get("siteIdx"); + long memberIdx = (long) betInfo.get("memberIdx"); + String trxId = betInfo.get("vendorTranKey").toString(); + String apiBaseUrl = betInfo.get("vendorApiUrl").toString(); + String apiAgentId = betInfo.get("vendorApiId").toString(); + String apiSecretKey = betInfo.get("vendorApiKey").toString(); + NexusApiInfo nexusApiInfo = NexusApiInfo.builder() + .siteIdx(siteIdx) + .memberIdx(memberIdx) + .apiBaseUrl(apiBaseUrl) + .agentId(apiAgentId) + .agentSecretKey(apiSecretKey) + .build(); + if("CASINO".equals(betInfo.get("vendorCetegory").toString())) { + dType = "detail_3"; + responseData.put("dType", dType); + JSONObject detailObj = transService.getNexusBetDetail(LOG_PREFIX, nexusApiInfo, trxId); + int resultCode = detailObj.getInt("code"); + if(resultCode == 0) { + JSONArray transactions = detailObj.getJSONArray("transactions"); + if(transactions.length() > 0) { + saveObjs = transactions; + List> detailMap = new Gson().fromJson(transactions.toString(), List.class); + responseData.put("detail", detailMap); + } else { + responseData.put("detail", "betId is not exist"); + } + } else { + responseData.put("detail", "betId is not exist"); + } + } else { + dType = "detail_2"; + responseData.put("dType", dType); + JSONObject detailObj = transService.getNexusBetDetailUrl(LOG_PREFIX, nexusApiInfo, trxId); + log.info(LOG_PREFIX+ "detailObj::"+detailObj.toString()); + int resultCode = detailObj.getInt("code"); + if(resultCode == 0) { + HashMap url = new HashMap<>(); + url.put("url", detailObj.getString("url")); + responseData.put("detail", url); + } else { + responseData.put("detail", "betId is not exist"); + } + } + } + } else if("prime".equals(betInfo.get("vendorCode").toString()) + || "dpcore".equals(betInfo.get("vendorCode").toString())) { + log.info(LOG_PREFIX+ "========== BetDetail::PRIME =========="); + dType = "detail_9"; + responseData.put("dType", dType); + + String jsonStr = siteService.getOrgDetailData(param); + if(jsonStr != null && !"".equals(jsonStr) && !"{}".equals(jsonStr)) { + JSONObject detailObj = new JSONObject(jsonStr); + String gameType = detailObj.optString("gameType"); + JSONArray participants = detailObj.optJSONArray("participants"); + if (participants != null) { + for (int i = 0; i < participants.length(); i++) { + // result 객체 가져오기 (없으면 생성) + JSONObject participant = participants.optJSONObject(i); + JSONObject result = participant.optJSONObject("result"); + if (result == null) { + result = new JSONObject(); + participant.put("result", result); + } + + // link 값 세팅 + String raw = "betId="+param.getBetId()+"&gameType="+gameType; + String encrypted = AesUtil.encrypt(raw); + result.put("link", "https://fst.tx-direction.cc/detailsPage/"+encrypted); + } + } + HashMap detailMap = new Gson().fromJson(detailObj.toString(), HashMap.class); + responseData.put("detail", detailMap); + } else { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + String apiKey = "Bearer "+betInfo.get("vendorApiKey").toString(); + headers.set("Authorization", apiKey); + String detailUrl = betInfo.get("vendorApiUrl").toString() + "/api/getBettingDetails5?"; + String detailParam = "referer="+param.getBetId(); + detailUrl = detailUrl + detailParam; + + log.info(LOG_PREFIX+ "PRIME::Detail Url: " + detailUrl); + log.info(LOG_PREFIX+ "PRIME::Detail Headers: " + headers.toString()); + ResponseEntity response = null; + JSONObject resJson = null; + try { + response = webClient.get() + .uri(detailUrl) + .headers(h -> h.addAll(headers)) + .retrieve() + .toEntity(String.class) + .block(); + } catch(WebClientResponseException e) { + log.error(LOG_PREFIX+ "PRIME::Detail WebClientResponseException : " + e.getMessage()); + log.error(LOG_PREFIX+ "PRIME::Detail status code : " + e.getStatusCode().value()); + log.error(LOG_PREFIX+ "PRIME::Detail response body : " + e.getResponseBodyAsString()); + resJson = new JSONObject(e.getResponseBodyAsString()); + log.error(LOG_PREFIX+ "PRIME::Detail error : " + resJson.getString("message")); + throw new ApiException("P209", resJson.getString("message")); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "PRIME::Detail ConnectTimeoutException::"+rae.getMessage()); + } + if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "PRIME::Detail SocketTimeoutException::"+rae.getMessage()); + } + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "PRIME::Detail InterruptedException::"+rae.getMessage()); + } + throw new ApiException("P210", rae.getMessage()); + } catch (Exception e) { + log.error(LOG_PREFIX+ "PRIME::Detail Exception : " + e.getMessage()); + throw new ApiException("P211", e.getMessage()); + } + + if(response != null && response.getStatusCode() == HttpStatus.OK) { + isSaveEvoDetail = true; + log.info(LOG_PREFIX+ "PRIME::Play response : " + response.getBody()); + resJson = new JSONObject(response.getBody()); + JSONObject dataObj = resJson; + String gameType = dataObj.optString("gameType"); + JSONArray participants = dataObj.optJSONArray("participants"); + if (participants != null) { + for (int i = 0; i < participants.length(); i++) { + // result 객체 가져오기 (없으면 생성) + JSONObject participant = participants.optJSONObject(i); + JSONObject result = participant.optJSONObject("result"); + if (result == null) { + result = new JSONObject(); + participant.put("result", result); + } + + // link 값 세팅 + String raw = "betId="+param.getBetId()+"&gameType="+gameType; + String encrypted = AesUtil.encrypt(raw); + result.put("link", "https://fst.tx-direction.cc/detailsPage/"+encrypted); + } + } + saveObj = dataObj; + HashMap detailMap = new Gson().fromJson(dataObj.toString(), HashMap.class); + responseData.put("detail", detailMap); + } else { + responseData.put("detail", "betId is not exist"); + } + } + } else if("grand".equals(betInfo.get("vendorCode").toString())) { + dType = "detail_2"; + responseData.put("dType", dType); + String detailUrl = + betInfo.get("vendorApiUrl").toString() + +"/transactions/detail" + + "?round_id="+betInfo.get("vendorTranKey").toString(); + log.info(LOG_PREFIX+"Request Url : {}" ,detailUrl); + OkHttpClient client = new OkHttpClient().newBuilder().build(); + okhttp3.Request requestok2 = new okhttp3.Request.Builder() + .url(detailUrl) + .method("GET", null)// + .addHeader("User-agent", "Mozilla") + .addHeader("Authorization", "Bearer "+betInfo.get("vendorApiKey").toString()) + .build(); + okhttp3.Response response = client.newCall(requestok2).execute(); + + if(response.isSuccessful()){ + okhttp3.ResponseBody body = response.body(); + String responseString = body.string(); + log.info(LOG_PREFIX+ "responseString : " , responseString); + JSONObject responseObj = new JSONObject(responseString); + JSONObject dataObj = responseObj.getJSONObject("data"); + if(dataObj != null) { + HashMap url = new HashMap(); + url.put("url", dataObj.getString("url")); + responseData.put("detail", url); + } else { + responseData.put("detail", "betId is not exist"); + } + } else { + responseData.put("detail", "betId is not exist"); + } + } else if("pracp".equals(betInfo.get("vendorCode").toString())) { + dType = "detail_2"; + responseData.put("dType", dType); + + HashMap apiInfo = new HashMap<>(); + apiInfo.put("apiAgentCode", betInfo.get("vendorApiId").toString()); + apiInfo.put("apiToken", betInfo.get("vendorApiKey").toString()); + apiInfo.put("apiBaseUrl", betInfo.get("vendorApiUrl").toString()); + apiInfo.put("uuid", betInfo.get("uuid").toString()); + apiInfo.put("round_id", betInfo.get("roundId").toString()); + + JSONObject dataObj = transService.getPracpDetail(LOG_PREFIX, apiInfo); + log.info(LOG_PREFIX+ "dataObj : " + dataObj.toString()); + if(dataObj != null) { + HashMap url = new HashMap(); + url.put("url", dataObj.getString("url")); + responseData.put("detail", url); + } else { + responseData.put("detail", "betId is not exist"); + } + } else if("tplus".equals(betInfo.get("vendorCode").toString())) { + dType = "detail_2"; + responseData.put("dType", dType); + + String apiBaseUrl = betInfo.get("vendorApiUrl").toString(); + String apiAuthKey = betInfo.get("vendorApiKey").toString(); + String pairTransactionKey = betInfo.get("refId").toString(); + + HashMap apiInfo = new HashMap<>(); + apiInfo.put("apiBaseUrl", apiBaseUrl); + apiInfo.put("apiAuthKey", apiAuthKey); + apiInfo.put("pairTransactionKey", pairTransactionKey); + + log.info(LOG_PREFIX+ "tplus::apiInfo: " + apiInfo.toString()); + + String detailURL = transService.getTplusDetails(LOG_PREFIX, apiInfo); + if(detailURL != null && !detailURL.equals("")) { + HashMap url = new HashMap(); + url.put("url", detailURL); + responseData.put("detail", url); + } else { + responseData.put("detail", "betId is not exist"); + } + } else if("onix".equals(betInfo.get("vendorCode").toString())) { + log.info(LOG_PREFIX+ "========== BetDetail::ONIX =========="); + dType = "detail_8"; + responseData.put("dType", dType); + + String jsonStr = siteService.getOrgDetailData(param); + if(jsonStr != null && !"".equals(jsonStr) && !"{}".equals(jsonStr)) { + JSONObject detailObj = new JSONObject(jsonStr); + String gameType = detailObj.optString("gameType"); + JSONArray participants = detailObj.optJSONArray("participants"); + if (participants != null) { + for (int i = 0; i < participants.length(); i++) { + // result 객체 가져오기 (없으면 생성) + JSONObject participant = participants.optJSONObject(i); + JSONObject result = participant.optJSONObject("result"); + if (result == null) { + result = new JSONObject(); + participant.put("result", result); + } + + // link 값 세팅 + String raw = "betId="+param.getBetId()+"&gameType="+gameType; + String encrypted = AesUtil.encrypt(raw); + result.put("link", "https://fst.tx-direction.cc/detailsPage/"+encrypted); + } + } + HashMap detailMap = new Gson().fromJson(detailObj.toString(), HashMap.class); + responseData.put("detail", detailMap); + } else { + String apiBaseUrl = betInfo.get("vendorApiUrl").toString(); + String fullDateTime = betInfo.get("betTime").toString(); + String dateOnly = fullDateTime.substring(0, 10); + + // Step 1: Get round info from /csapi/getBetting + String bettingUrl = apiBaseUrl + "/csapi/getBetting"; + JSONObject bettingBody = new JSONObject(); + bettingBody.put("userid", betInfo.get("siteIdxHex").toString()+betInfo.get("memberId").toString()); + bettingBody.put("sdate", dateOnly+" 00:00:00.000"); + bettingBody.put("edate", dateOnly+" 23:59:59.999"); + bettingBody.put("pagesize", "1"); + bettingBody.put("gameid", "0"); + bettingBody.put("roundcode", betInfo.get("uuid").toString()); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.set("Authorization", "Bearer " + betInfo.get("vendorApiKey").toString()); + + log.info(LOG_PREFIX+ "ONIX::Step1 getBetting Url: " + bettingUrl); + log.info(LOG_PREFIX+ "ONIX::Step1 getBetting Body: " + bettingBody.toString()); + + try { + ResponseEntity bettingRes = webClient.post() + .uri(bettingUrl) + .headers(h -> h.addAll(headers)) + .bodyValue(bettingBody.toString()) + .retrieve() + .toEntity(String.class) + .block(); + if(bettingRes != null && bettingRes.getBody() != null) { + JSONObject bettingObj = new JSONObject(bettingRes.getBody()); + log.info(LOG_PREFIX+ "ONIX::Step1 getBetting Response: " + bettingObj.toString()); + + int bettingResult = bettingObj.getInt("result"); + if(bettingResult == 1 && bettingObj.has("data")) { + JSONArray dataArray = bettingObj.getJSONArray("data"); + if(dataArray.length() > 0) { + isSaveEvoDetail = true; + JSONObject dataObj = dataArray.getJSONObject(0); + JSONObject detailObj = dataObj.getJSONArray("details").getJSONObject(0); + String gameType = detailObj.optString("gameType"); + JSONArray participants = detailObj.optJSONArray("participants"); + if (participants != null) { + for (int i = 0; i < participants.length(); i++) { + // result 객체 가져오기 (없으면 생성) + JSONObject participant = participants.optJSONObject(i); + JSONObject result = participant.optJSONObject("result"); + if (result == null) { + result = new JSONObject(); + participant.put("result", result); + } + + // link 값 세팅 + String raw = "betId="+param.getBetId()+"&gameType="+gameType; + String encrypted = AesUtil.encrypt(raw); + result.put("link", "https://fst.tx-direction.cc/detailsPage/"+encrypted); + } + } + HashMap detailMap = new Gson().fromJson(detailObj.toString(), HashMap.class); + responseData.put("detail", detailMap); + saveObj = detailObj; + } else { + responseData.put("detail", "betId is not exist"); + } + } else { + responseData.put("detail", "betId is not exist"); + String errorMsg = bettingObj.has("msg") ? bettingObj.getString("msg") : "Unknown error"; + log.error(LOG_PREFIX+ "ONIX::Betting Error: " + errorMsg); + } + } else { + responseData.put("detail", "betId is not exist"); + log.error(LOG_PREFIX+ "ONIX::Betting Response is null"); + } + } catch(WebClientResponseException e) { + log.error(LOG_PREFIX+ "ONIX::Betting HttpClientErrorException : " + e.getMessage()); + log.error(LOG_PREFIX+ "ONIX::Betting status code : " + e.getStatusCode().value()); + log.error(LOG_PREFIX+ "ONIX::Betting response body : " + e.getResponseBodyAsString()); + JSONObject errorJson = new JSONObject(e.getResponseBodyAsString()); + String errorMsg = errorJson.has("msg") ? errorJson.getString("msg") : "Betting API error"; + log.error(LOG_PREFIX+ "ONIX::Betting error : " + errorMsg); + throw new ApiException("P209", errorMsg); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ONIX::Betting ConnectTimeoutException::" + rae.getMessage()); + } + if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "ONIX::Betting ReadTimeoutException::" + rae.getMessage()); + } + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "ONIX::Betting InterruptedException::" + rae.getMessage()); + } + throw new ApiException("P210", rae.getMessage()); + } catch(Exception e) { + log.error(LOG_PREFIX+ "ONIX::Betting Exception : " + e.getMessage()); + throw new ApiException("P211", e.getMessage()); + } + } + } else if("bet_radar".equals(betInfo.get("vendorCode").toString())) { + log.info(LOG_PREFIX+ "========== BetDetail::BET_RADAR =========="); + // TODO: 베팅상세 내려주기 + /* + * param.getBetId() 기준으로 bet_radar_log 테이블 조회시 베팅과 결과 두가지가 나옴. + * 결과가 없는경우 베팅만 한가지 있을 수 있음. + * param.getBetId() 기준 bet_radar_log에서 jsonstr(베팅상세 json 원본)을 가져와서 + * 하나의 json으로 합쳐서 내려주기 구현. + */ + // bet_radar_log 테이블에서 조회 + String radarLogJson = siteService.getMergedBetRadarLog(param.getBetId()); + if(radarLogJson != null && !radarLogJson.isEmpty()) { + log.info(LOG_PREFIX+ "bet_radar_log found, returning merged json"); + dType = "detail_radar"; + responseData.put("dType", dType); + HashMap detailMap = new Gson().fromJson(radarLogJson, HashMap.class); + String detailUrl = "https://sportsbook.spokok.com/bets/detail/"+param.getBetId(); + detailMap.put("dLink", detailUrl); + responseData.put("detail", detailMap); + apiResponse.setData(responseData); + apiResponse.success(); + return apiResponse; + } + + } else if("thenut".equals(betInfo.get("vendorCode").toString())) { + log.info(LOG_PREFIX+ "========== BetDetail::THENUT =========="); + String jsonStr = siteService.getOrgDetailData(param); + log.info(LOG_PREFIX+ "jsonStr : " + jsonStr); + if(jsonStr != null && !"".equals(jsonStr) && !"{}".equals(jsonStr)) { + String detailType = StringUtils.getType(jsonStr); + if(detailType.equals("URL")) { + dType = "detail_2"; + responseData.put("dType", dType); + String detailUrl = jsonStr; + HashMap url = new HashMap<>(); + url.put("url", detailUrl); + responseData.put("detail", url); + } else if(detailType.equals("JSON")) { + dType = "detail_3"; + responseData.put("dType", dType); + + JSONObject detailObj = new JSONObject(jsonStr); + String gameType = detailObj.optString("gameType"); + JSONArray participants = detailObj.optJSONArray("participants"); + if (participants != null) { + for (int i = 0; i < participants.length(); i++) { + // result 객체 가져오기 (없으면 생성) + JSONObject participant = participants.optJSONObject(i); + JSONObject result = participant.optJSONObject("result"); + if (result == null) { + result = new JSONObject(); + participant.put("result", result); + } + + // link 값 세팅 + String raw = "betId="+param.getBetId()+"&gameType="+gameType; + String encrypted = AesUtil.encrypt(raw); + result.put("link", "https://fst.tx-direction.cc/detailsPage/"+encrypted); + } + } + HashMap detailMap = new Gson().fromJson(detailObj.toString(), HashMap.class); + responseData.put("detail", detailMap); + } else { + responseData.put("dType", dType); + responseData.put("detail", "betId is not exist"); + } + } else { + String apiBaseUrl = betInfo.get("vendorApiUrl").toString(); + String apiKey = betInfo.get("vendorApiKey").toString(); + HashMap apiInfo = new HashMap<>(); + apiInfo.put("apiBaseUrl", apiBaseUrl); + apiInfo.put("apiKey", apiKey); + apiInfo.put("betId", param.getBetId()); + + if("CASINO".equals(betInfo.get("vendorCetegory").toString())) { + isSaveEvoDetail = true; + dType = "detail_3"; + responseData.put("dType", dType); + JSONObject detailObj = thenutService.getBetDetail(LOG_PREFIX, apiInfo); + if(detailObj == null) { + responseData.put("detail", "betId is not exist"); + } else { + String gameType = detailObj.optString("gameType"); + JSONArray participants = detailObj.optJSONArray("participants"); + if (participants != null) { + for (int i = 0; i < participants.length(); i++) { + // result 객체 가져오기 (없으면 생성) + JSONObject participant = participants.optJSONObject(i); + JSONObject result = participant.optJSONObject("result"); + if (result == null) { + result = new JSONObject(); + participant.put("result", result); + } + + // link 값 세팅 + String raw = "betId="+param.getBetId()+"&gameType="+gameType; + String encrypted = AesUtil.encrypt(raw); + result.put("link", "https://fst.tx-direction.cc/detailsPage/"+encrypted); + } + } + HashMap detailMap = new Gson().fromJson(detailObj.toString(), HashMap.class); + responseData.put("detail", detailMap); + saveObj = detailObj; + } + } else { + dType = "detail_2"; + responseData.put("dType", dType); + String detailUrl = thenutService.getBetDetailUrl(LOG_PREFIX, apiInfo); + if(detailUrl == null) { + responseData.put("detail", "betId is not exist"); + } else { + log.info(LOG_PREFIX+ "detailUrl::"+detailUrl); + HashMap url = new HashMap<>(); + url.put("url", detailUrl); + responseData.put("detail", url); + } + } + } + } else if("panda".equals(betInfo.get("vendorCode").toString())) { + dType = "detail_2"; + responseData.put("dType", dType); + String apiBaseUrl = betInfo.get("vendorApiUrl").toString(); + String apiKey = betInfo.get("vendorApiKey").toString(); + String tranId = betInfo.get("uuid").toString(); + + HashMap apiInfo = new HashMap<>(); + apiInfo.put("apiBaseUrl", apiBaseUrl); + apiInfo.put("apiKey", apiKey); + apiInfo.put("tranId", tranId); + String detailUrl = pandaService.getDetail(LOG_PREFIX, apiInfo); + if(detailUrl == null) { + responseData.put("detail", "betId is not exist"); + } else { + log.info(LOG_PREFIX+ "detailUrl::"+detailUrl); + HashMap url = new HashMap<>(); + url.put("url", detailUrl); + responseData.put("detail", url); + } + } else { + responseData.put("dType", dType); + responseData.put("detail", "betId is not exist"); + } + } else { + responseData.put("dType", dType); + responseData.put("detail", "betId is not exist"); + } + + if(saveObj != null || saveObjs != null) { + // check detail data + if(isSaveEvoDetail) { + asyncSiteService.insertEvoDetailProc(LOG_PREFIX, param.getBetId(), saveObj, saveObjs); + } + } else { + log.info(LOG_PREFIX+ "saved detail is null"); + } + + } catch(Exception e) { + e.printStackTrace(); + log.error("#-API::TRANS::betDetail::Exception1::" +e.toString()); + log.error("#-API::TRANS::betDetail::Exception1::" +e.getMessage()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(responseData); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + log.error("#-API::TRANS::betDetail::Exception2::" +e.toString()); + log.error("#-API::TRANS::betDetail::Exception2::" +e.getMessage()); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping(value="/nexusDetail") + public ApiResponse nexusDetail(@RequestHeader String token, HttpServletRequest request, @RequestBody BetParam param) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + // apiKey 체크 + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-nexusDetail::"+tokenInfo.getSid()+"::::"; + + // 여기서 부터 로직 + log.info(LOG_PREFIX+ "BetParam::"+param.toString()); + responseData.put("betId", param.getBetId()); + + HashMap betInfo = transService.getBetInfoByBetId(param); + + if(betInfo == null) { + betInfo = transService.getSiteBetByRefIdFromOld(param); + log.info(LOG_PREFIX+ "betInfo_OLD {}", betInfo); + } + + log.info(LOG_PREFIX+ "betINfp {}", betInfo); + if(betInfo != null) { + if("nexus".equals(betInfo.get("vendorCode").toString()) || "xtreem".equals(betInfo.get("vendorCode").toString())) { + log.info(LOG_PREFIX+ "========== BetDetail::Hlink or Xtreem =========="); + + long siteIdx = (long) betInfo.get("siteIdx"); + long memberIdx = (long) betInfo.get("memberIdx"); + String trxId = betInfo.get("vendorTranKey").toString(); + String apiBaseUrl = betInfo.get("vendorApiUrl").toString(); + String apiAgentId = betInfo.get("vendorApiId").toString(); + String apiSecretKey = betInfo.get("vendorApiKey").toString(); + NexusApiInfo nexusApiInfo = NexusApiInfo.builder() + .siteIdx(siteIdx) + .memberIdx(memberIdx) + .apiBaseUrl(apiBaseUrl) + .agentId(apiAgentId) + .agentSecretKey(apiSecretKey) + .build(); + if("CASINO".equals(betInfo.get("vendorCetegory").toString())) { + JSONObject responseObj = transService.getNexusBetDetail(LOG_PREFIX, nexusApiInfo, trxId); + log.info(LOG_PREFIX+ "responseObj {}", responseObj); + + int resultCode = responseObj.getInt("code"); + if(resultCode == 0) { + JSONArray transactions = responseObj.getJSONArray("transactions"); + + // 금애기치환 + JSONObject transaction = transactions.getJSONObject(0); + JSONObject detailObj = transaction.getJSONObject("detail"); + + if(detailObj.isNull("result")) { + // resultObj가 존재하지 않으면 상세가 없다는 뜻. + HashMap detailMap = new HashMap<>(); + detailMap.put("refId", param.getBetId()); + int result = transService.deleteEvoDetailNull(detailMap); + log.info(LOG_PREFIX+ "deleteEvoDetailNull result::" + result + ", refId::"+param.getBetId()); + } else { + HashMap detailMap = new HashMap<>(); + detailMap.put("refId", param.getBetId()); + detailMap.put("orgDetail", detailObj.toString()); + detailMap.put("parDetail", null); + try { + int result = siteService.insertEvoDetail(detailMap); + log.info(LOG_PREFIX+ "insertEvoDetail result::" + result + ", refId::"+param.getBetId()); + // TODO : 베팅상세 파싱 치환 작업 + if(result > 0) { + changePaseDetail(LOG_PREFIX, param.getBetId(), detailObj); + } + + result = transService.deleteEvoDetailNull(detailMap); + log.info(LOG_PREFIX+ "deleteEvoDetailNull result::" + result + ", refId::"+param.getBetId()); + } catch(DataIntegrityViolationException de) { + log.error(LOG_PREFIX+ "Duplicate refId::"+param.getBetId()); + } + } + + } else { + responseData.put("detail", "betId is not exist"); + } + } + } + } + } catch(Exception e) { + e.printStackTrace(); + log.error("#-nexusDetail::Exception1::" +e.toString()); + log.error("#-nexusDetail::Exception1::" +e.getMessage()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(responseData); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + log.error("#-nexusDetail::Exception2::" +e.toString()); + log.error("#-nexusDetail::Exception2::" +e.getMessage()); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @GetMapping("/nexusDetails") + public ApiResponse nexusDetails(HttpServletRequest request, @RequestHeader String token, @RequestParam String startDate, @RequestParam String endDate) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-nexusDetails::"+tokenInfo.getSid()+"::::"; + + if(startDate == null || "".equals(startDate)) { + log.error(LOG_PREFIX+ "startDate is not null or empty or blank"); + apiResponse.setResultCode("-1"); + apiResponse.setResultMessage("startDate is not null or empty or blank"); + return apiResponse; + } + + if(endDate == null || "".equals(endDate)) { + log.error(LOG_PREFIX+ "endDate is not null or empty or blank"); + apiResponse.setResultCode("-2"); + apiResponse.setResultMessage("endDate is not null or empty or blank"); + return apiResponse; + } + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + // 문자열 -> Date + Date date1 = sdf.parse(startDate); + Date date2 = sdf.parse(endDate); + + // Date -> 밀리세컨즈 + long timeMil1 = date1.getTime(); + long timeMil2 = date2.getTime(); + + // 비교 + long diff = timeMil2 - timeMil1; + + long diffMin = diff / (1000 * 60); + + if(diffMin > 60) { + log.error(LOG_PREFIX+ "End_Start_60분_초과"); + apiResponse.setResultCode("-3"); + apiResponse.setResultMessage("End_Start_60분_초과"); + return apiResponse; + } + + startDate = startDate+".000"; + endDate = endDate+".000"; + responseData.put("BF_START_DATE", startDate); + responseData.put("BF_END_DATE", endDate); + + startDate = makeDateStrForUTC(true, makeEdate(startDate)); + endDate = makeDateStrForUTC(true, makeEdate(endDate)); + String nextReqSDate = endDate; + String resultMsg = ""; + int totalCnt = 0; + int bfDataCnt = 0; + int afDataCnt = 0; + int nullDataCnt = 0; + int duplDataCnt = 0; + log.info(LOG_PREFIX+ "Start 시각 : " + startDate); + log.info(LOG_PREFIX+ "End 시각 : " + endDate); + responseData.put("AF_START_DATE", startDate); + responseData.put("AF_END_DATE", endDate); + + // 여기서 부터 로직 + HashMap apiInfo = transService.getApiInfo("nexus"); + // asyncTransService.getNexusEvoDetail(LOG_PREFIX, apiInfo, startDate, endDate); + + log.info(LOG_PREFIX+ "BATCH_INFO::"); + log.info(LOG_PREFIX+ "BATCH_INFO::"); + log.info(LOG_PREFIX+ "BATCH_INFO:: ============================== S T A R T =============================="); + log.info(LOG_PREFIX+ "BATCH_INFO::"); + log.info(LOG_PREFIX+ "BATCH_INFO::apiInfo : " + apiInfo.toString()); + + JSONObject bodyObj = new JSONObject(); + bodyObj.put("vendorKey", "evolution-n"); + bodyObj.put("sdate", startDate); + bodyObj.put("eDate", endDate); + bodyObj.put("username", ""); + bodyObj.put("limit", 2000); + String bodyJson = bodyObj.toString(); + log.info(LOG_PREFIX+ "BATCH_INFO::bodyJson :"+bodyJson); + + HttpHeaders headers = getHeader(LOG_PREFIX, apiInfo, bodyJson); + String apiUrl = apiInfo.get("apiBaseUrl").toString() + "/transaction"; + UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(apiInfo.get("apiBaseUrl").toString() + "/transaction"); + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("vendorKey", "evolution-n"); + params.add("sdate", startDate); + params.add("eDate", endDate); + params.add("username", ""); + params.add("limit", 2000); + log.info(LOG_PREFIX+ "BATCH_INFO::apiUrl :"+apiUrl); + ResponseEntity response = null; + try { + response = webClient.post() + .uri(uriBuilder.toUriString()) + .headers(h -> h.addAll(headers)) + .bodyValue(params) + .retrieve() + .toEntity(String.class) + .block(); + } catch(WebClientResponseException e) { + log.error(LOG_PREFIX+ "BATCH_INFO::WebClientResponseException : " + e.getMessage()); + log.error(LOG_PREFIX+ "BATCH_INFO::status code : " + e.getStatusCode().value()); + log.error(LOG_PREFIX+ "BATCH_INFO::response body : " + e.getResponseBodyAsString()); + throw new ApiException("NX001", e.getResponseBodyAsString()); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "BATCH_INFO::ConnectTimeoutException::"+rae.getMessage()); + } + if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "BATCH_INFO::SocketTimeoutException::"+rae.getMessage()); + } + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "BATCH_INFO::InterruptedException::"+rae.getMessage()); + } + throw new ApiException("NX002", rae.getMessage()); + } catch (Exception e) { + log.error(LOG_PREFIX+ "BATCH_INFO::Exception : " + e.getMessage()); + throw new ApiException("NX003", e.getMessage()); + } + if(response.getStatusCode() == HttpStatus.OK) { + JSONObject responseObj = new JSONObject(response.getBody()); + JSONArray transactionsArr = responseObj.getJSONArray("transactions"); + log.info(LOG_PREFIX+ "BATCH_INFO::transactionsArr.length() : " + transactionsArr.length()); + + totalCnt = transactionsArr.length(); + + for(int i=0; i(); + detailMap.put("refId", refId); + int result = transService.deleteEvoDetailNull(detailMap); + log.info(LOG_PREFIX+ "deleteEvoDetailNull result::" + result + ", refId::"+refId); + + nullDataCnt++; + } else { + HashMap detailMap = new HashMap<>(); + detailMap.put("refId", refId); + detailMap.put("orgDetail", detailObj.toString()); + detailMap.put("parDetail", null); + try { + int result = siteService.insertEvoDetail(detailMap); + log.info(LOG_PREFIX+ "insertEvoDetail result::" + result + ", refId::"+refId); + // TODO : 베팅상세 파싱 치환 작업 + if(result > 0) { + changePaseDetail(LOG_PREFIX, refId, detailObj); + } + + result = transService.deleteEvoDetailNull(detailMap); + log.info(LOG_PREFIX+ "deleteEvoDetailNull result::" + result + ", refId::"+refId); + + afDataCnt++; + } catch(DataIntegrityViolationException de) { + //log.error(LOG_PREFIX+ "Duplicate refId::"+refId); + duplDataCnt++; + } + } + } + } + + resultMsg = "Success"; + + } else { + resultMsg = "Request Fail::"; + log.error(LOG_PREFIX+ "Fail response::"+response.toString()); + } + + responseData.put("resultMsg", resultMsg); + responseData.put("totalCnt", totalCnt); + responseData.put("bfDataCnt", bfDataCnt); + responseData.put("afDataCnt", afDataCnt); + responseData.put("nullDataCnt", nullDataCnt); + responseData.put("duplDataCnt", duplDataCnt); + responseData.put("nextStartDate", nextReqSDate); + + log.info(LOG_PREFIX+ "BATCH_INFO::"); + log.info(LOG_PREFIX+ "BATCH_INFO:: ============================== E N D =============================="); + log.info(LOG_PREFIX+ "BATCH_INFO::"); + log.info(LOG_PREFIX+ "BATCH_INFO::"); + + } catch(Exception e) { + log.info(e.toString()); + e.printStackTrace(); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(responseData); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + private void changePaseDetail(String LOG_PREFIX, String refId, JSONObject detailObj) { + + } + + + @ResponseBody + @PostMapping(value="/betDetail2") + public ApiResponse betDetail2(@RequestHeader String token, HttpServletRequest request, @RequestBody BetParam param) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + // apiKey 체크 + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::TRANS::betDetail::"+tokenInfo.getSid()+"::::"; + + // 여기서 부터 로직 + log.info(LOG_PREFIX+ "BetParam::"+param.toString()); + responseData.put("betId", param.getBetId()); + String betDetail = siteService.getBetInfo(param); + String dType = "detail_0"; + + if("".equals(betDetail) || betDetail == null) { + HashMap betInfo = transService.getBetInfoByBetId(param); + + if(betInfo == null) { + betInfo = transService.getSiteBetByRefIdFromOld(param); + log.info(LOG_PREFIX+ "betInfo_OLD {}", betInfo); + } + + log.info(LOG_PREFIX+ "betINfp {}", betInfo); + if(betInfo != null) { + String category = betInfo.get("vendorCetegory").toString(); + log.info(LOG_PREFIX+ "Game category : " + category); + + if("svendor".equals(betInfo.get("vendorCode").toString())) { + String jsonStr = siteService.getOrgDetailData(param); + log.info(LOG_PREFIX+ "jsonStr : " + jsonStr); + if(jsonStr != null && !"".equals(jsonStr)) { + dType = "detail_6"; + responseData.put("dType", dType); + HashMap detailMap = new Gson().fromJson(jsonStr, HashMap.class); + responseData.put("detail", detailMap); + } else { + JSONObject dataObj = transService.getSvendorDetail(LOG_PREFIX, betInfo); + if(dataObj == null) { + responseData.put("detail", "betId is not exist"); + } else { + if(dataObj.has("gameDetail") && !dataObj.isNull("gameDetail")) { + String gameType = dataObj.getString("game_type"); + if(gameType.equals("slot")) { + dType = "detail_2"; + responseData.put("dType", dType); + String detailUrl = dataObj.getString("gameDetail"); + responseData.put("detail", detailUrl); + } else { + dType = "detail_6"; + responseData.put("dType", dType); + JSONObject detailObj = dataObj.getJSONObject("gameDetail"); + JSONObject parseJsonObj = null; + detailObj.put("parseData", parseJsonObj); + HashMap detailMap = new Gson().fromJson(detailObj.toString(), HashMap.class); + responseData.put("detail", detailMap); + } + } else { + responseData.put("detail", "betId is not exist"); + } + } + } + } else if(Integer.parseInt(betInfo.get("vendorIdx").toString())==17 && "tower".equals(betInfo.get("vendorCode").toString())) { + dType = "detail_2"; + responseData.put("dType", dType); + String detailUrl = + betInfo.get("vendorApiUrl").toString() + +"/v2/detail_url" + + "?site_code="+betInfo.get("vendorApiId").toString() + + "&user_id="+betInfo.get("siteHex").toString()+betInfo.get("memberId").toString() + + "&transaction_id="+betInfo.get("transactionId").toString() + + "&vendorCode=pp" + + "&gameCode="+betInfo.get("gameIdx").toString(); + log.info(LOG_PREFIX+" {}" ,detailUrl); + OkHttpClient client = new OkHttpClient().newBuilder().build(); + okhttp3.Request requestok2 = new okhttp3.Request.Builder() + .url(detailUrl) + .method("GET", null)// + .addHeader("User-agent", "Mozilla") + .addHeader("Authorization", betInfo.get("vendorApiKey").toString()) + .build(); + okhttp3.Response response = client.newCall(requestok2).execute(); + + if(response.isSuccessful()){ + okhttp3.ResponseBody body = response.body(); + String responseString = body.string(); + + log.info(LOG_PREFIX+ responseString+" {}" ,StringUtils.extractLink(responseString)); + + HashMap url = new HashMap(); + url.put("url", StringUtils.extractLink(responseString)); + + responseData.put("detail", url); + } else { + responseData.put("detail", "betId is not exist"); + } + + } else if(Integer.parseInt(betInfo.get("vendorIdx").toString())==83 && "splus".equals(betInfo.get("vendorCode").toString())) { + log.info(LOG_PREFIX+ "========== BetDetail::Splus =========="); + dType = "detail_1"; + responseData.put("dType", dType); + + HashMap d = new HashMap(); + List splusDetail = siteService.getSplusDetailData(param); + for(HashMap ttype : splusDetail) { + log.info(LOG_PREFIX+ "{}, {}", ttype.get("tranType").toString(), ttype.get("data").toString()); + HashMap detailMap = new Gson().fromJson(ttype.get("data").toString(), HashMap.class); + d.put(ttype.get("tranType").toString(), detailMap); + } + + responseData.put("detail", d); + + } else if(Integer.parseInt(betInfo.get("vendorIdx").toString())==17 && "gsoft".equals(betInfo.get("vendorCode").toString())) { + log.info(LOG_PREFIX+ "========== BetDetail::Gsoft =========="); + dType = "detail_2"; + responseData.put("dType", dType); + + String betId = betInfo.get("refId").toString(); + String roundId = transService.getGsoftRoundIdByBetId(betId); + + OkHttpClient client = new OkHttpClient().newBuilder().build(); + okhttp3.Request requestok2 = new okhttp3.Request.Builder() + .url("https://api.iblive.net/api/apigamedetail.aspx?gtype=sxprg&roundId="+roundId) + .method("GET", null)// + .addHeader("User-agent", "Mozilla") + .addHeader("Content-Type", "application/json") + .build(); + okhttp3.Response response = client.newCall(requestok2).execute(); + + if(response.isSuccessful()){ + okhttp3.ResponseBody body = response.body(); + String responseString = body.string(); + log.info(LOG_PREFIX+ responseString+" {}" ,responseString); + + org.codehaus.jettison.json.JSONObject resJson = new org.codehaus.jettison.json.JSONObject(responseString); + + HashMap url = new HashMap(); + url.put("url", resJson.getString("link")); + + responseData.put("detail", url); + } + } else if("nexus".equals(betInfo.get("vendorCode").toString())) { + log.info(LOG_PREFIX+ "========== BetDetail::Hlink or Xtreem =========="); + + String jsonStr = siteService.getOrgDetailData(param); + log.info(LOG_PREFIX+ "jsonStr : " + jsonStr); + if(jsonStr != null && !"".equals(jsonStr)) { + dType = "detail_3"; + responseData.put("dType", dType); + HashMap detailMap = new Gson().fromJson(jsonStr, HashMap.class); + responseData.put("detail", detailMap); + } else { + long siteIdx = (long) betInfo.get("siteIdx"); + long memberIdx = (long) betInfo.get("memberIdx"); + String trxId = betInfo.get("vendorTranKey").toString(); + String apiBaseUrl = betInfo.get("vendorApiUrl").toString(); + String apiAgentId = betInfo.get("vendorApiId").toString(); + String apiSecretKey = betInfo.get("vendorApiKey").toString(); + NexusApiInfo nexusApiInfo = NexusApiInfo.builder() + .siteIdx(siteIdx) + .memberIdx(memberIdx) + .apiBaseUrl(apiBaseUrl) + .agentId(apiAgentId) + .agentSecretKey(apiSecretKey) + .build(); + if("CASINO".equals(betInfo.get("vendorCetegory").toString())) { + dType = "detail_3"; + responseData.put("dType", dType); + JSONObject detailObj = transService.getNexusBetDetail(LOG_PREFIX, nexusApiInfo, trxId); + log.info(LOG_PREFIX+ "detailObj {}", detailObj); + + int resultCode = detailObj.getInt("code"); + if(resultCode == 0) { + JSONArray transactions = detailObj.getJSONArray("transactions"); + if(transactions.length() > 0) { + List> detailMap = new Gson().fromJson(transactions.toString(), List.class); + responseData.put("detail", detailMap); + } else { + responseData.put("detail", "betId is not exist"); + } + } else { + responseData.put("detail", "betId is not exist"); + } + } else { + dType = "detail_2"; + responseData.put("dType", dType); + JSONObject detailObj = transService.getNexusBetDetailUrl(LOG_PREFIX, nexusApiInfo, trxId); + log.info(LOG_PREFIX+ "detailObj::"+detailObj.toString()); + int resultCode = detailObj.getInt("code"); + if(resultCode == 0) { + HashMap detailMap = new HashMap<>(); + detailMap.put("url", detailObj.getString("url")); + responseData.put("detail", detailMap); + } else { + responseData.put("detail", "betId is not exist"); + } + } + } + } else if("honor".equals(betInfo.get("vendorCode").toString()) || "xhlnk".equals(betInfo.get("vendorCode").toString())) { + log.info(LOG_PREFIX+ "========== BetDetail::Honor =========="); + dType = "detail_5"; + responseData.put("dType", dType); + String jsonStr = siteService.getOrgDetailData(param); + log.info(LOG_PREFIX+ "jsonStr : " + jsonStr); + if(jsonStr != null && !"".equals(jsonStr)) { + HashMap detailMap = new Gson().fromJson(jsonStr, HashMap.class); + responseData.put("detail", detailMap); + } else { + responseData.put("detail", "betId is not exist"); + } + } else if("prime".equals(betInfo.get("vendorCode").toString())) { + log.info(LOG_PREFIX+ "========== BetDetail::PRIME =========="); + dType = "detail_9"; + responseData.put("dType", dType); + + String jsonStr = siteService.getOrgDetailData(param); + log.info(LOG_PREFIX+ "jsonStr : " + jsonStr); + if(jsonStr != null && !"".equals(jsonStr)) { + HashMap detailMap = new Gson().fromJson(jsonStr, HashMap.class); + responseData.put("detail", detailMap); + } else { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + String apiKey = "Bearer "+betInfo.get("vendorApiKey").toString(); + headers.set("Authorization", apiKey); + String detailUrl = betInfo.get("vendorApiUrl").toString() + "/api/getBettingDetails5?"; + String detailParam = "referer="+param.getBetId(); + detailUrl = detailUrl + detailParam; + + log.info(LOG_PREFIX+ "PRIME::Detail Url: " + detailUrl); + log.info(LOG_PREFIX+ "PRIME::Detail Headers: " + headers.toString()); + ResponseEntity response = null; + JSONObject resJson = null; + try { + response = webClient.get() + .uri(detailUrl) + .headers(h -> h.addAll(headers)) + .retrieve() + .toEntity(String.class) + .block(); + } catch(WebClientResponseException e) { + log.error(LOG_PREFIX+ "PRIME::Detail WebClientResponseException : " + e.getMessage()); + log.error(LOG_PREFIX+ "PRIME::Detail status code : " + e.getStatusCode().value()); + log.error(LOG_PREFIX+ "PRIME::Detail response body : " + e.getResponseBodyAsString()); + resJson = new JSONObject(e.getResponseBodyAsString()); + log.error(LOG_PREFIX+ "PRIME::Detail error : " + resJson.getString("message")); + throw new ApiException("P209", resJson.getString("message")); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "PRIME::Detail ConnectTimeoutException::"+rae.getMessage()); + } + if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "PRIME::Detail SocketTimeoutException::"+rae.getMessage()); + } + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "PRIME::Detail InterruptedException::"+rae.getMessage()); + } + throw new ApiException("P210", rae.getMessage()); + } catch (Exception e) { + log.error(LOG_PREFIX+ "PRIME::Detail Exception : " + e.getMessage()); + throw new ApiException("P211", e.getMessage()); + } + + if(response != null && response.getStatusCode() == HttpStatus.OK) { + log.info(LOG_PREFIX+ "PRIME::Play response : " + response.getBody()); + resJson = new JSONObject(response.getBody()); + JSONObject dataObj = resJson; + HashMap detailMap = new Gson().fromJson(dataObj.toString(), HashMap.class); + responseData.put("detail", detailMap); + } else { + responseData.put("detail", "betId is not exist"); + } + } + } else { + responseData.put("dType", dType); + responseData.put("detail", "betId is not exist"); + } + } else { + responseData.put("dType", dType); + responseData.put("detail", "betId is not exist"); + } + } else { + responseData.put("dType", dType); + log.info(LOG_PREFIX+ "BetDetail::"+betDetail); + HashMap detailMap = new Gson().fromJson(betDetail, HashMap.class); + responseData.put("detail", detailMap); + } + + } catch(Exception e) { + e.printStackTrace(); + log.error("#-API::TRANS::betDetail::Exception1::" +e.toString()); + log.error("#-API::TRANS::betDetail::Exception1::" +e.getMessage()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(responseData); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + log.error("#-API::TRANS::betDetail::Exception2::" +e.toString()); + log.error("#-API::TRANS::betDetail::Exception2::" +e.getMessage()); + apiResponse.fail(); + } + + return apiResponse; + } + + + + private HttpHeaders getHeader(String LOG_PREFIX, HashMap apiInfo, String bodyJson) { + LOG_PREFIX = LOG_PREFIX + "getHeader::"; + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8"))); + + String hashCode = getHashCode(LOG_PREFIX, bodyJson, apiInfo.get("apiSecretKey").toString()); + headers.set("hash", hashCode); + headers.set("agent", apiInfo.get("apiAgentId").toString()); + log.info(LOG_PREFIX+ "BATCH_INFO::HttpHeaders::"+headers.toString()); + + return headers; + } + + private String getHashCode(String LOG_PREFIX, String body, String secretKey) { + String hashCode = ""; + LOG_PREFIX = LOG_PREFIX + "BATCH_INFO::getHashCode::"; + try { + // Json String Body + Secret Key + String result = body + secretKey; + // String result = "{\"username\":\"057007mptest01\",\"nickname\":\"007mptest01\",\"siteUsername\":\"057007mptest01\"}"; + log.info(LOG_PREFIX+ "BATCH_INFO::Body + Secret Key::"+result); + // SHA-256 Hash make + MessageDigest digestObj = MessageDigest.getInstance("SHA-256"); + byte[] hash_data = digestObj.digest(result.getBytes("UTF-8")); + + // Base64 encoding + hashCode = Base64.getEncoder().encodeToString(hash_data); + log.info(LOG_PREFIX+ "BATCH_INFO::hashCode::"+hashCode); + } catch(Exception e) { + log.error(LOG_PREFIX+ "BATCH_INFO::#-NexusService::getHashCode::Exception::"+e.getMessage()); + } + + return hashCode; + } + + private String makeDateStrForUTC(boolean flag, String strDate) { + String result = ""; + if(flag) { + // 2022-05-01 00:00:00.000 => 2022-05-01T00:00:00.000Z + result = strDate.replace(" ", "T") + "Z"; + } else { + // 2022-05-01T00:00:00.000Z => 2022-05-01 00:00:00.000 + result = strDate.replace("T", " ").replace("Z", ""); + } + return result; + } + + private String makeEdate(String paramDate) { + // TODO Auto-generated method stub + String eDate = ""; + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + try { + Date date = sdf.parse(paramDate); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + calendar.add(Calendar.HOUR_OF_DAY, -9); + Date date2 = calendar.getTime(); + eDate = sdf.format(date2); + } catch(Exception e) { + log.error(e.getMessage()); + } + return eDate; + } + +} diff --git a/src/main/java/com/bb/api/ApiUserController.java b/src/main/java/com/bb/api/ApiUserController.java new file mode 100644 index 0000000..ccc3a18 --- /dev/null +++ b/src/main/java/com/bb/api/ApiUserController.java @@ -0,0 +1,389 @@ +package com.bb.api; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.Valid; + +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import com.bb.jwt.JwtManager; +import com.bb.model.ApiResponse; +import com.bb.model.CashParam; +import com.bb.model.Credit; +import com.bb.model.Member; +import com.bb.model.PageFormVO; +import com.bb.model.Site; +import com.bb.model.UserSearch; +import com.bb.service.CreditService; +import com.bb.service.SiteService; +import com.bb.service.StatService; +import com.bb.util.IPKit; +import com.bb.util.PagingUtil; +import com.fasterxml.jackson.databind.ObjectMapper; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Controller +@RequiredArgsConstructor +@RequestMapping(value = "/api/v1/user") +public class ApiUserController { + + @Autowired + SiteService siteService; + + @Autowired + StatService statService; + + @Autowired + CreditService creditService; + + @Autowired + private final JwtManager jwtManager; + + + @ResponseBody + @PostMapping("/list") + public ApiResponse userList(@RequestHeader String token, HttpServletRequest request, @Valid @RequestBody UserSearch search) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::USER::userList::"+tokenInfo.getSid()+"::::"; + + // 여기서 부터 로직 + + PageFormVO pageVo= new PageFormVO(); + search.setSiteId(site.getSiteId()); + search.setSiteIdx((long) site.getSiteIdx()); + search.setTopId(tokenInfo.getSid()); + + log.info(LOG_PREFIX+ "UserSearch::"+search.toString()); + + int totalCount = siteService.getUserListCnt(search); + if (totalCount != 0) { + PageFormVO commonForm = new PageFormVO(); + commonForm.setFunction_name("goPage"); + commonForm.setPage(search.getPage()); + commonForm.setCount_per_page(20); + if(search.getCount_per_list()==0) { + commonForm.setCount_per_list(30); + } else { + commonForm.setCount_per_list(search.getCount_per_list()); + } + commonForm.setTatal_list_count(totalCount); + pageVo = PagingUtil.setPageUtil(commonForm); + search.setLimit(pageVo.getLimit()); + search.setOffset(pageVo.getOffset()); + search.setTatal_list_count(totalCount); + + responseData.put("pageInfo", pageVo); + } + + List> list = siteService.getUserList(search); + responseData.put("list", list); + + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(responseData); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + + @ResponseBody + @GetMapping("/detail/{siteIdx}/{memberIdx}") + public ApiResponse userDetail( @RequestHeader String token, HttpServletRequest request, @PathVariable long siteIdx, @PathVariable long memberIdx) throws Exception { + + ApiResponse apiResponse = new ApiResponse(); + try { + log.info(token.toString()); + Site site = siteService.getSiteInfoAPI(request); + + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + + if( !( site.getSiteIp() == null || "".equals(site.getSiteIp()) || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0 ) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + apiResponse.setResultMessage("access denied IP"); + return apiResponse; + } + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::USER::userDetail::"+tokenInfo.getSid()+"::::"; + + // 여기서 부터 로직 + UserSearch search = new UserSearch(); + search.setSiteIdx(siteIdx); + search.setMemberIdx(memberIdx); + search.setTopId(tokenInfo.getSid()); + + log.info(LOG_PREFIX+ "UserSearch::"+search.toString()); + + HashMap targetUser = siteService.getUserDetail(search); + responseData.put("targetUser", targetUser); // 유저 상세정보 + + boolean isMyAgent = false; + List treeInfo = (List) targetUser.get("treeInfo"); + for(HashMap item : treeInfo) { + if(tokenInfo.getSid().equals(item.get("upperSiteId").toString())) { + isMyAgent = true; + } + } + if(!isMyAgent) { + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + // TODO : 에이전트 상세 베팅통계 데이터 + // TODO : 에이전트 상세 베팅통계 데이터 + HashMap ydayBetInfo = statService.getYdayBetInfoByUser(targetUser); + log.info(LOG_PREFIX+ "ydayBetInfo {}", ydayBetInfo); + HashMap monthBetInfo = statService.getMonthBetInfoByUser(targetUser); + log.info(LOG_PREFIX+ "monthBetInfo {}", monthBetInfo); + responseData.put("ydayBetInfo", ydayBetInfo); // 어제 배팅통계 + responseData.put("monthBetInfo", monthBetInfo); // 이번달 배팅통계 + + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.setData(responseData); + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping("/cashInOut") + public ApiResponse cashInOut(@RequestHeader String token, HttpServletRequest request, @RequestBody CashParam param) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + try { + Site site = siteService.getSiteInfoAPI(request); + if(site == null) { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + // TO DO 토큰체크 + Map data = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::CASH::cashInOut::"+tokenInfo.getSid()+"::::"; + + // 여기서 부터 로직 + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(param); + JSONObject reqObj = new JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + if("tripleSuper".equals(site.getSiteId())){ + apiResponse.setResultCode("9991"); + apiResponse.setResultMessage("Super admin is not allow"); + return apiResponse; + } + + if("N".equals(site.getIsTransfer())) { + apiResponse.setResultCode("9992"); + apiResponse.setResultMessage("NOT_TRANSFER_SITE"); + return apiResponse; + } + + //회원정보 + param.setSiteIdx(site.getSiteIdx()); + Member member = siteService.getMember2(param); + if(member == null) { + // Fail + log.error(LOG_PREFIX+ "9993:NOT_FOUND_USER"); + apiResponse.setResultCode("9993"); + apiResponse.setResultMessage("NOT_FOUND_USER"); + return apiResponse; + } + log.info(LOG_PREFIX+ "Member::"+member.toString()); + + long amount = Long.parseLong(param.getAmount()); + + // Insert credit_info : MAI, IN / MAO, OUT + Credit credit = new Credit(); + credit.setSiteIdx(site.getSiteIdx()); + credit.setSiteId(site.getSiteId()); + credit.setTargetSiteIdx(member.getMemberIdx()); + credit.setTargetSiteId(member.getMemberId()); + credit.setCreditType(param.getCreditType()); + if("MAI".equals(credit.getCreditType())) { + // 관리자 > 회원 보유금 지급 + long siteCredit = site.getCredit(); + if(siteCredit < amount) { + log.error(LOG_PREFIX+ "9994:사이트 크레딧 부족"); + apiResponse.setResultCode("9994"); + apiResponse.setResultMessage("사이트 크레딧 부족"); + return apiResponse; + } + credit.setCreditRate(null); + credit.setInOut("IN"); + credit.setTranId("회원 보유금 지급"); + credit.setCreditAmt(Long.parseLong(param.getAmount())); + credit.setUserAmt(Long.parseLong(param.getAmount())); + credit.setCreditStatus(1); + credit.setWaitTime(-5); // 재요청 대기시간 5초 + credit.setPreBalance(member.getUserBalance()); + int cnt = creditService.checkRequestTime(credit); + if(cnt > 0) { + // Fail + log.error(LOG_PREFIX+ "T1005:재요청 대기시간 5초"); + apiResponse.setResultCode("T1005"); + apiResponse.setResultMessage("재요청 대기시간 5초"); + return apiResponse; + } + + log.info(LOG_PREFIX+ "Credit::"+credit.toString()); + int result = creditService.insertCreditByCash(credit); + log.info(LOG_PREFIX+ "insertCredit result::"+result); + if(result < 0) { + // Fail + log.error(LOG_PREFIX+ "T1009:DEPOSIT_FAIL"); + apiResponse.setResultCode("T1009"); + apiResponse.setResultMessage("DEPOSIT_FAIL"); + return apiResponse; + } + + } else if("MAO".equals(credit.getCreditType())) { + // 관리자 < 회원 보유금 회수 + long userBalance = member.getUserBalance(); + if(param.getWithAll() != null && param.getWithAll().equals("Y")) { + amount = userBalance; + param.setAmount(Long.toString(amount)); + } + + if(userBalance < amount) { + log.error(LOG_PREFIX+ "9995:유저 잔액 부족"); + apiResponse.setResultCode("9995"); + apiResponse.setResultMessage("유저 잔액 부족"); + return apiResponse; + } + credit.setCreditRate(null); + credit.setInOut("OUT"); + credit.setTranId("회원 보유금 회수"); + credit.setCreditAmt(Long.parseLong(param.getAmount())); + credit.setUserAmt(Long.parseLong(param.getAmount())); + credit.setCreditStatus(1); + credit.setWaitTime(-5); // 재요청 대기시간 5초 + credit.setPreBalance(member.getUserBalance()); + int cnt = creditService.checkRequestTime(credit); + if(cnt > 0) { + // Fail + log.error(LOG_PREFIX+ "T1005:재요청 대기시간 5초"); + apiResponse.setResultCode("T1005"); + apiResponse.setResultMessage("재요청 대기시간 5초"); + return apiResponse; + } + + log.info(LOG_PREFIX+ "Credit::"+credit.toString()); + int result = creditService.insertCreditByCash(credit); + log.info(LOG_PREFIX+ "insertCredit result::"+result); + if(result < 0) { + // Fail + log.error(LOG_PREFIX+ "T1009:WITHDRAW_FAIL"); + apiResponse.setResultCode("T1009"); + apiResponse.setResultMessage("WITHDRAW_FAIL"); + return apiResponse; + } + + } else { + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("알 수 없는 요청"); + return apiResponse; + } + + } catch(Exception e) { + log.error(e.toString()); + e.printStackTrace(); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + apiResponse.success(); + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + +} diff --git a/src/main/java/com/bb/common/bean/RedisSession.java b/src/main/java/com/bb/common/bean/RedisSession.java new file mode 100644 index 0000000..c78a45e --- /dev/null +++ b/src/main/java/com/bb/common/bean/RedisSession.java @@ -0,0 +1,62 @@ +package com.bb.common.bean; + +import java.util.concurrent.TimeUnit; + +import jakarta.annotation.Resource; + +//import org.springframework.data.redis.core.ValueOperations; +import org.springframework.stereotype.Component; + +import com.bb.common.model.OutLoginVO; +import com.bb.util.TempKey; +import com.google.gson.Gson; + + + +//@Component +/* +public class RedisSession { + + @Resource(name="redisTemplate") + private ValueOperations tokens; + private Gson gson = new Gson(); + + public String getToken(OutLoginVO outLoginVO) { + TempKey tempKey = new TempKey(); + String newToken = tempKey.getKey(300); + String oldToken = getCheckId(outLoginVO); + String token = null; + if(oldToken == null) { + token = newToken; + }else { + token = oldToken; + } + setToken(token, outLoginVO); + return token; + } + + private String getCheckId(OutLoginVO outLoginVO) { + String oldToken = (String) tokens.get(outLoginVO.getId()+outLoginVO.getDomain()); + return oldToken; + } + + private void setToken(String token, OutLoginVO outLoginVO) { + if(outLoginVO.getTimeout()==0 || outLoginVO.getTimeUnit()==null) { + tokens.set(token, gson.toJson(outLoginVO), 30, TimeUnit.MINUTES); + tokens.set(outLoginVO.getId()+outLoginVO.getDomain(), token, 30, TimeUnit.MINUTES); + }else { + tokens.set(token, gson.toJson(outLoginVO), outLoginVO.getTimeout(), outLoginVO.getTimeUnit()); + tokens.set(outLoginVO.getId()+outLoginVO.getDomain(), token, outLoginVO.getTimeout(), outLoginVO.getTimeUnit()); + } + } + + public OutLoginVO getUserVO(String token) { + OutLoginVO outLoginVO = gson.fromJson(tokens.get(token), OutLoginVO.class); + if(outLoginVO != null) { + setToken(token, outLoginVO); + } + return outLoginVO; + } + +} +*/ diff --git a/src/main/java/com/bb/common/controller/BetResultProcController.java b/src/main/java/com/bb/common/controller/BetResultProcController.java new file mode 100644 index 0000000..bf504d0 --- /dev/null +++ b/src/main/java/com/bb/common/controller/BetResultProcController.java @@ -0,0 +1,11 @@ +package com.bb.common.controller; + +public class BetResultProcController { + + //베팅결과 가져와서 우리족 디비에넣고 해당사이트에로 연동 URL 보내주기 (베팅 , 당첨 ) + + //해당 사이트 크레딧 처리 + + + +} diff --git a/src/main/java/com/bb/common/model/InChatMessageVO.java b/src/main/java/com/bb/common/model/InChatMessageVO.java new file mode 100644 index 0000000..eed86f2 --- /dev/null +++ b/src/main/java/com/bb/common/model/InChatMessageVO.java @@ -0,0 +1,39 @@ +package com.bb.common.model; + +public class InChatMessageVO { + + private String token; // 사용자 정보를 가져올 토큰 + private String content; // 메세지 내용 + private String type; // 채팅 타입 + private String chatId; // 채팅 고유 아이디 + + public String getToken() { + return token; + } + public void setToken(String token) { + this.token = token; + } + public String getContent() { + return content; + } + public void setContent(String content) { + this.content = content; + } + public String getType() { + return type; + } + public void setType(String type) { + this.type = type; + } + public String getChatId() { + return chatId; + } + public void setChatId(String chatId) { + this.chatId = chatId; + } + @Override + public String toString() { + return "InChatMessageVO [token=" + token + ", content=" + content + ", type=" + type + ", chatId=" + chatId + + "]"; + } +} diff --git a/src/main/java/com/bb/common/model/OutChatMessageVO.java b/src/main/java/com/bb/common/model/OutChatMessageVO.java new file mode 100644 index 0000000..98425be --- /dev/null +++ b/src/main/java/com/bb/common/model/OutChatMessageVO.java @@ -0,0 +1,43 @@ +package com.bb.common.model; + +public class OutChatMessageVO { + + private String id; + private String content; + + + + + public String getId() { + return id; + } + + + + + public void setId(String id) { + this.id = id; + } + + + + + public String getContent() { + return content; + } + + + + + public void setContent(String content) { + this.content = content; + } + + + + + @Override + public String toString() { + return "OutChatMessageVO [id=" + id + ", content=" + content + "]"; + } +} diff --git a/src/main/java/com/bb/common/model/OutLoginVO.java b/src/main/java/com/bb/common/model/OutLoginVO.java new file mode 100644 index 0000000..d612eef --- /dev/null +++ b/src/main/java/com/bb/common/model/OutLoginVO.java @@ -0,0 +1,51 @@ +package com.bb.common.model; + +import java.io.Serializable; +import java.util.concurrent.TimeUnit; + +public class OutLoginVO implements Serializable { + + private static final long serialVersionUID = 1L; + + private String id; + private String name; + private String domain; + private int timeout; + private TimeUnit timeUnit; + + public String getId() { + return id; + } + public void setId(String id) { + this.id = id; + } + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + public String getDomain() { + return domain; + } + public void setDomain(String domain) { + this.domain = domain; + } + public int getTimeout() { + return timeout; + } + public void setTimeout(int timeout) { + this.timeout = timeout; + } + public TimeUnit getTimeUnit() { + return timeUnit; + } + public void setTimeUnit(TimeUnit timeUnit) { + this.timeUnit = timeUnit; + } + @Override + public String toString() { + return "OutLoginVO [id=" + id + ", name=" + name + ", domain=" + domain + ", timeout=" + timeout + ", timeUnit=" + + timeUnit + "]"; + } +} diff --git a/src/main/java/com/bb/config/AccessLogFilter.java b/src/main/java/com/bb/config/AccessLogFilter.java new file mode 100644 index 0000000..e26479d --- /dev/null +++ b/src/main/java/com/bb/config/AccessLogFilter.java @@ -0,0 +1,125 @@ +package com.bb.config; + +/* +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import jakarta.servlet.*; +import jakarta.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.io.UnsupportedEncodingException; + +@Component +public class AccessLogFilter implements Filter { + + private static final Logger LOG = LoggerFactory.getLogger(AccessLogFilter.class); + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + } + + @Override + public void destroy() { + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + CustomRequestWrapper customRequestWrapper = new CustomRequestWrapper((HttpServletRequest) servletRequest); + String accessLog = buildAccessLog(customRequestWrapper); + LOG.info(accessLog); + + try { + filterChain.doFilter(customRequestWrapper, servletResponse); + } finally { + customRequestWrapper.setBody(null); + } + } + + private String buildAccessLog(CustomRequestWrapper customRequestWrapper) { + + String requestURL = getRequestURL(customRequestWrapper); + String remoteAddr = getRemoteAddr(customRequestWrapper); + String method = getMethod(customRequestWrapper); + String queryString = getQueryString(customRequestWrapper); + String requestBody = getRequestBody(customRequestWrapper); + + StringBuilder sb = new StringBuilder(); + sb.append("##### ACCESS LOG {"); + if (requestURL != null) { + sb + .append("\"").append("requestURL").append("\"") + .append(":") + .append("\"").append(requestURL).append("\""); + } + if (remoteAddr != null) { + sb + .append(",") + .append("\"").append("remoteAddr").append("\"") + .append(":") + .append("\"").append(remoteAddr).append("\""); + } + if (method != null) { + sb + .append(",") + .append("\"").append("method").append("\"") + .append(":") + .append("\"").append(method).append("\""); + } + if (queryString != null) { + sb + .append(",") + .append("\"").append("queryString").append("\"") + .append(":") + .append("\"").append(queryString).append("\""); + } + if (requestBody != null && requestBody.length() > 0) { + sb + .append(",") + .append("\"").append("body").append("\"") + .append(":") + .append("\"").append(requestBody).append("\""); + } + sb.append("}"); + return sb.toString(); + } + + private String getRequestBody(CustomRequestWrapper customRequestWrapper) { + String content = null; + String method = customRequestWrapper.getMethod().toLowerCase(); + + // POST, PUT + application/json + if (method.startsWith("p")) { + if (customRequestWrapper.getContentType().toLowerCase().indexOf("json") > 0) { + try { + content = new String(customRequestWrapper.getBody(), customRequestWrapper.getCharacterEncoding()); + } catch (UnsupportedEncodingException e) { + LOG.error(e.getMessage()); + } + } + } + return content; + } + + private String getQueryString(CustomRequestWrapper customRequestWrapper) { + String queryString = null; + if (customRequestWrapper.getQueryString() != null) { + queryString = customRequestWrapper.getQueryString(); + } + return queryString; + } + + private String getMethod(CustomRequestWrapper customRequestWrapper) { + return customRequestWrapper.getMethod(); + } + + private String getRemoteAddr(CustomRequestWrapper customRequestWrapper) { + return customRequestWrapper.getRemoteAddr(); + } + + private String getRequestURL(CustomRequestWrapper customRequestWrapper) { + return customRequestWrapper.getRequestURL().toString(); + } + +} + */ diff --git a/src/main/java/com/bb/config/ApiKeyFilter.java b/src/main/java/com/bb/config/ApiKeyFilter.java new file mode 100644 index 0000000..0b151f5 --- /dev/null +++ b/src/main/java/com/bb/config/ApiKeyFilter.java @@ -0,0 +1,39 @@ +package com.bb.config; + +import java.io.IOException; + +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + + +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; + + +import com.bb.util.StringUtils; + +@Component +public class ApiKeyFilter implements Filter { + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + HttpServletRequest req = (HttpServletRequest) request; + HttpServletResponse res = (HttpServletResponse) response; + + + String reqKey = req.getHeader("Authorization"); + + if (StringUtils.isEmpty(reqKey)) { + + res.setStatus(HttpStatus.UNAUTHORIZED.value()); + } else { + request.setAttribute("Authorization", reqKey); + chain.doFilter(request, response); + } + } +} diff --git a/src/main/java/com/bb/config/AsyncConfig.java b/src/main/java/com/bb/config/AsyncConfig.java new file mode 100644 index 0000000..8404efb --- /dev/null +++ b/src/main/java/com/bb/config/AsyncConfig.java @@ -0,0 +1,59 @@ +package com.bb.config; + +import java.util.concurrent.Executor; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.AsyncConfigurerSupport; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +@Configuration +@EnableAsync +public class AsyncConfig extends AsyncConfigurerSupport { + + // 기본 실행 대기하는 Thread의 수 + private final int CORE_POOL_SIZE = 10; + + // 동시 동작하는 최대 Thread의 수 + private final int MAX_POOL_SIZE = 50; + + // MaxPoolSize 초과 요청에서 Thread 생성 요청 시, 해당 요청을 Queue에 저장하는데 이때 최대 수용 가능한 Queue의 수 + private final int QUEUE_CAPACITY = 500; + + // maxPoolSize가 모두 사용되다가 idle(쓰레드 휴식상태)로 돌아갔을 때 종료하기까지 대기하는 걸리는 시간 + private final int KEEP_ALIVE_SECONDS = 60; + + // 생성되는 Thread 접두사 지정 + private final String CUSTOM_THREAD_NAME_PREFIX = "HSLOT-ASYNC-"; + + // 시스템을 종료(shutdown)할 때 queue에 남아있는 작업을 모두 완료한 후 종료 하도록 처리 + private final boolean WAIT_FOR_TASKS_TO_COMPLETE_ON_SHOUTDOWN = true; + + @Override + public Executor getAsyncExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setCorePoolSize(CORE_POOL_SIZE); + executor.setMaxPoolSize(MAX_POOL_SIZE); + executor.setQueueCapacity(QUEUE_CAPACITY); + executor.setKeepAliveSeconds(KEEP_ALIVE_SECONDS); + executor.setThreadNamePrefix(CUSTOM_THREAD_NAME_PREFIX); + executor.setWaitForTasksToCompleteOnShutdown(WAIT_FOR_TASKS_TO_COMPLETE_ON_SHOUTDOWN); + executor.initialize(); + return executor; + } + + // 포인트 처리 전용 Executor 추가 + @Bean(name = "pointTaskExecutor") + public Executor pointTaskExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setCorePoolSize(5); + executor.setMaxPoolSize(10); + executor.setQueueCapacity(100); + executor.setKeepAliveSeconds(60); + executor.setThreadNamePrefix("PointAsync-"); + executor.setWaitForTasksToCompleteOnShutdown(true); + executor.initialize(); + return executor; + } +} \ No newline at end of file diff --git a/src/main/java/com/bb/config/AuthFailureHandler.java b/src/main/java/com/bb/config/AuthFailureHandler.java new file mode 100644 index 0000000..c9bf26e --- /dev/null +++ b/src/main/java/com/bb/config/AuthFailureHandler.java @@ -0,0 +1,35 @@ +package com.bb.config; + +import java.io.IOException; + +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import javax.xml.transform.Result; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; +import org.springframework.stereotype.Component; + +/** + * 로그인 실패 핸들러 + * + * @author wedul + * + */ +@Component +public class AuthFailureHandler extends SimpleUrlAuthenticationFailureHandler { + + @Override + public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, + AuthenticationException exception) throws IOException, ServletException { + + ObjectMapper om = new ObjectMapper(); + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + //response.getWriter().print(om.writeValueAsString("FAIL")); + //response.getWriter().flush(); + response.sendRedirect(request.getContextPath() + "/login?code=1"); + } +} diff --git a/src/main/java/com/bb/config/AuthProvider.java b/src/main/java/com/bb/config/AuthProvider.java new file mode 100644 index 0000000..3eacac4 --- /dev/null +++ b/src/main/java/com/bb/config/AuthProvider.java @@ -0,0 +1,144 @@ +package com.bb.config; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Repository; + +import com.bb.admin.controller.MainController; +import com.bb.exception.ApiException; +import com.bb.model.OTPInfo; +import com.bb.model.Site; +import com.bb.service.SiteService; +import com.bb.util.TOTPTokenGenerator; + +import lombok.extern.slf4j.Slf4j; + +/** + * Description: 스프링시큐리티 로그인 인증 + * Path : 스프링시큐리티 + * @FileName : AsRepairController.java + * @Version : 2019. 8. 27. + * @Author : LeeChunghan + * @Comment : + */ +@Slf4j +@Component("authProvider") +public class AuthProvider implements AuthenticationProvider { + + @Autowired + SiteService siteService; + + @Override + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + String id = authentication.getName(); + String password = authentication.getCredentials().toString(); + String verificationCode = ((CustomWebAuthenticationDetails) authentication.getDetails()).getVerificationCode(); + + final String LOG_PREFIX = "#-AP::"+id+":::"; + log.info(LOG_PREFIX+ "Authentication::"+authentication.toString()); + log.info(LOG_PREFIX+ "verificationCode::"+verificationCode); + + Site agency = null; + boolean isAdmin = false; + if(!"".equals(id)) { + log.info(LOG_PREFIX+ "Super Login!!!"); + isAdmin = true; + agency = siteService.getSiteLogin(authentication); + } else { + log.info(LOG_PREFIX+ "Guest Login!!!"); + isAdmin = false; + agency = siteService.getGuestLogin(); + id = "oms"; + } + + OTPInfo otpInfo = siteService.getOtpInfo(agency.getSiteIdx()); + if(otpInfo == null || otpInfo.getAccount().equals("")) { + log.error(LOG_PREFIX+ "OTP 정보를 찾을 수 없습니다."); + return null; + } + + if(otpInfo.getSecretKey() == null || otpInfo.getSecretKey().equals("")) { + // Create New OTP + otpInfo = TOTPTokenGenerator.getGoogleAuthQRUrl(otpInfo); + + log.info(LOG_PREFIX+ "makeOtp:: secret : " + otpInfo.getSecretKey()); + log.info(LOG_PREFIX+ "makeOtp::account : " + otpInfo.getAccount()); + log.info(LOG_PREFIX+ "makeOtp:: issuer : " + otpInfo.getIssuer()); + log.info(LOG_PREFIX+ "makeOtp:: URL : " + otpInfo.getUrl()); + + int result = siteService.registSuperOtp(otpInfo); + log.info(LOG_PREFIX+ "makeOtp:: result : " + result); + } else { + log.info(LOG_PREFIX+ "OTP Info : " + otpInfo); + String secret = otpInfo.getSecretKey(); + + if(verificationCode == null || verificationCode.equals("")) { + log.error(LOG_PREFIX+ "OTP 번호를 입력하세요."); + return null; + } + + boolean chkOtp = TOTPTokenGenerator.otpVerify(secret, Integer.parseInt(verificationCode)); + if(!chkOtp) { + log.error(LOG_PREFIX+ "OTP 번호가 일치하지 않습니다."); + return null; + } + } + + if(isAdmin) { + OTPInfo otpManager = siteService.getOtpInfoByManger(agency.getSiteIdx()); + if(otpManager.getSecretKey() == null || otpManager.getSecretKey().equals("")) { + // Create New Manager OTP + otpManager = TOTPTokenGenerator.getGoogleAuthQRUrl(otpManager); + + log.info(LOG_PREFIX+ "Manager makeOtp:: secret : " + otpManager.getSecretKey()); + log.info(LOG_PREFIX+ "ManagermakeOtp::account : " + otpManager.getAccount()); + log.info(LOG_PREFIX+ "ManagermakeOtp:: issuer : " + otpManager.getIssuer()); + log.info(LOG_PREFIX+ "ManagermakeOtp:: URL : " + otpManager.getUrl()); + + log.info(LOG_PREFIX+ "Manager otpManager:: " + otpManager.toString()); + int result = siteService.registSuperOtp(otpManager); + log.info(LOG_PREFIX+ "ManagermakeOtp:: result : " + result); + } + } + + if(agency == null) { + return null; + } else { + Site loginVO = new Site(); + loginVO = agency; + + List roles = new ArrayList(); + if(isAdmin) { + roles.add(new SimpleGrantedAuthority("ROLE_ADMIN")); + } else { + roles.add(new SimpleGrantedAuthority("ROLE_GUEST")); + } + + UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(id, password, roles); + result.setDetails(loginVO); + // log.info(LOG_PREFIX+ "UsernamePasswordAuthenticationToken result::"+result.getDetails().toString()); + + return result; + } + + } + + + + @Override + public boolean supports(Class authentication) { + return authentication.equals(UsernamePasswordAuthenticationToken.class); + } + +} diff --git a/src/main/java/com/bb/config/AuthSuccessHandler.java b/src/main/java/com/bb/config/AuthSuccessHandler.java new file mode 100644 index 0000000..48dc386 --- /dev/null +++ b/src/main/java/com/bb/config/AuthSuccessHandler.java @@ -0,0 +1,89 @@ +package com.bb.config; + +import java.io.IOException; + +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; + +import com.bb.common.model.OutLoginVO; +import com.bb.model.Site; +import com.fasterxml.jackson.databind.ObjectMapper; + +import lombok.extern.slf4j.Slf4j; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; +import org.springframework.security.web.context.HttpSessionSecurityContextRepository; +import org.springframework.security.web.context.SecurityContextRepository; +import org.springframework.stereotype.Component; + +/** + * Description: 스프링시큐리티 인증 성공 핸들러 (Spring Security 6 대응) + * 작성된 코드에서 JSON 출력 로직을 제거하고 명시적 세션 저장을 추가했습니다. + */ +@Slf4j +@Component +public class AuthSuccessHandler extends SimpleUrlAuthenticationSuccessHandler { + + // [1번 방식 핵심] SecurityContextConfig에서 등록한 빈을 주입받아 사용합니다. + // 이를 통해 SecurityConfig와의 순환 참조 문제를 해결합니다. + @Autowired + private SecurityContextRepository securityContextRepository; + + @Override + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, + Authentication authentication) throws ServletException, IOException { + + // 1. [핵심] SecurityContext 생성 및 명시적 저장 + // Spring Security 6부터는 이 과정이 있어야 리다이렉트 후 @Secured가 권한을 올바르게 인식합니다. + SecurityContext context = SecurityContextHolder.createEmptyContext(); + context.setAuthentication(authentication); + SecurityContextHolder.setContext(context); + + // [수정] 빈으로 주입받은 repository를 통해 세션에 SecurityContext를 영구 저장 (Persistence) + securityContextRepository.saveContext(context, request, response); + request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, context); + + // 2. 로그인 사용자 정보 추출 (UserDetails 대신 사용 중인 Site 객체) + Site login = (Site) authentication.getDetails(); + final String LOG_PREFIX = "#-AS::" + (login != null ? login.getSiteId() : "Unknown") + ":::"; + + String authorities = authentication.getAuthorities() + .stream() + .map(GrantedAuthority::getAuthority) + .reduce((a, b) -> a + ", " + b) + .orElse("없음"); + + log.info(LOG_PREFIX + "로그인 성공 - 권한: " + authorities); + + // 3. 커스텀 세션 정보 저장 + HttpSession session = request.getSession(true); + session.setAttribute("user", login); + + // 4. 권한에 따른 리다이렉트 경로 결정 + String targetUrl; + if (authorities.contains("ROLE_ADMIN")) { + // 관리자 세션 추가 정보 설정 (필요 시) + OutLoginVO outLoginVO = new OutLoginVO(); + outLoginVO.setDomain(login != null ? login.getDomain() : ""); + outLoginVO.setId(login != null ? login.getSiteId() : ""); + + targetUrl = "/index"; + } else { + targetUrl = "/guest/simpleReport"; + } + + log.info(LOG_PREFIX + "Redirecting to: " + targetUrl); + + // 5. 리다이렉트 실행 (Clear prior attributes and redirect) + clearAuthenticationAttributes(request); + getRedirectStrategy().sendRedirect(request, response, targetUrl); + + } +} \ No newline at end of file diff --git a/src/main/java/com/bb/config/CachedByteArrayInputStream.java b/src/main/java/com/bb/config/CachedByteArrayInputStream.java new file mode 100644 index 0000000..dc2c480 --- /dev/null +++ b/src/main/java/com/bb/config/CachedByteArrayInputStream.java @@ -0,0 +1,33 @@ +package com.bb.config; + + +import jakarta.servlet.ReadListener; +import jakarta.servlet.ServletInputStream; +import java.io.ByteArrayInputStream; + +public class CachedByteArrayInputStream extends ServletInputStream { + private ByteArrayInputStream in; + + public CachedByteArrayInputStream(byte[] body) { + this.in = new ByteArrayInputStream(body); + } + + @Override + public boolean isFinished() { + return false; + } + + @Override + public boolean isReady() { + return false; + } + + @Override + public void setReadListener(ReadListener readListener) { + } + + @Override + public int read() { + return in.read(); + } +} \ No newline at end of file diff --git a/src/main/java/com/bb/config/CorsConfig.java b/src/main/java/com/bb/config/CorsConfig.java new file mode 100644 index 0000000..20a2e87 --- /dev/null +++ b/src/main/java/com/bb/config/CorsConfig.java @@ -0,0 +1,23 @@ +package com.bb.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class CorsConfig implements WebMvcConfigurer{ + + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/api/**") + .allowedOriginPatterns("*") + .allowedHeaders("*") // 어떤 헤더들을 허용할 것인지 + .allowedMethods("*") // 어떤 메서드를 허용할 것인지 (GET, POST...) + .allowCredentials(false) // 쿠키 요청을 허용한다(다른 도메인 서버 + .maxAge(86400); + + WebMvcConfigurer.super.addCorsMappings(registry); + + } +} diff --git a/src/main/java/com/bb/config/CustomRequestWrapper.java b/src/main/java/com/bb/config/CustomRequestWrapper.java new file mode 100644 index 0000000..490d949 --- /dev/null +++ b/src/main/java/com/bb/config/CustomRequestWrapper.java @@ -0,0 +1,45 @@ +package com.bb.config; + +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequestWrapper; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.IOException; + +public class CustomRequestWrapper extends HttpServletRequestWrapper { + + private byte[] body; + + public CustomRequestWrapper(HttpServletRequest httpServletRequest) { + super(httpServletRequest); + try { +// this.body = IOUtils.toByteArray(httpServletRequest.getInputStream()); + DataInputStream dis = new DataInputStream(httpServletRequest.getInputStream()); + ByteArrayOutputStream os = new ByteArrayOutputStream(); +// byte[] buffer = new byte[0xFFFF]; + byte[] buffer = new byte[1024]; + for (int len = dis.read(buffer); len != -1; len = dis.read(buffer)) { + os.write(buffer, 0, len); + } + os.flush(); + this.body = os.toByteArray(); + } catch (IOException ioe) { + System.out.println("IOException"); + } + } + + public byte[] getBody() { + return body; + } + + public void setBody(byte[] body) { + this.body = body; + } + + @Override + public ServletInputStream getInputStream() { + return new CachedByteArrayInputStream(this.body); + } + +} \ No newline at end of file diff --git a/src/main/java/com/bb/config/CustomServletWrappingFilter.java b/src/main/java/com/bb/config/CustomServletWrappingFilter.java new file mode 100644 index 0000000..66eade9 --- /dev/null +++ b/src/main/java/com/bb/config/CustomServletWrappingFilter.java @@ -0,0 +1,25 @@ +package com.bb.config; + + +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; +import org.springframework.web.util.ContentCachingRequestWrapper; +import org.springframework.web.util.ContentCachingResponseWrapper; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; + +@Component +public class CustomServletWrappingFilter extends OncePerRequestFilter { + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + ContentCachingRequestWrapper wrappingRequest = new ContentCachingRequestWrapper(request); + ContentCachingResponseWrapper wrappingResponse = new ContentCachingResponseWrapper(response); + filterChain.doFilter(wrappingRequest, wrappingResponse); + wrappingResponse.copyBodyToResponse(); + } +} \ No newline at end of file diff --git a/src/main/java/com/bb/config/CustomWebAuthenticationDetails.java b/src/main/java/com/bb/config/CustomWebAuthenticationDetails.java new file mode 100644 index 0000000..5877062 --- /dev/null +++ b/src/main/java/com/bb/config/CustomWebAuthenticationDetails.java @@ -0,0 +1,20 @@ +package com.bb.config; + +import jakarta.servlet.http.HttpServletRequest; + +import org.springframework.security.web.authentication.WebAuthenticationDetails; + +public class CustomWebAuthenticationDetails extends WebAuthenticationDetails { + + private String verificationCode; + + public CustomWebAuthenticationDetails(HttpServletRequest request) { + super(request); + verificationCode = request.getParameter("code"); + } + + public String getVerificationCode() { + return verificationCode; + } + +} diff --git a/src/main/java/com/bb/config/CustomWebAuthenticationDetailsSource.java b/src/main/java/com/bb/config/CustomWebAuthenticationDetailsSource.java new file mode 100644 index 0000000..a058946 --- /dev/null +++ b/src/main/java/com/bb/config/CustomWebAuthenticationDetailsSource.java @@ -0,0 +1,18 @@ +package com.bb.config; + +import jakarta.servlet.http.HttpServletRequest; + +import org.springframework.security.authentication.AuthenticationDetailsSource; +import org.springframework.security.web.authentication.WebAuthenticationDetails; +import org.springframework.stereotype.Component; + +@Component +public class CustomWebAuthenticationDetailsSource implements AuthenticationDetailsSource { + + @Override + public WebAuthenticationDetails buildDetails(HttpServletRequest context) { + // TODO Auto-generated method stub + return new CustomWebAuthenticationDetails(context); + } + +} diff --git a/src/main/java/com/bb/config/DbConfig.java b/src/main/java/com/bb/config/DbConfig.java new file mode 100644 index 0000000..7fe6ce0 --- /dev/null +++ b/src/main/java/com/bb/config/DbConfig.java @@ -0,0 +1,130 @@ +package com.bb.config; + +import java.util.Arrays; +import java.util.HashSet; + +import javax.sql.DataSource; + +import org.apache.ibatis.session.AutoMappingBehavior; +import org.apache.ibatis.session.ExecutorType; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; +import org.apache.ibatis.type.JdbcType; +import org.mybatis.spring.SqlSessionFactoryBean; +import org.mybatis.spring.SqlSessionTemplate; +import org.mybatis.spring.boot.autoconfigure.SpringBootVFS; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.core.io.support.ResourcePatternResolver; + +import com.zaxxer.hikari.HikariDataSource; + +@Configuration +public class DbConfig { + + + + /** DataSource 트리플-Main 생성 */ + @Bean + @Primary + @ConfigurationProperties(prefix = "spring.datasource1") + public DataSource mysql1DataSource() { + return DataSourceBuilder.create() + .type(HikariDataSource.class) + .build(); + } + + /** DataSource 트리플-Sub 생성 */ + @Bean + @ConfigurationProperties(prefix = "spring.datasource2") + public DataSource mysql2DataSource() { + return DataSourceBuilder.create() + .type(HikariDataSource.class) + .build(); + } + + /** sqlSessionFactory 트리플-Main 생성 */ + @Bean + @Primary + public SqlSessionFactory sqlSessionFactoryMain(@Autowired @Qualifier("mysql1DataSource") DataSource dataSource) throws Exception { + // logger.info("SqlSessionFactory Main Start"); + org.apache.ibatis.session.Configuration configuration = this.getMybatisConfig(); + + SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); + factoryBean.setDataSource(dataSource); + factoryBean.setVfs(SpringBootVFS.class); + factoryBean.setConfiguration(configuration); + factoryBean.setTypeHandlersPackage("com.commax.tool.framework.mybatis.typehandler"); + + ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); + Resource[] resource = resolver.getResources("db1/**/*.xml"); + factoryBean.setMapperLocations(resource); + + return factoryBean.getObject(); + } + + /** sqlSessionFactory 트리플-Sub 생성 */ + @Bean + public SqlSessionFactory sqlSessionFactory(@Autowired @Qualifier("mysql2DataSource") DataSource dataSource) throws Exception { + //logger.info("SqlSessionFactory SUB Start"); + org.apache.ibatis.session.Configuration configuration = this.getMybatisConfig(); + + SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); + factoryBean.setDataSource(dataSource); + factoryBean.setVfs(SpringBootVFS.class); + factoryBean.setConfiguration(configuration); + factoryBean.setTypeHandlersPackage("com.commax.tool.framework.mybatis.typehandler"); + + ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); + Resource[] resource = resolver.getResources("db2/**/*.xml"); + factoryBean.setMapperLocations(resource); + + return factoryBean.getObject(); + } + + /** sqlSession 트리플-Main 생성 */ + @Bean + @Primary + public SqlSession sqlSessionMain(@Autowired @Qualifier("sqlSessionFactoryMain") SqlSessionFactory factory) { + return new SqlSessionTemplate(factory); + } + + /** sqlSession 트리플-Sub 생성 */ + @Bean + public SqlSession sqlSessionSub(@Autowired @Qualifier("sqlSessionFactory") SqlSessionFactory factory) { + return new SqlSessionTemplate(factory); + } + + /** MybatisConfig 설정정보 */ + private org.apache.ibatis.session.Configuration getMybatisConfig() { + org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration(); + configuration.setCacheEnabled(true); + configuration.setLazyLoadingEnabled(false); + configuration.setAggressiveLazyLoading(false); + configuration.setMultipleResultSetsEnabled(true); + configuration.setUseColumnLabel(true); + configuration.setAutoMappingBehavior(AutoMappingBehavior.PARTIAL); + configuration.setDefaultExecutorType(ExecutorType.SIMPLE); + configuration.setDefaultStatementTimeout(25000); + configuration.setMapUnderscoreToCamelCase(true); + configuration.setJdbcTypeForNull(JdbcType.NVARCHAR); + configuration.setLazyLoadTriggerMethods(new HashSet<>(Arrays.asList("equals", "clone", "hashCode", "toString"))); + configuration.setLogPrefix("[SQL]"); + + return configuration; + } + + + + + + + +} diff --git a/src/main/java/com/bb/config/GlobalModelAdvice.java b/src/main/java/com/bb/config/GlobalModelAdvice.java new file mode 100644 index 0000000..991434d --- /dev/null +++ b/src/main/java/com/bb/config/GlobalModelAdvice.java @@ -0,0 +1,21 @@ +package com.bb.config; + +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ModelAttribute; + +@ControllerAdvice +public class GlobalModelAdvice { + + @ModelAttribute("currentURI") + public String currentURI(HttpServletRequest request) { + String uri = request.getRequestURI(); + String query = request.getQueryString(); + + // 쿼리 스트링이 있다면 URI 뒤에 붙여서 반환 (예: /insurance/betList?updown=up) + if (query != null && !query.isEmpty()) { + return uri + "?" + query; + } + return uri; + } +} \ No newline at end of file diff --git a/src/main/java/com/bb/config/GuestProvider.java b/src/main/java/com/bb/config/GuestProvider.java new file mode 100644 index 0000000..718c643 --- /dev/null +++ b/src/main/java/com/bb/config/GuestProvider.java @@ -0,0 +1,86 @@ +package com.bb.config; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.stereotype.Component; + +import com.bb.model.OTPInfo; +import com.bb.model.Site; +import com.bb.service.SiteService; +import com.bb.util.TOTPTokenGenerator; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Component("guestProvider") +public class GuestProvider implements AuthenticationProvider { + + @Autowired + SiteService siteService; + + @Override + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + String verificationCode = ((CustomWebAuthenticationDetails) authentication.getDetails()).getVerificationCode(); + + final String LOG_PREFIX = "#-GuestProvider:::"; + log.info(LOG_PREFIX+ "Authentication::"+authentication.toString()); + log.info(LOG_PREFIX+ "verificationCode::"+verificationCode); + + Site guest = siteService.getGuestLogin(); + OTPInfo otpInfo = siteService.getOtpInfo(guest.getSiteIdx()); + + if(otpInfo.getSecretKey() == null || otpInfo.getSecretKey().equals("")) { + // Create New OTP + otpInfo = TOTPTokenGenerator.getGoogleAuthQRUrl(otpInfo); + + log.info(LOG_PREFIX+ "makeOtp:: secret : " + otpInfo.getSecretKey()); + log.info(LOG_PREFIX+ "makeOtp::account : " + otpInfo.getAccount()); + log.info(LOG_PREFIX+ "makeOtp:: issuer : " + otpInfo.getIssuer()); + log.info(LOG_PREFIX+ "makeOtp:: URL : " + otpInfo.getUrl()); + + int result = siteService.registSuperOtp(otpInfo); + log.info(LOG_PREFIX+ "makeOtp:: result : " + result); + } else { + log.info(LOG_PREFIX+ "OTP Info : " + otpInfo); + String secret = otpInfo.getSecretKey(); + + if(verificationCode == null || verificationCode.equals("")) { + log.error(LOG_PREFIX+ "OTP 번호를 입력하세요."); + return null; + } + + boolean chkOtp = TOTPTokenGenerator.otpVerify(secret, Integer.parseInt(verificationCode)); + if(!chkOtp) { + log.error(LOG_PREFIX+ "OTP 번호가 일치하지 않습니다."); + return null; + } + } + + if(guest == null) { + return null; + } else { + List roles = new ArrayList(); + roles.add(new SimpleGrantedAuthority("GUEST")); + + UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken("oms", "ehfrhfo22#", roles); + result.setDetails(guest); + + return result; + } + } + + @Override + public boolean supports(Class authentication) { + // TODO Auto-generated method stub + return authentication.equals(UsernamePasswordAuthenticationToken.class); + } + +} diff --git a/src/main/java/com/bb/config/HttpInterceptor.java b/src/main/java/com/bb/config/HttpInterceptor.java new file mode 100644 index 0000000..325423b --- /dev/null +++ b/src/main/java/com/bb/config/HttpInterceptor.java @@ -0,0 +1,83 @@ +package com.bb.config; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; + + +import com.bb.util.StringUtils; + + +import lombok.extern.slf4j.Slf4j; + +import java.io.DataInputStream; +import java.util.Enumeration; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +@Slf4j +@Component +public class HttpInterceptor implements HandlerInterceptor { + private final static String REQUEST_POST = "POST"; + + + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + log.info("Requested Domain (Host): {}", request.getHeader("Host")); + log.info("[preHandle]"+request.getRequestURI() +","+request.getMethod()); + + + log.info("___________________Parameter____________________________ "); + + Enumeration params = request.getParameterNames(); + while (params.hasMoreElements()) { + String name = (String) params.nextElement(); + String value = request.getParameter(name); + log.info(name + "=" + value); + } + + + log.info("____________________________ Header ____________________________ "); + + Enumeration headers = request.getHeaderNames(); + while (headers.hasMoreElements()) { + String name = (String) headers.nextElement(); + String value = request.getHeader(name); + log.info(name + "=" + value); + } + + + log.info("____________________________ Request Body ____________________________ "); + /* + try { + DataInputStream dis = new DataInputStream(request.getInputStream()); + String str = null; + while ((str = dis.readLine()) != null) { + log.info(new String(str.getBytes("ISO-8859-1"), "euc-kr")+"
"); + // utf-8로 전송된 한글은 깨짐 + + } + }catch(Exception e) { + log.info("ERROR E : {}", e.getMessage()); + } + */ + return true; + } + + @Override + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { + log.info("[postHandle]"+request.getRequestURI()); + } + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object object, Exception ex) throws Exception { + log.info("[afterCompletion]"+request.getRequestURI()); + } + +} + diff --git a/src/main/java/com/bb/config/InterceptorConfig.java b/src/main/java/com/bb/config/InterceptorConfig.java new file mode 100644 index 0000000..0f6b8d6 --- /dev/null +++ b/src/main/java/com/bb/config/InterceptorConfig.java @@ -0,0 +1,17 @@ +package com.bb.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class InterceptorConfig implements WebMvcConfigurer { + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(new HttpInterceptor()) + .addPathPatterns("/api/*") .addPathPatterns("/api/**") + .excludePathPatterns("/api/login", "/api/signUp"); // 해당 경로는 인터셉터가 가로채지 않는다. + } +} + + diff --git a/src/main/java/com/bb/config/OpenapiConfig.java b/src/main/java/com/bb/config/OpenapiConfig.java new file mode 100644 index 0000000..468bdbd --- /dev/null +++ b/src/main/java/com/bb/config/OpenapiConfig.java @@ -0,0 +1,55 @@ +package com.bb.config; + +// 중요: 패키지 경로에 .models 가 추가되었습니다. +import org.springdoc.core.models.GroupedOpenApi; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn; +import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; +import io.swagger.v3.oas.annotations.info.Info; +import io.swagger.v3.oas.annotations.security.SecurityScheme; +import io.swagger.v3.oas.annotations.servers.Server; + +@Configuration +@OpenAPIDefinition( + servers = { + @Server(url = "https://oprvender.com"), + @Server(url = "http://localhost"), + @Server(url = "http://lz.akrra.cc") + }, + info = @Info(title = "My API", version = "v1") +) +@SecurityScheme( + name = "Authorization", + scheme = "basic", + type = SecuritySchemeType.APIKEY, + in = SecuritySchemeIn.HEADER +) +public class OpenapiConfig { + + @Bean + public GroupedOpenApi publicOpenAPI() { + return GroupedOpenApi.builder() + .group("front") + .packagesToScan("com.bb.front") + .build(); + } + + @Bean + public GroupedOpenApi adminAPI() { + return GroupedOpenApi.builder() + .group("admin") + .packagesToScan("com.bb.admin") + .build(); + } + + @Bean + public GroupedOpenApi commonAPI() { + return GroupedOpenApi.builder() + .group("common") + .packagesToScan("com.bb.common") + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/com/bb/config/RedisConfig.java b/src/main/java/com/bb/config/RedisConfig.java new file mode 100644 index 0000000..a9bb656 --- /dev/null +++ b/src/main/java/com/bb/config/RedisConfig.java @@ -0,0 +1,26 @@ +package com.bb.config; + +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +//import org.springframework.data.redis.connection.RedisConnectionFactory; +//import org.springframework.data.redis.core.StringRedisTemplate; +/* +@Configuration +public class RedisConfig { + + @Bean + public StringRedisTemplate stringRedisTemplate( + @Qualifier("redisConnectionFactory") RedisConnectionFactory redisConnectionFactory + ) { + + StringRedisTemplate template = new StringRedisTemplate(); + template.setConnectionFactory(redisConnectionFactory); + + return template; + } + + + +} +*/ diff --git a/src/main/java/com/bb/config/RestTemplateConfig.java b/src/main/java/com/bb/config/RestTemplateConfig.java new file mode 100644 index 0000000..cff219f --- /dev/null +++ b/src/main/java/com/bb/config/RestTemplateConfig.java @@ -0,0 +1,43 @@ +package com.bb.config; + +import org.apache.hc.client5.http.classic.HttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.web.client.RestTemplate; + +@Configuration +public class RestTemplateConfig { + + @Bean + public HttpClient httpClient() { + // HttpClient 5에서는 PoolingHttpClientConnectionManager를 사용하여 커넥션 풀을 관리합니다. + PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(); + connectionManager.setMaxTotal(4096); // 최대 오픈되는 커넥션 수 + connectionManager.setDefaultMaxPerRoute(200); // IP, 포트 1쌍에 대해 수행할 커넥션 수 + + return HttpClientBuilder.create() + .setConnectionManager(connectionManager) + .build(); + } + + @Bean + public HttpComponentsClientHttpRequestFactory factory(HttpClient httpClient) { + // HttpClient 5를 사용하는 팩토리 생성 + HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient); + + // Spring Boot 3/HttpClient 5에서는 타임아웃 설정을 팩토리에서 직접 관리하거나 + // 필요한 경우 빌더 단계에서 설정합니다. + factory.setConnectTimeout(3000); // 연결시간초과, ms + // 주의: v5용 팩토리에서 setReadTimeout은 지원되지 않을 수 있으므로, + // 런타임 에러 시 빌더의 RequestConfig 설정을 사용해야 합니다. + return factory; + } + + @Bean + public RestTemplate restTemplate(HttpComponentsClientHttpRequestFactory factory) { + return new RestTemplate(factory); + } +} \ No newline at end of file diff --git a/src/main/java/com/bb/config/SecurityConfig.java b/src/main/java/com/bb/config/SecurityConfig.java new file mode 100644 index 0000000..965edc8 --- /dev/null +++ b/src/main/java/com/bb/config/SecurityConfig.java @@ -0,0 +1,122 @@ +package com.bb.config; + +import java.util.Arrays; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; +import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler; +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.context.SecurityContextRepository; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.CorsConfigurationSource; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Configuration +@EnableWebSecurity +@EnableMethodSecurity(securedEnabled = true, prePostEnabled = true, proxyTargetClass = true) // EnableGlobalMethodSecurity 대체 +@ComponentScan(basePackages = {"com.bb.*"}) +public class SecurityConfig { + + @Autowired + AuthProvider authProvider; + + @Autowired + AuthFailureHandler authFailureHandler; + + @Autowired + AuthSuccessHandler authSuccessHandler; + + @Autowired + CustomWebAuthenticationDetailsSource authenticationDetailsSource; + + static final String SERVER_HOST_1 = "139-162-90-184.ip.linodeusercontent.com"; + static final String SERVER_HOST_2 = "139-162-90-179.ip.linodeusercontent.com"; + + @Bean + public MethodSecurityExpressionHandler methodSecurityExpressionHandler() { + DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler(); + // ROLE_ 접두사 규칙을 강제합니다. + expressionHandler.setDefaultRolePrefix("ROLE_"); + return expressionHandler; + } + /** + * 기존 web.ignoring() 설정 부분 + */ + @Bean + public WebSecurityCustomizer webSecurityCustomizer() { + return (web) -> web.ignoring().requestMatchers( + "/v3/api-docs", "/swagger-resources/**", "/webjars/**", "/swagger/**", "/favicon.ico", + "/html/**", "/resources/**", "/websocket", "/websocket/**", "/images/**", + "/img/**", "/css/**", "/js/**" + ); + } + + /** + * 관리자 및 메인 보안 설정 (SecurityFilterChain) + */ + @Bean + public SecurityFilterChain filterChain(HttpSecurity http, SecurityContextRepository securityContextRepository) throws Exception { + + http + .cors(cors -> cors.configurationSource(corsConfigurationSource())) + .csrf(csrf -> csrf.disable()) + .headers(headers -> headers.frameOptions(frame -> frame.disable())) + .securityContext(context -> context + .securityContextRepository(securityContextRepository) + ) + .authenticationProvider(authProvider); + + http.authorizeHttpRequests(auth -> auth + .requestMatchers("/", "/login/**", "/lg/**", "/api/**", "/actuator/**", "/lunch/**", "/websocket", "/websocket/**", "/guest/guestLogin").permitAll() + .anyRequest().authenticated() + ); + + http.formLogin(form -> form + .loginPage("/lg") + .loginProcessingUrl("/authenticate") + .failureHandler(authFailureHandler) + .successHandler(authSuccessHandler) + .usernameParameter("id") + .passwordParameter("pw") + .authenticationDetailsSource(authenticationDetailsSource) + ); + + return http.build(); + } + + @Bean + public FilterRegistrationBean filterRegistrationBean() { + FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); + ApiKeyFilter customURLFilter = new ApiKeyFilter(); + + registrationBean.setFilter(customURLFilter); + registrationBean.addUrlPatterns("/api/login"); + registrationBean.setOrder(1); + + return registrationBean; + } + + @Bean + public CorsConfigurationSource corsConfigurationSource() { + final CorsConfiguration configuration = new CorsConfiguration(); + configuration.setAllowedOriginPatterns(Arrays.asList("*")); + configuration.addAllowedHeader("*"); + configuration.addAllowedMethod("*"); + configuration.setAllowCredentials(false); + + final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", configuration); + return source; + } +} diff --git a/src/main/java/com/bb/config/SecurityContextConfig.java b/src/main/java/com/bb/config/SecurityContextConfig.java new file mode 100644 index 0000000..ee30bba --- /dev/null +++ b/src/main/java/com/bb/config/SecurityContextConfig.java @@ -0,0 +1,26 @@ +package com.bb.config; + +import jakarta.annotation.PostConstruct; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.context.HttpSessionSecurityContextRepository; +import org.springframework.security.web.context.SecurityContextRepository; + +@Configuration // @Component보다 설정을 위한 @Configuration 권장 +public class SecurityContextConfig { + + @PostConstruct + public void init() { + // 부모 스레드의 SecurityContext를 자식 스레드에서 상속받도록 설정 + SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL); + } + + /** + * [핵심] 세션 저장소를 빈으로 등록하여 순환 참조 방지 및 공유 + */ + @Bean + public SecurityContextRepository securityContextRepository() { + return new HttpSessionSecurityContextRepository(); + } +} \ No newline at end of file diff --git a/src/main/java/com/bb/config/WebClientConfig.java b/src/main/java/com/bb/config/WebClientConfig.java new file mode 100644 index 0000000..e47f160 --- /dev/null +++ b/src/main/java/com/bb/config/WebClientConfig.java @@ -0,0 +1,43 @@ +package com.bb.config; + +import io.netty.channel.ChannelOption; +import io.netty.handler.timeout.ReadTimeoutHandler; +import io.netty.handler.timeout.WriteTimeoutHandler; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.reactive.ReactorClientHttpConnector; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.netty.http.client.HttpClient; +import reactor.netty.resources.ConnectionProvider; + +import java.time.Duration; +import java.util.concurrent.TimeUnit; + +@Configuration +public class WebClientConfig { + + @Bean + public WebClient webClient() { + // 1. 커넥션 풀 설정 + ConnectionProvider provider = ConnectionProvider.builder("my-connection-pool") + .maxConnections(4096) // 기존 MaxTotal(4096)과 매칭 + .pendingAcquireTimeout(Duration.ofMillis(3000)) + .maxIdleTime(Duration.ofSeconds(20)) + .build(); + + // 2. 타임아웃 및 Netty HttpClient 설정 + HttpClient httpClient = HttpClient.create(provider) + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000) // 기존 ConnectTimeout(3000)과 매칭 + .responseTimeout(Duration.ofSeconds(8)) // 응답 대기 시간 + .doOnConnected(conn -> + conn.addHandlerLast(new ReadTimeoutHandler(9, TimeUnit.SECONDS)) + .addHandlerLast(new WriteTimeoutHandler(9, TimeUnit.SECONDS)) + ); + + // 3. WebClient 빈 생성 + return WebClient.builder() + .clientConnector(new ReactorClientHttpConnector(httpClient)) + .codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(2 * 1024 * 1024)) // 2MB + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/com/bb/config/WebSocketConfig.java b/src/main/java/com/bb/config/WebSocketConfig.java new file mode 100644 index 0000000..c2feaad --- /dev/null +++ b/src/main/java/com/bb/config/WebSocketConfig.java @@ -0,0 +1,32 @@ +package com.bb.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.messaging.simp.config.ChannelRegistration; +import org.springframework.messaging.simp.config.MessageBrokerRegistry; +import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; +import org.springframework.web.socket.config.annotation.StompEndpointRegistry; +import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; // 인터페이스로 변경 + +@Configuration +@EnableWebSocketMessageBroker +public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { // implements로 변경 + + @Override + public void configureMessageBroker(MessageBrokerRegistry config) { + config.enableSimpleBroker("/topic"); + config.setApplicationDestinationPrefixes("/app"); + } + + @Override + public void registerStompEndpoints(StompEndpointRegistry registry) { + // 기존 allowedOriginPatterns("*") 유지 + registry.addEndpoint("/websocket") + .setAllowedOriginPatterns("*") + .withSockJS(); + } + + @Override + public void configureClientInboundChannel(ChannelRegistration registration) { + registration.interceptors(new WebSocketInterceptor()); + } +} \ No newline at end of file diff --git a/src/main/java/com/bb/config/WebSocketInterceptor.java b/src/main/java/com/bb/config/WebSocketInterceptor.java new file mode 100644 index 0000000..7da575a --- /dev/null +++ b/src/main/java/com/bb/config/WebSocketInterceptor.java @@ -0,0 +1,32 @@ +package com.bb.config; + +import java.util.HashSet; +import java.util.Set; +import org.apache.commons.lang3.StringUtils; +import org.springframework.messaging.Message; +import org.springframework.messaging.MessageChannel; +import org.springframework.messaging.support.ChannelInterceptor; // 인터페이스로 변경 +import org.springframework.stereotype.Component; + +@Component +public class WebSocketInterceptor implements ChannelInterceptor { // implements로 변경 + Set sessionSet = new HashSet<>(); + + @Override + public Message preSend(Message message, MessageChannel channel) { + String simpMessageType = String.valueOf(message.getHeaders().get("simpMessageType")); + + if(StringUtils.equals(simpMessageType, "CONNECT")) { + String simpSessionId = String.valueOf(message.getHeaders().get("simpSessionId")); + sessionSet.add(simpSessionId); + } else if(StringUtils.equals(simpMessageType, "DISCONNECT")) { + String simpSessionId = String.valueOf(message.getHeaders().get("simpSessionId")); + sessionSet.remove(simpSessionId); + } + + // int uniqueJoinSessionCount = sessionSet.size(); + + // 인터페이스에는 super.preSend()가 없으므로 message를 그대로 리턴합니다. + return message; + } +} \ No newline at end of file diff --git a/src/main/java/com/bb/controller/PragmaticController.java b/src/main/java/com/bb/controller/PragmaticController.java new file mode 100644 index 0000000..cbf3586 --- /dev/null +++ b/src/main/java/com/bb/controller/PragmaticController.java @@ -0,0 +1,5 @@ +package com.bb.controller; + +public class PragmaticController { + +} diff --git a/src/main/java/com/bb/dao/CallBackDao.java b/src/main/java/com/bb/dao/CallBackDao.java new file mode 100644 index 0000000..aef044c --- /dev/null +++ b/src/main/java/com/bb/dao/CallBackDao.java @@ -0,0 +1,14 @@ +package com.bb.dao; + +import java.util.HashMap; +import java.util.List; + +public interface CallBackDao { + + void insertCallBackErrLog(HashMap logParam); + + void insertBetRadarLog(HashMap sData); + + List getBetRadarLogByBetId(String betId); + +} diff --git a/src/main/java/com/bb/dao/CallBackDaoImpl.java b/src/main/java/com/bb/dao/CallBackDaoImpl.java new file mode 100644 index 0000000..525a8b5 --- /dev/null +++ b/src/main/java/com/bb/dao/CallBackDaoImpl.java @@ -0,0 +1,39 @@ +package com.bb.dao; + +import java.util.HashMap; +import java.util.List; + +import org.apache.ibatis.session.SqlSession; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Repository; + +@Repository("callBackDao") +public class CallBackDaoImpl implements CallBackDao { + + /** 메인DB 연결 */ + @Autowired @Qualifier("sqlSessionMain") + protected SqlSession sqlSession; + + /** 서브DB 연결 */ + @Autowired @Qualifier("sqlSessionSub") + protected SqlSession sqlSessionSub; + + @Override + public void insertCallBackErrLog(HashMap logParam) { + sqlSession.insert("insertCallBackErrLog", logParam); + + } + + @Override + public void insertBetRadarLog(HashMap sData) { + // TODO Auto-generated method stub + sqlSession.insert("insertBetRadarLog", sData); + } + + @Override + public List getBetRadarLogByBetId(String betId) { + return sqlSessionSub.selectList("getBetRadarLogByBetId", betId); + } + +} diff --git a/src/main/java/com/bb/dao/CoinDao.java b/src/main/java/com/bb/dao/CoinDao.java new file mode 100644 index 0000000..250f228 --- /dev/null +++ b/src/main/java/com/bb/dao/CoinDao.java @@ -0,0 +1,10 @@ +package com.bb.dao; + +import com.bb.model.CoinVo; + +public interface CoinDao { + + void saveCoinInfo(CoinVo coinInfo); + CoinVo getCoinInfo(String coinSymbol, String currency); + +} diff --git a/src/main/java/com/bb/dao/CoinDaoImpl.java b/src/main/java/com/bb/dao/CoinDaoImpl.java new file mode 100644 index 0000000..775a853 --- /dev/null +++ b/src/main/java/com/bb/dao/CoinDaoImpl.java @@ -0,0 +1,38 @@ +package com.bb.dao; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.ibatis.session.SqlSession; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Repository; + +import com.bb.model.CoinVo; + +@Repository("coinDao") +public class CoinDaoImpl implements CoinDao{ + + /** 메인DB 연결 */ + @Autowired @Qualifier("sqlSessionMain") + protected SqlSession sqlSession; + + /** 서브DB 연결 */ + @Autowired @Qualifier("sqlSessionSub") + protected SqlSession sqlSessionSub; + + @Override + public void saveCoinInfo(CoinVo coinInfo) { + sqlSession.insert("saveCoinInfo", coinInfo); + + } + + @Override + public CoinVo getCoinInfo(String coinSymbol, String currency) { + Map param = new HashMap(); + param.put("coinSymbol", coinSymbol); + param.put("currency", currency); + return sqlSessionSub.selectOne("getCoinInfo", param); + } + +} diff --git a/src/main/java/com/bb/dao/CommonDao.java b/src/main/java/com/bb/dao/CommonDao.java new file mode 100644 index 0000000..aabdfc7 --- /dev/null +++ b/src/main/java/com/bb/dao/CommonDao.java @@ -0,0 +1,23 @@ +package com.bb.dao; + +import java.util.HashMap; +import java.util.List; + +import com.bb.model.BanGameSearch; +import com.bb.model.CmnSearch; + +public interface CommonDao { + + List> getGameCategoryList(); + + List> getGameVendorList(CmnSearch search); + + List> getBanGameList(BanGameSearch search); + + int insertBanGameInfo(HashMap item); + + int insertNexusGameInfo(HashMap item); + + HashMap getVendorApiInfo(CmnSearch search); + +} diff --git a/src/main/java/com/bb/dao/CommonDaoImpl.java b/src/main/java/com/bb/dao/CommonDaoImpl.java new file mode 100644 index 0000000..a7dabfb --- /dev/null +++ b/src/main/java/com/bb/dao/CommonDaoImpl.java @@ -0,0 +1,60 @@ +package com.bb.dao; + +import java.util.HashMap; +import java.util.List; + +import org.apache.ibatis.session.SqlSession; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Repository; + +import com.bb.model.BanGameSearch; +import com.bb.model.CmnSearch; + +@Repository("commonDao") +public class CommonDaoImpl implements CommonDao { + + /** 메인DB 연결 */ + @Autowired @Qualifier("sqlSessionMain") + protected SqlSession sqlSession; + + /** 서브DB 연결 */ + @Autowired @Qualifier("sqlSessionSub") + protected SqlSession sqlSessionSub; + + @Override + public List> getGameCategoryList() { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getGameCategoryList"); + } + + @Override + public List> getGameVendorList(CmnSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getGameVendorList", search); + } + + @Override + public List> getBanGameList(BanGameSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getBanGameList", search); + } + + @Override + public int insertBanGameInfo(HashMap item) { + // TODO Auto-generated method stub + return sqlSession.update("insertBanGameInfo", item); + } + + @Override + public int insertNexusGameInfo(HashMap item) { + // TODO Auto-generated method stub + return sqlSession.update("insertNexusGameInfo", item); + } + + @Override + public HashMap getVendorApiInfo(CmnSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getVendorApiInfo", search); + } +} diff --git a/src/main/java/com/bb/dao/CreditDao.java b/src/main/java/com/bb/dao/CreditDao.java new file mode 100644 index 0000000..6415b3f --- /dev/null +++ b/src/main/java/com/bb/dao/CreditDao.java @@ -0,0 +1,98 @@ +package com.bb.dao; + +import java.util.HashMap; +import java.util.List; + +import jakarta.validation.Valid; + +import com.bb.model.CashParam; +import com.bb.model.Credit; +import com.bb.model.CreditPoint; +import com.bb.model.CreditPointSearch; +import com.bb.model.CreditSearchVO; +import com.bb.model.Insure; +import com.bb.model.SiteSearch; + +public interface CreditDao { + + void insertCredit(Credit credit); + + void insertCreditByCash(Credit credit); + + void setSiteCreditUpdate(HashMap param); + + int getCreditListCnt(SiteSearch search); + + List getCreditList(SiteSearch search); + + int getSiteTranListCnt(SiteSearch search); + + List getSiteTranList(SiteSearch search); + + void updateStatus(Credit credit); + + int getPointListCnt(SiteSearch search); + + List getPointList(SiteSearch search); + + int getSiteBetListCnt(SiteSearch search); + + List getSiteBetList(SiteSearch search); + + void updateInsureStatus(Insure insure); + + void insertInsure(Insure insure); + + HashMap getMyInsureInfo(int siteIdx); + + HashMap getMyRateInfo(int siteIdx); + + int getInsureListCnt(SiteSearch search); + + List getInsureList(SiteSearch search); + + HashMap getCreditSumToday(SiteSearch search); + + void updateSetStatus(Credit credit2); + + void updateCreditYn(Credit credit); + + String getRoundIdByGsoft(String refId); + + void insertCreditAiAo(Credit credit); + + void insertCreditPoint(HashMap pointParam); + + int insertPoint(CreditPoint point); + + int checkRequestTime(Credit credit); + + int getCashInOutListCnt(CashParam param); + + List getCashInOutList(CashParam param); + + int getTransCreditListCnt(CreditSearchVO search); + + List> getTransCreditList(CreditSearchVO search); + + int getTotalTransactionListCnt(CreditSearchVO search); + + List> getTotalTransactionList(CreditSearchVO search); + + int getCreditPointListCnt(@Valid CreditPointSearch search); + + List> getCreditPointList(@Valid CreditPointSearch search); + + int getCreditBetListCnt(@Valid CreditPointSearch search); + + List> getCreditBetList(@Valid CreditPointSearch search); + + int getStatCreditListCnt(SiteSearch search); + + List getStatCreditList(SiteSearch search); + + HashMap getStatCreditTotal(SiteSearch search); + + void updateSubCredit(Credit credit); + +} diff --git a/src/main/java/com/bb/dao/CreditDaoImpl.java b/src/main/java/com/bb/dao/CreditDaoImpl.java new file mode 100644 index 0000000..cbd6f63 --- /dev/null +++ b/src/main/java/com/bb/dao/CreditDaoImpl.java @@ -0,0 +1,261 @@ +package com.bb.dao; + +import java.util.HashMap; +import java.util.List; + +import jakarta.validation.Valid; + +import org.apache.ibatis.session.SqlSession; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Repository; + +import com.bb.model.CashParam; +import com.bb.model.Credit; +import com.bb.model.CreditPoint; +import com.bb.model.CreditPointSearch; +import com.bb.model.CreditSearchVO; +import com.bb.model.Insure; +import com.bb.model.SiteSearch; + +@Repository("creditDao") +public class CreditDaoImpl implements CreditDao { + + /** 메인DB 연결 */ + @Autowired @Qualifier("sqlSessionMain") + protected SqlSession sqlSession; + + /** 서브DB 연결 */ + @Autowired @Qualifier("sqlSessionSub") + protected SqlSession sqlSessionSub; + + @Override + public void insertCredit(Credit credit) { + sqlSession.insert("insertCredit", credit); + } + + @Override + public void insertCreditByCash(Credit credit) { + sqlSession.insert("insertCreditByCash", credit); + } + + @Override + public void setSiteCreditUpdate(HashMap param) { + sqlSession.update("setSiteCreditUpdate", param); + + } + + @Override + public int getCreditListCnt(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getCreditListCnt", search); + } + + @Override + public List getCreditList(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSession.selectList("getCreditList", search); + } + + @Override + public int getSiteTranListCnt(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getSiteTranListCnt", search); + } + + @Override + public List getSiteTranList(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSession.selectList("getSiteTranList", search); + } + + @Override + public void updateStatus(Credit credit) { + // TODO Auto-generated method stub + sqlSession.update("updateStatus", credit); + } + + @Override + public int getPointListCnt(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getPointListCnt", search); + } + + @Override + public List getPointList(SiteSearch search) { + return sqlSession.selectList("getPointList", search); + } + + @Override + public int getSiteBetListCnt(SiteSearch search) { + return sqlSession.selectOne("getSiteBetListCnt", search); + } + + @Override + public List getSiteBetList(SiteSearch search) { + return sqlSession.selectList("getSiteBetList", search); + } + + @Override + public void updateInsureStatus(Insure insure) { + // TODO Auto-generated method stub + sqlSession.update("updateInsureStatus", insure); + } + + @Override + public void insertInsure(Insure insure) { + // TODO Auto-generated method stub + sqlSession.insert("insertInsure", insure); + } + + @Override + public HashMap getMyInsureInfo(int siteIdx) { + return sqlSession.selectOne("getMyInsureInfo", siteIdx); + } + + @Override + public HashMap getMyRateInfo(int siteIdx) { + return sqlSession.selectOne("getMyRateInfo", siteIdx); + } + + @Override + public int getInsureListCnt(SiteSearch search) { + return sqlSession.selectOne("getInsureListCnt", search); + } + + @Override + public List getInsureList(SiteSearch search) { + return sqlSession.selectList("getInsureList", search); + } + + @Override + public HashMap getCreditSumToday(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getCreditSumToday", search); + } + + @Override + public void updateSetStatus(Credit credit2) { + // TODO Auto-generated method stub + sqlSession.update("updateSetStatus", credit2); + } + + @Override + public void updateCreditYn(Credit credit) { + // TODO Auto-generated method stub + sqlSession.update("updateCreditYn", credit); + } + + @Override + public String getRoundIdByGsoft(String refId) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getRoundIdByGsoft", refId); + } + + @Override + public void insertCreditAiAo(Credit credit) { + // TODO Auto-generated method stub + sqlSession.insert("insertCreditAiAo", credit); + } + + @Override + public void insertCreditPoint(HashMap pointParam) { + // TODO Auto-generated method stub + sqlSession.insert("insertCreditPoint", pointParam); + } + + @Override + public int insertPoint(CreditPoint point) { + // TODO Auto-generated method stub + return sqlSession.insert("insertPoint", point); + } + + @Override + public int checkRequestTime(Credit credit) { + // TODO Auto-generated method stub + return sqlSession.selectOne("checkRequestTime", credit); + } + + @Override + public int getCashInOutListCnt(CashParam param) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getCashInOutListCnt", param); + } + + @Override + public List getCashInOutList(CashParam param) { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getCashInOutList", param); + } + + @Override + public int getTransCreditListCnt(CreditSearchVO search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getTransCreditListCnt", search); + } + + @Override + public List> getTransCreditList(CreditSearchVO search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getTransCreditList", search); + } + + @Override + public int getTotalTransactionListCnt(CreditSearchVO search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getTotalTransactionListCnt", search); + } + + @Override + public List> getTotalTransactionList(CreditSearchVO search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getTotalTransactionList", search); + } + + @Override + public int getCreditPointListCnt(@Valid CreditPointSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getCreditPointListCnt", search); + } + + @Override + public List> getCreditPointList(@Valid CreditPointSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getCreditPointList", search); + } + + @Override + public int getCreditBetListCnt(@Valid CreditPointSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getCreditBetListCnt", search); + } + + @Override + public List> getCreditBetList(@Valid CreditPointSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getCreditBetList", search); + } + + @Override + public int getStatCreditListCnt(SiteSearch search) { + return sqlSessionSub.selectOne("getStatCreditListCnt", search); + } + + @Override + public List getStatCreditList(SiteSearch search) { + return sqlSessionSub.selectList("getStatCreditList", search); + } + + @Override + public HashMap getStatCreditTotal(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getStatCreditTotal", search); + } + + @Override + public void updateSubCredit(Credit credit) { + // TODO Auto-generated method stub + sqlSession.update("updateSubCredit", credit); + } + +} diff --git a/src/main/java/com/bb/dao/SettingDao.java b/src/main/java/com/bb/dao/SettingDao.java new file mode 100644 index 0000000..d0e64f2 --- /dev/null +++ b/src/main/java/com/bb/dao/SettingDao.java @@ -0,0 +1,34 @@ +package com.bb.dao; + +import java.util.HashMap; +import java.util.List; + +import com.bb.model.BlockGameVO; +import com.bb.model.CmnSearch; +import com.bb.model.SiteVendorSkinVO; + +public interface SettingDao { + + List> getSettingVendorList(CmnSearch search); + + List> getSettingSkinList(CmnSearch search); + + int settingVendorSkinSave(SiteVendorSkinVO item); + + String getWhiteIpListStr(CmnSearch search); + + List> getBlockVendorSelectBoxList(String category); + + List> getBlockVendorSelectBoxList2(CmnSearch search); + + List> getBlockTableSelectBoxList(CmnSearch search); + + String getBlockTableIds(CmnSearch search); + + int blockTableIdSave(BlockGameVO blockGameVO); + + String getVendorTitle(CmnSearch search); + + HashMap getBetRadarApiInfo(String siteId); + +} diff --git a/src/main/java/com/bb/dao/SettingDaoImpl.java b/src/main/java/com/bb/dao/SettingDaoImpl.java new file mode 100644 index 0000000..e060bd3 --- /dev/null +++ b/src/main/java/com/bb/dao/SettingDaoImpl.java @@ -0,0 +1,104 @@ +package com.bb.dao; + +import java.util.HashMap; +import java.util.List; + +import org.apache.ibatis.session.SqlSession; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Repository; + +import com.bb.model.BlockGameVO; +import com.bb.model.CmnSearch; +import com.bb.model.SiteVendorSkinVO; + +@Repository("settingDao") +public class SettingDaoImpl implements SettingDao { + + /** 메인DB 연결 */ + @Autowired @Qualifier("sqlSessionMain") + protected SqlSession sqlSession; + + /** 서브DB 연결 */ + @Autowired @Qualifier("sqlSessionSub") + protected SqlSession sqlSessionSub; + + + @Override + public List> getSettingVendorList(CmnSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getSettingVendorList", search); + } + + + @Override + public List> getSettingSkinList(CmnSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getSettingSkinList", search); + } + + + @Override + public int settingVendorSkinSave(SiteVendorSkinVO item) { + // TODO Auto-generated method stub + return sqlSession.update("settingVendorSkinSave", item); + } + + + @Override + public String getWhiteIpListStr(CmnSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getWhiteIpListStr", search); + } + + + @Override + public List> getBlockVendorSelectBoxList(String category) { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getBlockVendorSelectBoxList", category); + } + + + @Override + public List> getBlockVendorSelectBoxList2(CmnSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getBlockVendorSelectBoxList2", search); + } + + + @Override + public List> getBlockTableSelectBoxList(CmnSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getBlockTableSelectBoxList", search); + } + + + @Override + public String getBlockTableIds(CmnSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getBlockTableIds", search); + } + + + @Override + public int blockTableIdSave(BlockGameVO blockGameVO) { + // TODO Auto-generated method stub + return sqlSession.update("blockTableIdSave", blockGameVO); + } + + + @Override + public String getVendorTitle(CmnSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getVendorTitle", search); + } + + + @Override + public HashMap getBetRadarApiInfo(String siteId) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getBetRadarApiInfo", siteId); + } + + +} diff --git a/src/main/java/com/bb/dao/SiteDao.java b/src/main/java/com/bb/dao/SiteDao.java new file mode 100644 index 0000000..618d73f --- /dev/null +++ b/src/main/java/com/bb/dao/SiteDao.java @@ -0,0 +1,489 @@ +package com.bb.dao; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.security.core.Authentication; + +import com.bb.model.BalanceParam; +import com.bb.model.BetParam; +import com.bb.model.BoardSearch; +import com.bb.model.CashParam; +import com.bb.model.CommonParam; +import com.bb.model.Game; +import com.bb.model.Member; +import com.bb.model.OTPInfo; +import com.bb.model.Site; +import com.bb.model.SitePwdVO; +import com.bb.model.SiteSearch; +import com.bb.model.TrfApiInfo; +import com.bb.model.UserSearch; +import com.bb.model.Vendor; +import com.bb.model.VendorChangeBalanceLogVo; + + +public interface SiteDao { + + Site getSiteInfo(String authorization); + + Site getSiteInfoAPI(String authorization); + + Member getMember(CommonParam commonParam); + + Member getMember2(CashParam param); + + void insertMember(CommonParam commonParam); + + HashMap getVenderApiInfo(CommonParam commonParam); + + int commonBetinsert(HashMap tranParam); + + int commonBetinsert2(HashMap tranParam); + + List getCbList(); + + void updateCbApi(HashMap upParam); + + HashMap getSiteApiInfo(HashMap sParam); + + HashMap getSiteApiInfo2(HashMap sParam); + + Site getSiteLogin(Authentication authentication); + + Site getSiteLoginApi(Map site); + + Site getGuestLogin(); + + int getSiteListCnt(SiteSearch search); + + List getSiteList(SiteSearch search); + + void addProc(Site site); + + void addCreditInfo(Site site); + + void addsiteFlow(Site site); + + void insertVendors(Site site); + + Site getSiteInfoMypage(Site site); + + long getSiteCredit(String siteId); + + long getUnderSiteCredit(String siteId); + + long getSitePoint(String siteId); + + void addPointInfo(Site site); + + HashMap getCreditWait(int siteIdx); + + int getSiteUserListCnt(SiteSearch search); + + List getSiteUserList(SiteSearch search); + + int getTranCheck(String tranId); + + void insertError(HashMap eParam); + + int getFinalErr(String betId); + + void updateSid(Member member); + + long getInsureAmt(String siteId); + + long getInsurePointAmt(String siteId); + + void insertinsurance(Site site); + + void insertinsurancePoint(Site site); + + List getVenderRateList(Site loginSite); + + int getBetCancelCount(String betId); + + void updateBombKey(Member member); + + Member getMemByBombAccId(HashMap memParam); + + void insertBetDetail(Map detailMap); + + String getBetInfo(BetParam param); + + List getSiteFlow(Site loginSite); + + void saveVendorRate(HashMap paramMap); + + HashMap getEvoApiInfo(); + + String getSiteIdByRefId(String refId); + + void updateDetailLastTime(HashMap evoInfo); + + Site getSiteDetail(SiteSearch search); + + Site getSiteSimpleDetail(SiteSearch search); + + HashMap getVenderApiInfoByToken(Map paramV); + + Site getSiteBypassword(Map siteParam); + + void updatePass(Map siteParam); + + void siteUpdate(Site site); + + void saveVendorInsurePointRate(HashMap paramMap); + + HashMap getDashInfo(Site loginSite); + + HashMap getDashInfo2(Site loginSite); + + void insertVendorsRate(Site site); + + HashMap getMicroApiInfo(); + + int getApiStatus(HashMap tranParam); + + void saveVendorInsureRate(HashMap paramMap); + + void updateVendorUseYn(HashMap paramMap); + + List getSiteVendorList(SiteSearch search); + + List getVendorList(SiteSearch search); + + void siteVenderUpdate(Vendor vendor); + + HashMap getDowinApiInfo(); + + long getSiteMaxBet(HashMap sParam); + + Long getUserMaxBet(HashMap sParam); + + int getBetCheckByHc(String refId); + + void updatePragmaticId(Member member); + + HashMap getProgmaticApiInfo(); + + HashMap getSiteApiInfoByPra(HashMap sParam); + + String getlastDepostId(HashMap dParam); + + List getNotUseMemberListProgama(); + + List getGameList(HashMap param); + + HashMap getOnlyVenderInfo(CommonParam commonParam); + + int getBotaAutoCancelCnt(String tranId); + + int getBotaBetCnt(String tranId); + + HashMap getProgmaticApiInfo2(); + + List getBotaBetListMinute(); + + String getSiteIdByRefId2(String string); + + int getTranIdCheck(String string); + + int getTranIdCheck2(String string); + + HashMap getSiteMember(String string); + + void updateDebitCancel(String refId); + + void insertSiteCallBackLog(HashMap logParam); + + List getBetList(BetParam param); + + List getMonsterGameList(); + + HashMap getProgmaticApiInfo3(String code); + + long getBetCancelAmt(String string); + + int getBetIdCheck(String refId); + + int getBetIdCheck2(String refId); + + int getTranCheck2(String betId); + + void insertSlotCity(HashMap slotMap); + + void botaAutoCancel(HashMap tranParam); + + void seattleCredit(); + + void updateDecimal(HashMap decimalParam); + + List getonlyDebitList(); + + void insertAutoLose(HashMap loseCredit); + + HashMap getBetCheck(BetParam param); + + int callbackTokenCheck(String token); + + HashMap getVenderInfo(BalanceParam param); + + String getRefIdByTranId(String tranId); + + List getCreditReSendList(); + + void updateMemCancelCnt(long memberIdx); + + Long getMemberIdx(HashMap memParam); + + int insertVendorChangeBalanceLog(VendorChangeBalanceLogVo logVo); + + HashMap getGsoftVendorInfo(String gameID); + + String getCreditRate(HashMap upParam); + + void inserDemoUSer(String bombToken); + + HashMap getDemoByBombAccId(HashMap memParam); + + void updateDemoUSer(HashMap memParam); + + List getTrasferVendorList(); + + List getAllMember(); + + int gethourBetCheck(long member); + + List getAllMember2(); + + HashMap getUserVendorInfo(HashMap memParam); + + Member getMemberByToken(Map authParam); + + HashMap getSiteApiInfoByToken(Map authParam); + + double getBetDepositAmt(String tranId); + + void insertSplusTran(Map trxParam); + + void updateSplusTran(Map trxParam); + + String getCbData(String reserve_id); + + void updatesPurchaseId(Map trxParam); + + double getBetGapAmt(String pid); + + void insertToken(String base64Token); + + int getSplusToken(String base64Token); + + String getRefIdByPurchaseId(String purchase_id); + + List getSplusDetailData(BetParam param); + + String getKorNameTeam(String txt); + + String getKorNameLeague(String txt); + + void insertVendorsCodeRate(Site site); + + HashMap getBetInfoByTranId(String reference); + + int getSuccDebitCnt(String betId); + + HashMap getSiteVendorInfo(HashMap param); + + int updatePowerballApiInfo(HashMap registParam); + + List> getPowerBallInfoList(String gameType); + + HashMap getSiteApiInfoByApiKey(HashMap param); + + HashMap getSiteApiInfoByCallbackKey(HashMap param); + + int updMemLastVendorIdx(HashMap memParam); + + List getVendorListByVendorKey(HashMap venderInfo); + + void vendorUpdate(HashMap venderInfo); + + List getNexusSkinListByVendorKey(HashMap venderInfo); + + void nexusSkinUpdate(HashMap venderInfo); + + String getParseTarget(); + + String getParseTargetExtr(); + + HashMap getParseUseYn(int siteIdx); + + void insertParseUse(HashMap parseParam); + + List getApiBetVendorList(int siteIdx); + + int getApiBetTransactionCnt(BetParam param); + + List getApiBetTransactionList(BetParam param); + + void updVendorMapForDefault(Site site); + + void updVendorCreditRateForDefault(Site site); + + void deleteVendorAccountForDefault(Site site); + + HashMap getParseUserYn(HashMap pum); + + void setParseUserYn(HashMap pum); + + OTPInfo getOtpInfo(long siteIdx); + + OTPInfo getOtpInfoByManger(long siteIdx); + + int registSuperOtp(OTPInfo param); + + HashMap getSiteOnlyVendorInfo(HashMap vendorParam); + + TrfApiInfo getTrfApiInfo(HashMap mapParam); + + void agentIpsUpdate(Site site); + + int insertEvoDetail(HashMap detailMap); + + HashMap getCommonApiInfo(HashMap commonParam); + + HashMap getBeforeTranInfo(String vendorTranKey); + + List getParseTargetGame(String gameType); + + String getOrgDetailData(BetParam param); + + String getParDetailData(BetParam param); + + HashMap getBetInfoByTranKey(String vendorTranKey); + + HashMap getParseInfo(HashMap param); + + int getBlockParseGameId(String gameId); + + HashMap getBeforeTranInfo2(String vendorTranKey); + + String getMemberByIdx(HashMap memParam); + + List getSiteVendorList2(int siteIdx); + + List getVendorList2(int siteIdx); + + void saveSvcr(HashMap paramMap); + + int siteVenderCodeCheck(HashMap paramMap); + + void saveVendorRate2(HashMap paramMap); + + String getSiteKey(HashMap paramMap); + + String getVendorTitle(HashMap paramMap); + + Long getUserTimeout(HashMap accLog); + + int updateUserTimeout(HashMap accLog); + + String getGameKeyByNexusGameId(String gameId); + + String getDebitIsParse(String betId); + + int updateParseUseYN(String useYn); + + int insertTheaTrxId(HashMap param); + + HashMap getApiKeyInfo(String vendorTitle); + + HashMap getApiKeyInfo2(HashMap keyParam); + + HashMap getRefBetInfoByTranId(String tranId); + + int updMemberBalance(HashMap balanceMap); + + int getMemberBalance(HashMap balanceMap); + + HashMap getMemberId(String vendorUsername); + + int checkMemberId(String vendorUsername); + + HashMap getNewSiteApiInfo(String vendorUsername); + + HashMap getNewSiteVendorInfo(HashMap param); + + int updateTestCnt(Site site); + + int updateParseEvoYn(HashMap param); + + int saveParsEvoAmount(SiteSearch param); + + int getUserBalance(HashMap balanceMap); + + List getMyDownSite(SiteSearch search); + + HashMap getCreditInfo(String siteId); + + int checkDownSite(Map checkDown); + + List getSiteTreeList(String siteId); + + int getMyDownSiteCheck(Site targetsite); + + void insertParseUseYn(Site site); + + int updateSitePwd(SitePwdVO sitePwdVO); + + Site getSite(Site site); + + void siteVenderLobbyUpdate(Vendor vendor); + + List getVendorMapList(SiteSearch search); + + List geLobbyList(SiteSearch search); + + String siteVenderRate(Vendor vendor); + + int getBoardListCnt(BoardSearch search); + + List> getBoardList(BoardSearch search); + + HashMap getBoardDetail(long boardIdx); + + int getSiteCallbackErrLogListCnt(SiteSearch search); + + List getSiteCallbackErrLogList(SiteSearch search); + + List getSiteTreeInfo(HashMap param); + + int getUserListCnt(UserSearch search); + + List> getUserList(UserSearch search); + + HashMap getUserDetail(UserSearch search); + + void insertCmsIp(Site site); + + int getSiteListCntForApi(SiteSearch search); + + List getSiteListForApi(SiteSearch search); + + Site getSiteDetailForApi(SiteSearch search); + + List getVendorListForApi(SiteSearch search); + + List getSiteVendorListForApi(SiteSearch search); + + HashMap getRefIdByVendorTranKey(String vendorTranKey); + + int updateUserMaxBet(HashMap param); + + int insertTranLog(HashMap logParam); + + HashMap getSiteSubCredit(String siteId); + + String getBetAmountByTranParam(HashMap param); +} diff --git a/src/main/java/com/bb/dao/SiteDaoImpl.java b/src/main/java/com/bb/dao/SiteDaoImpl.java new file mode 100644 index 0000000..527c5a8 --- /dev/null +++ b/src/main/java/com/bb/dao/SiteDaoImpl.java @@ -0,0 +1,1396 @@ +package com.bb.dao; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.ibatis.session.SqlSession; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Repository; + +import com.bb.model.BalanceParam; +import com.bb.model.BetParam; +import com.bb.model.BoardSearch; +import com.bb.model.CashParam; +import com.bb.model.CommonParam; +import com.bb.model.Game; +import com.bb.model.Member; +import com.bb.model.OTPInfo; +import com.bb.model.Site; +import com.bb.model.SitePwdVO; +import com.bb.model.SiteSearch; +import com.bb.model.TrfApiInfo; +import com.bb.model.UserSearch; +import com.bb.model.Vendor; +import com.bb.model.VendorChangeBalanceLogVo; + +@Repository("siteDao") +public class SiteDaoImpl implements SiteDao { + + /** 메인DB 연결 */ + @Autowired @Qualifier("sqlSessionMain") + protected SqlSession sqlSession; + + /** 서브DB 연결 */ + @Autowired @Qualifier("sqlSessionSub") + protected SqlSession sqlSessionSub; + + @Override + public Site getSiteInfo(String authorization) { + return sqlSession.selectOne("getSiteInfo", authorization); + } + + @Override + public Site getSiteInfoAPI(String authorization) { + return sqlSession.selectOne("getSiteInfoAPI", authorization); + } + + @Override + public Member getMember(CommonParam commonParam) { + return sqlSession.selectOne("getMember", commonParam); + } + + @Override + public Member getMember2(CashParam param) { + return sqlSession.selectOne("getMember2", param); + } + + @Override + public void insertMember(CommonParam commonParam) { + sqlSession.insert("insertMember", commonParam); + + } + + @Override + public HashMap getVenderApiInfo(CommonParam commonParam) { + return sqlSession.selectOne("getVenderApiInfo", commonParam); + } + + + @Override + public List getCbList() { + // TODO Auto-generated method stub + return sqlSession.selectList("getCbList", null); + } + + @Override + public void updateCbApi(HashMap upParam) { + // TODO Auto-generated method stub + sqlSession.update("updateCbApi", upParam); + } + + @Override + public HashMap getSiteApiInfo(HashMap sParam) { + return sqlSessionSub.selectOne("getSiteApiInfo", sParam); + } + + @Override + public HashMap getSiteApiInfo2(HashMap sParam) { + return sqlSessionSub.selectOne("getSiteApiInfo2", sParam); + } + + @Override + public int commonBetinsert(HashMap tranParam) { + // TODO Auto-generated method stub + return sqlSession.update("commonBetinsert", tranParam); + } + + @Override + public int commonBetinsert2(HashMap tranParam) { + // TODO Auto-generated method stub + return sqlSession.update("commonBetinsert2", tranParam); + } + + @Override + public Site getSiteLogin(Authentication authentication) { + return sqlSession.selectOne("getSiteLogin", authentication); + } + + @Override + public Site getSiteLoginApi(Map site) { + return sqlSessionSub.selectOne("getSiteLoginApi", site); + } + + @Override + public Site getGuestLogin() { + return sqlSession.selectOne("getGuestLogin"); + } + + @Override + public int getSiteListCnt(SiteSearch search) { + return sqlSession.selectOne("getSiteListCnt", search); + } + + @Override + public List getSiteList(SiteSearch search) { + return sqlSession.selectList("getSiteList", search); + } + + @Override + public void addProc(Site site) { + sqlSession.insert("addProc",site ); + } + + @Override + public void addCreditInfo(Site site) { + sqlSession.insert("addCreditInfo",site ); + } + + @Override + public void addsiteFlow(Site site) { + sqlSession.insert("addsiteFlow",site ); + } + + @Override + public void insertVendors(Site site) { + sqlSession.insert("insertVendors",site ); + + } + + @Override + public Site getSiteInfoMypage(Site site) { + return sqlSession.selectOne("getSiteInfoMypage", site); + } + + @Override + public long getSiteCredit(String siteId) { + return sqlSession.selectOne("getSiteCredit", siteId); + } + + @Override + public long getUnderSiteCredit(String siteId) { + return sqlSession.selectOne("getUnderSiteCredit", siteId); + } + + @Override + public long getSitePoint(String siteId) { + return sqlSessionSub.selectOne("getSitePoint", siteId); + } + + @Override + public void addPointInfo(Site site) { + // TODO Auto-generated method stub + sqlSession.insert("addPointInfo",site ); + } + + @Override + public HashMap getCreditWait(int siteIdx) { + return sqlSession.selectOne("getCreditWait", siteIdx); + } + + @Override + public int getSiteUserListCnt(SiteSearch search) { + return sqlSession.selectOne("getSiteUserListCnt", search); + } + + @Override + public List getSiteUserList(SiteSearch search) { + return sqlSession.selectList("getSiteUserList", search); + } + + @Override + public int getTranCheck(String tranId) { + return sqlSession.selectOne("getTranCheck", tranId); + } + + @Override + public void insertError(HashMap eParam) { + sqlSession.insert("insertError",eParam ); + + } + + @Override + public int getFinalErr(String betId) { + return sqlSession.selectOne("getFinalErr", betId); + } + + @Override + public void updateSid(Member member) { + sqlSession.update("updateSid",member ); + + } + + @Override + public long getInsureAmt(String siteId) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getInsureAmt", siteId); + } + + @Override + public long getInsurePointAmt(String siteId) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getInsurePointAmt", siteId); + } + + @Override + public void insertinsurance(Site site) { + // TODO Auto-generated method stub + sqlSession.insert("insertinsurance", site); + } + + @Override + public void insertinsurancePoint(Site site) { + // TODO Auto-generated method stub + sqlSession.insert("insertinsurancePoint", site); + } + + @Override + public List getVenderRateList(Site loginSite) { + // TODO Auto-generated method stub + return sqlSession.selectList("getVenderRateList", loginSite); + } + + @Override + public int getBetCancelCount(String betId) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getBetCancelCount", betId); + } + + @Override + public void updateBombKey(Member member) { + // TODO Auto-generated method stub + sqlSession.update("updateBombKey", member); + } + + @Override + public Member getMemByBombAccId(HashMap memParam) { + return sqlSession.selectOne("getMemByBombAccId", memParam); + } + + + @Override + public void insertBetDetail(Map detailMap) { + // TODO Auto-generated method stub + sqlSession.insert("insertBetDetail", detailMap); + } + + @Override + public String getBetInfo(BetParam param) { + // TODO Auto-generated method stub + sqlSession.update("updateVariable", "SET @@group_concat_max_len = 50240"); + return sqlSession.selectOne("getBetInfo", param); + + } + + @Override + public List getSiteFlow(Site loginSite) { + // TODO Auto-generated method stub + return sqlSession.selectList("getSiteFlow", loginSite); + + } + + @Override + public void saveVendorRate(HashMap paramMap) { + // TODO Auto-generated method stub + sqlSession.insert("saveVendorRate", paramMap); + } + + @Override + public HashMap getEvoApiInfo() { + // TODO Auto-generated method stub + return sqlSession.selectOne("getEvoApiInfo", null); + } + + @Override + public String getSiteIdByRefId(String refId) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getSiteIdByRefId", refId); + } + + @Override + public void updateDetailLastTime(HashMap evoInfo) { + // TODO Auto-generated method stub + //System.out.print("endDate " + evoInfo.get("endDate")); + sqlSession.insert("updateDetailLastTime", evoInfo); + } + + @Override + public Site getSiteDetail(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getSiteDetail", search); + } + + @Override + public Site getSiteSimpleDetail(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getSiteSimpleDetail", search); + } + + @Override + public HashMap getVenderApiInfoByToken(Map paramV) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getVenderApiInfoByToken", paramV); + } + + @Override + public Site getSiteBypassword(Map siteParam) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getSiteBypassword", siteParam); + } + + @Override + public void updatePass(Map siteParam) { + sqlSession.update("updatePass", siteParam); + + } + + @Override + public void siteUpdate(Site site) { + sqlSession.update("siteUpdate", site); + + } + + @Override + public void saveVendorInsurePointRate(HashMap paramMap) { + // TODO Auto-generated method stub + sqlSession.insert("saveVendorInsurePointRate", paramMap); + } + + @Override + public HashMap getDashInfo(Site loginSite) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getDashInfo", loginSite); + } + + @Override + public HashMap getDashInfo2(Site loginSite) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getDashInfo2", loginSite); + } + + @Override + public void insertVendorsRate(Site site) { + // TODO Auto-generated method stub + sqlSession.insert("insertVendorsRate", site); + } + + @Override + public HashMap getMicroApiInfo() { + // TODO Auto-generated method stub + return sqlSession.selectOne("getMicroApiInfo", null); + } + + @Override + public int getApiStatus(HashMap tranParam) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getApiStatus", tranParam); + } + + @Override + public void saveVendorInsureRate(HashMap paramMap) { + // TODO Auto-generated method stub + sqlSession.insert("saveVendorInsureRate", paramMap); + } + + @Override + public void updateVendorUseYn(HashMap paramMap) { + // TODO Auto-generated method stub + sqlSession.update("updateVendorUseYn", paramMap); + } + + @Override + public List getSiteVendorList(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSession.selectList("getSiteVendorList", search); + } + + @Override + public List getVendorList(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSession.selectList("getVendorList", search); + } + + @Override + public void siteVenderUpdate(Vendor vendor) { + // TODO Auto-generated method stub + sqlSession.update("siteVenderUpdate", vendor); + } + + @Override + public HashMap getDowinApiInfo() { + // TODO Auto-generated method stub + return sqlSession.selectOne("getDowinApiInfo", null); + } + + @Override + public long getSiteMaxBet(HashMap sParam) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getSiteMaxBet", sParam); + } + + @Override + public Long getUserMaxBet(HashMap sParam) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getUserMaxBet", sParam); + } + + @Override + public int getBetCheckByHc(String refId) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getBetCheckByHc", refId); + } + + @Override + public void updatePragmaticId(Member member) { + // TODO Auto-generated method stub + sqlSession.update("updatePragmaticId", member); + } + + @Override + public HashMap getProgmaticApiInfo() { + // TODO Auto-generated method stub + return sqlSession.selectOne("getProgmaticApiInfo", null); + } + + @Override + public HashMap getProgmaticApiInfo2() { + // TODO Auto-generated method stub + return sqlSession.selectOne("getProgmaticApiInfo2", null); + } + + @Override + public HashMap getSiteApiInfoByPra(HashMap sParam) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getSiteApiInfoByPra", sParam); + } + + @Override + public String getlastDepostId(HashMap dParam) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getlastDepostId", dParam); + } + + @Override + public List getNotUseMemberListProgama() { + // TODO Auto-generated method stub + return sqlSession.selectList("getNotUseMemberListProgama", null); + } + + @Override + public List getGameList(HashMap param) { + // TODO Auto-generated method stub + return sqlSession.selectList("getGameList", param); + } + + @Override + public HashMap getOnlyVenderInfo(CommonParam commonParam) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getOnlyVenderInfo", commonParam); + } + + @Override + public int getBotaAutoCancelCnt(String tranId) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getBotaAutoCancelCnt", tranId); + } + + @Override + public int getBotaBetCnt(String tranId) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getBotaBetCnt", tranId); + } + + @Override + public List getBotaBetListMinute() { + // TODO Auto-generated method stub + return sqlSession.selectList("getBotaBetListMinute", null); + } + + @Override + public String getSiteIdByRefId2(String string) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getSiteIdByRefId2", string); + } + + @Override + public int getTranIdCheck(String string) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getTranIdCheck", string); + } + + @Override + public int getTranIdCheck2(String string) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getTranIdCheck2", string); + } + + @Override + public HashMap getSiteMember(String string) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getSiteMember", string); + } + + @Override + public void updateDebitCancel(String refId) { + // TODO Auto-generated method stub + sqlSession.update("updateDebitCancel", refId); + } + + @Override + public void insertSiteCallBackLog(HashMap logParam) { + // TODO Auto-generated method stub + sqlSession.insert("insertSiteCallBackLog", logParam); + } + + @Override + public List getBetList(BetParam param) { + // TODO Auto-generated method stub + return sqlSession.selectList("getBetList", param); + } + + @Override + public List getMonsterGameList() { + // TODO Auto-generated method stub + return sqlSession.selectList("getMonsterGameList", null); + } + + @Override + public HashMap getProgmaticApiInfo3(String code) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getProgmaticApiInfo3", code); + } + + @Override + public long getBetCancelAmt(String string) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getBetCancelAmt", string); + } + + @Override + public int getBetIdCheck(String refId) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getBetIdCheck", refId); + } + + @Override + public int getBetIdCheck2(String refId) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getBetIdCheck2", refId); + } + + @Override + public int getTranCheck2(String tranId) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getTranCheck2", tranId); + } + + @Override + public void insertSlotCity(HashMap slotMap) { + // TODO Auto-generated method stub + sqlSession.insert("insertSlotCity", slotMap); + } + + @Override + public void botaAutoCancel(HashMap tranParam) { + // TODO Auto-generated method stub + sqlSession.update("botaAutoCancel", tranParam); + } + + @Override + public void seattleCredit() { + // TODO Auto-generated method stub + sqlSession.insert("seattleCredit", null); + } + + @Override + public void updateDecimal(HashMap decimalParam) { + sqlSession.update("updateDecimal", decimalParam); + + } + + @Override + public List getonlyDebitList() { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getonlyDebitList", null); + } + + @Override + public void insertAutoLose(HashMap loseCredit) { + // TODO Auto-generated method stub + sqlSession.insert("insertAutoLose", loseCredit); + } + + @Override + public HashMap getBetCheck(BetParam param) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getBetCheck", param); + } + + @Override + public int callbackTokenCheck(String token) { + // TODO Auto-generated method stub + return sqlSession.selectOne("callbackTokenCheck", token); + } + + @Override + public HashMap getVenderInfo(BalanceParam param) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getVenderInfo", param); + } + + @Override + public String getRefIdByTranId(String tranId) { + return sqlSession.selectOne("getRefIdByTranId", tranId); + + } + + @Override + public List getCreditReSendList() { + return sqlSessionSub.selectList("getCreditReSendList", null); + + } + + @Override + public void updateMemCancelCnt(long memberIdx) { + // TODO Auto-generated method stub + sqlSession.update("updateMemCancelCnt", memberIdx); + } + + @Override + public Long getMemberIdx(HashMap memParam) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getMemberIdx", memParam); + } + + @Override + public int insertVendorChangeBalanceLog(VendorChangeBalanceLogVo logVo) { + // TODO Auto-generated method stub + return sqlSession.insert("insertVendorChangeBalanceLog", logVo); + } + + @Override + public HashMap getGsoftVendorInfo(String gameID) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getGsoftVendorInfo", gameID); + } + + @Override + public String getCreditRate(HashMap upParam) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getCreditRate", upParam); + } + + @Override + public void inserDemoUSer(String bombToken) { + sqlSession.insert("inserDemoUSer", bombToken); + } + + @Override + public HashMap getDemoByBombAccId(HashMap memParam) { + return sqlSession.selectOne("getDemoByBombAccId", memParam); + } + + @Override + public void updateDemoUSer(HashMap memParam) { + sqlSession.insert("updateDemoUSer", memParam); + + } + + @Override + public List getTrasferVendorList() { + return sqlSessionSub.selectList("getTrasferVendorList", null); + } + + @Override + public List getAllMember() { + return sqlSessionSub.selectList("getAllMember", null); + } + + @Override + public int gethourBetCheck(long member) { + return sqlSessionSub.selectOne("gethourBetCheck", member); + } + + @Override + public List getAllMember2() { + return sqlSessionSub.selectList("getAllMember2", null); + } + + @Override + public HashMap getUserVendorInfo(HashMap memParam) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getUserVendorInfo", memParam); + } + + + @Override + public Member getMemberByToken(Map authParam) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getMemberByToken", authParam); + } + + @Override + public HashMap getSiteApiInfoByToken(Map authParam) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getSiteApiInfoByToken", authParam); + } + + @Override + public double getBetDepositAmt(String tranId) { + double res =0; + try { + res = sqlSession.selectOne("getBetDepositAmt", tranId); + }catch(Exception e) { + res =0; + } + return res; + + } + + @Override + public void insertSplusTran(Map trxParam) { + sqlSession.insert("insertSplusTran", trxParam); + + } + + @Override + public void updateSplusTran(Map trxParam) { + sqlSession.update("updateSplusTran", trxParam); + + } + + @Override + public String getCbData(String reserve_id) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getCbData", reserve_id); + } + + @Override + public void updatesPurchaseId(Map trxParam) { + sqlSession.update("updatesPurchaseId", trxParam); + } + + @Override + public double getBetGapAmt(String pid) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getBetGapAmt", pid); + } + + @Override + public void insertToken(String base64Token) { + sqlSession.insert("insertToken", base64Token); + } + + @Override + public int getSplusToken(String base64Token) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getSplusToken", base64Token); + } + + @Override + public String getRefIdByPurchaseId(String purchaseId) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getRefIdByPurchaseId", purchaseId); + } + + @Override + public List getSplusDetailData(BetParam param) { + // TODO Auto-generated method stub + return sqlSession.selectList("getSplusDetailData", param); + } + + @Override + public String getKorNameTeam(String txt) { + return sqlSession.selectOne("getKorNameTeam", txt); + + } + + @Override + public String getKorNameLeague(String txt) { + return sqlSession.selectOne("getKorNameLeague", txt); + + } + + @Override + public void insertVendorsCodeRate(Site site) { + // TODO Auto-generated method stub + sqlSession.insert("insertVendorsCodeRate", site); + } + + @Override + public HashMap getBetInfoByTranId(String tranId) { + return sqlSession.selectOne("getBetInfoByTranId", tranId); + + } + + @Override + public int getSuccDebitCnt(String betId) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getSuccDebitCnt", betId); + } + + @Override + public HashMap getSiteVendorInfo(HashMap param) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getSiteVendorInfo", param); + } + + @Override + public int updatePowerballApiInfo(HashMap registParam) { + // TODO Auto-generated method stub + return sqlSession.update("updatePowerballApiInfo", registParam); + } + + @Override + public List> getPowerBallInfoList(String gameType) { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getPowerBallInfoList", gameType); + } + + @Override + public HashMap getSiteApiInfoByApiKey(HashMap param) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getSiteApiInfoByApiKey", param); + } + + @Override + public HashMap getSiteApiInfoByCallbackKey(HashMap param) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getSiteApiInfoByCallbackKey", param); + } + + @Override + public int updMemLastVendorIdx(HashMap memParam) { + // TODO Auto-generated method stub + return sqlSession.update("updMemLastVendorIdx", memParam); + } + + @Override + public List getVendorListByVendorKey(HashMap venderInfo) { + return sqlSession.selectList("getVendorListByVendorKey", venderInfo); + } + + @Override + public void vendorUpdate(HashMap venderInfo) { + sqlSession.update("vendorUpdate", venderInfo); + + } + + @Override + public List getNexusSkinListByVendorKey(HashMap venderInfo) { + return sqlSession.selectList("getNexusSkinListByVendorKey", venderInfo); + } + + @Override + public void nexusSkinUpdate(HashMap venderInfo) { + sqlSession.update("nexusSkinUpdate", venderInfo); + + } + + @Override + public String getParseTarget() { + return sqlSession.selectOne("getParseTarget", null); + } + + @Override + public String getParseTargetExtr() { + return sqlSessionSub.selectOne("getParseTargetExtr", null); + } + + @Override + public HashMap getParseUseYn(int siteIdx) { + return sqlSession.selectOne("getParseUseYn", siteIdx); + } + + @Override + public void insertParseUse(HashMap parseParam) { + sqlSession.insert("insertParseUse", parseParam); + + } + + @Override + public List getApiBetVendorList(int siteIdx) { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getApiBetVendorList", siteIdx); + } + + @Override + public int getApiBetTransactionCnt(BetParam param) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getApiBetTransactionCnt", param); + } + + @Override + public List getApiBetTransactionList(BetParam param) { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getApiBetTransactionList", param); + } + + @Override + public void updVendorMapForDefault(Site site) { + // TODO Auto-generated method stub + sqlSession.update("updVendorMapForDefault", site); + } + + @Override + public void updVendorCreditRateForDefault(Site site) { + // TODO Auto-generated method stub + sqlSession.update("updVendorCreditRateForDefault", site); + } + + @Override + public void deleteVendorAccountForDefault(Site site) { + // TODO Auto-generated method stub + sqlSession.update("deleteVendorAccountForDefault", site); + } + + @Override + public HashMap getParseUserYn(HashMap pum) { + return sqlSession.selectOne("getParseUserYn", pum); + } + + @Override + public void setParseUserYn(HashMap pum) { + sqlSession.update("setParseUserYn", pum); + + } + + @Override + public OTPInfo getOtpInfo(long siteIdx) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getOtpInfo", siteIdx); + } + + @Override + public OTPInfo getOtpInfoByManger(long siteIdx) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getOtpInfoByManger", siteIdx); + } + + @Override + public int registSuperOtp(OTPInfo param) { + // TODO Auto-generated method stub + return sqlSession.insert("registSuperOtp", param); + } + + @Override + public HashMap getSiteOnlyVendorInfo(HashMap vendorParam) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getSiteOnlyVendorInfo", vendorParam); + } + + @Override + public TrfApiInfo getTrfApiInfo(HashMap mapParam) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getTrfApiInfo", mapParam); + } + + @Override + public void agentIpsUpdate(Site site) { + sqlSession.update("agentIpsUpdate", site); + + } + + @Override + public int insertEvoDetail(HashMap detailMap) { + // TODO Auto-generated method stub + return sqlSession.insert("insertEvoDetail", detailMap); + } + + @Override + public HashMap getCommonApiInfo(HashMap commonParam) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getCommonApiInfo", commonParam); + } + + @Override + public HashMap getBeforeTranInfo(String vendorTranKey) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getBeforeTranInfo", vendorTranKey); + } + + @Override + public List getParseTargetGame(String gameType) { + return sqlSession.selectList("getParseTargetGame", gameType); + } + + @Override + public String getOrgDetailData(BetParam param) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getOrgDetailData", param); + } + + @Override + public String getParDetailData(BetParam param) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getParDetailData", param); + } + + @Override + public HashMap getBetInfoByTranKey(String vendorTranKey) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getBetInfoByTranKey", vendorTranKey); + } + + @Override + public HashMap getParseInfo(HashMap param) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getParseInfo", param); + } + + @Override + public int getBlockParseGameId(String gameId) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getBlockParseGameId", gameId); + } + + @Override + public HashMap getBeforeTranInfo2(String vendorTranKey) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getBeforeTranInfo2", vendorTranKey); + } + + @Override + public String getMemberByIdx(HashMap memParam) { + return sqlSession.selectOne("getMemberByIdx", memParam); + } + + @Override + public List getSiteVendorList2(int siteIdx) { + // TODO Auto-generated method stub + return sqlSession.selectList("getSiteVendorList2", siteIdx); + } + + @Override + public List getVendorList2(int siteIdx) { + // TODO Auto-generated method stub + return sqlSession.selectList("getVendorList2", siteIdx); + } + + @Override + public void saveSvcr(HashMap paramMap) { + // TODO Auto-generated method stub + sqlSession.insert("saveSvcr", paramMap); + } + + @Override + public int siteVenderCodeCheck(HashMap paramMap) { + // TODO Auto-generated method stub + return sqlSession.selectOne("siteVenderCodeCheck", paramMap); + } + + @Override + public void saveVendorRate2(HashMap paramMap) { + // TODO Auto-generated method stub + sqlSession.update("saveVendorRate2", paramMap); + } + + @Override + public String getSiteKey(HashMap paramMap) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getSiteKey", paramMap); + } + + @Override + public String getVendorTitle(HashMap paramMap) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getVendorTitle", paramMap); + } + + @Override + public Long getUserTimeout(HashMap accLog) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getUserTimeout", accLog); + } + + @Override + public int updateUserTimeout(HashMap accLog) { + // TODO Auto-generated method stub + return sqlSession.update("updateUserTimeout", accLog); + } + + @Override + public String getGameKeyByNexusGameId(String gameId) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getGameKeyByNexusGameId", gameId); + } + + @Override + public String getDebitIsParse(String betId) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getDebitIsParse", betId); + } + + @Override + public int updateParseUseYN(String useYn) { + // TODO Auto-generated method stub + return sqlSession.update("updateParseUseYN", useYn); + } + + @Override + public int insertTheaTrxId(HashMap param) { + // TODO Auto-generated method stub + return sqlSession.insert("insertTheaTrxId", param); + } + + @Override + public HashMap getApiKeyInfo(String vendorTitle) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getApiKeyInfo", vendorTitle); + } + + @Override + public HashMap getApiKeyInfo2(HashMap keyParam) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getApiKeyInfo2", keyParam); + } + + @Override + public HashMap getRefBetInfoByTranId(String tranId) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getRefBetInfoByTranId", tranId); + } + + @Override + public int updMemberBalance(HashMap balanceMap) { + // TODO Auto-generated method stub + return sqlSession.update("updMemberBalance", balanceMap); + } + + @Override + public int getMemberBalance(HashMap balanceMap) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getMemberBalance", balanceMap); + } + + @Override + public HashMap getMemberId(String vendorUsername) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getMemberId", vendorUsername); + } + + @Override + public int checkMemberId(String vendorUsername) { + // TODO Auto-generated method stub + return sqlSession.selectOne("checkMemberId", vendorUsername); + } + + @Override + public HashMap getNewSiteApiInfo(String vendorUsername) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getNewSiteApiInfo", vendorUsername); + } + + @Override + public HashMap getNewSiteVendorInfo(HashMap param) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getNewSiteVendorInfo", param); + } + + @Override + public int updateTestCnt(Site site) { + // TODO Auto-generated method stub + return sqlSession.update("updateTestCnt", site); + } + + @Override + public int updateParseEvoYn(HashMap param) { + // TODO Auto-generated method stub + return sqlSession.update("updateParseEvoYn", param); + } + + @Override + public int saveParsEvoAmount(SiteSearch param) { + // TODO Auto-generated method stub + return sqlSession.update("saveParsEvoAmount", param); + } + + @Override + public int getUserBalance(HashMap balanceMap) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getUserBalance", balanceMap); + } + + @Override + public List getMyDownSite(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSession.selectList("getMyDownSite", search); + } + + @Override + public HashMap getCreditInfo(String siteId) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getCreditInfo", siteId); + } + + @Override + public int checkDownSite(Map checkDown) { + // TODO Auto-generated method stub + return sqlSession.selectOne("checkDownSite", checkDown); + } + + @Override + public List getSiteTreeList(String siteId) { + // TODO Auto-generated method stub + return sqlSession.selectList("getSiteTreeList", siteId); + } + + @Override + public int getMyDownSiteCheck(Site targetsite) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getMyDownSiteCheck", targetsite); + } + + @Override + public void insertParseUseYn(Site site) { + // TODO Auto-generated method stub + sqlSession.insert("insertParseUseYn", site); + } + + @Override + public int updateSitePwd(SitePwdVO sitePwdVO) { + // TODO Auto-generated method stub + return sqlSession.update("updateSitePwd", sitePwdVO); + } + + @Override + public Site getSite(Site site) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getSite", site); + } + + @Override + public void siteVenderLobbyUpdate(Vendor vendor) { + // TODO Auto-generated method stub + sqlSession.update("siteVenderLobbyUpdate", vendor); + } + + @Override + public List getVendorMapList(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSession.selectList("getVendorMapList", search); + } + + @Override + public List geLobbyList(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSession.selectList("geLobbyList", search); + } + + @Override + public String siteVenderRate(Vendor vendor) { + // TODO Auto-generated method stub + return sqlSession.selectOne("siteVenderRate", vendor); + } + + @Override + public int getBoardListCnt(BoardSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getBoardListCnt", search); + } + + @Override + public List> getBoardList(BoardSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getBoardList", search); + } + + @Override + public HashMap getBoardDetail(long boardIdx) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getBoardDetail", boardIdx); + } + + @Override + public int getSiteCallbackErrLogListCnt(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getSiteCallbackErrLogListCnt", search); + } + + @Override + public List getSiteCallbackErrLogList(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getSiteCallbackErrLogList", search); + } + + @Override + public List getSiteTreeInfo(HashMap param) { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getSiteTreeInfo", param); + } + + @Override + public int getUserListCnt(UserSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getUserListCnt", search); + } + + @Override + public List> getUserList(UserSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getUserList", search); + } + + @Override + public HashMap getUserDetail(UserSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getUserDetail", search); + } + + @Override + public void insertCmsIp(Site site) { + // TODO Auto-generated method stub + sqlSession.insert("insertCmsIp", site); + } + + @Override + public int getSiteListCntForApi(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getSiteListCntForApi", search); + } + + @Override + public List getSiteListForApi(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSession.selectList("getSiteListForApi", search); + } + + @Override + public Site getSiteDetailForApi(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getSiteDetailForApi", search); + } + + @Override + public List getVendorListForApi(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSession.selectList("getVendorListForApi", search); + } + + @Override + public List getSiteVendorListForApi(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSession.selectList("getSiteVendorListForApi", search); + } + + @Override + public HashMap getRefIdByVendorTranKey(String vendorTranKey) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getRefIdByVendorTranKey", vendorTranKey); + } + + @Override + public int updateUserMaxBet(HashMap param) { + return sqlSession.update("updateUserMaxBet", param); + } + + @Override + public int insertTranLog(HashMap logParam) { + return sqlSession.insert("insertTranLog", logParam); + } + + @Override + public HashMap getSiteSubCredit(String siteId) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getSiteSubCredit", siteId); + } + + @Override + public String getBetAmountByTranParam(HashMap param) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getBetAmountByTranParam", param); + } + +} diff --git a/src/main/java/com/bb/dao/SplusDao.java b/src/main/java/com/bb/dao/SplusDao.java new file mode 100644 index 0000000..dbff911 --- /dev/null +++ b/src/main/java/com/bb/dao/SplusDao.java @@ -0,0 +1,24 @@ +package com.bb.dao; + + +import java.util.Map; + +public interface SplusDao { + + void insertSplus(Map splusBetParam); + + void udpateEvent(Map eventParam); + + void udpateBet(Map splusBetParam); + + void cancelBet(Map splusBetParam); + + int getReserveCnt(Map trxParam); + + int getCommitCnt(Map trxParam); + + int getDeReverseCnt(Map trxParam); + + int getCustomerCnt(Map trxParam); + +} diff --git a/src/main/java/com/bb/dao/SplusDaoImpl.java b/src/main/java/com/bb/dao/SplusDaoImpl.java new file mode 100644 index 0000000..8e873ba --- /dev/null +++ b/src/main/java/com/bb/dao/SplusDaoImpl.java @@ -0,0 +1,78 @@ +package com.bb.dao; + +import java.util.Map; + +import org.apache.ibatis.session.SqlSession; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Repository; + +@Repository("splusDao") +public class SplusDaoImpl implements SplusDao { + + /** 메인DB 연결 */ + @Autowired @Qualifier("sqlSessionMain") + protected SqlSession sqlSession; + + /** 서브DB 연결 */ + @Autowired @Qualifier("sqlSessionSub") + protected SqlSession sqlSessionSub; + + + @Override + public void insertSplus(Map splusBetParam) { + System.out.print("dsfsdfsdfsdfsdfsdf"); + sqlSession.insert("insertSplus", splusBetParam); + + } + + + @Override + public void udpateEvent(Map eventParam) { + sqlSession.update("udpateEvent", eventParam); + + } + + + @Override + public void udpateBet(Map splusBetParam) { + sqlSession.update("udpateBet", splusBetParam); + + } + + + @Override + public void cancelBet(Map splusBetParam) { + sqlSession.update("udpacancelBeteBet", splusBetParam); + + } + + + @Override + public int getReserveCnt(Map trxParam) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getReserveCnt", trxParam); + } + + + @Override + public int getCommitCnt(Map trxParam) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getCommitCnt", trxParam); + } + + + @Override + public int getDeReverseCnt(Map trxParam) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getDeReverseCnt", trxParam); + } + + + @Override + public int getCustomerCnt(Map trxParam) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getCustomerCnt", trxParam); + } + +} diff --git a/src/main/java/com/bb/dao/StatDao.java b/src/main/java/com/bb/dao/StatDao.java new file mode 100644 index 0000000..53d9cb1 --- /dev/null +++ b/src/main/java/com/bb/dao/StatDao.java @@ -0,0 +1,89 @@ +package com.bb.dao; + +import java.util.HashMap; +import java.util.List; + +import com.bb.model.ReportSearch; +import com.bb.model.Site; +import com.bb.model.SiteSearch; + +import jakarta.validation.Valid; + + +public interface StatDao { + + int getSiteDailyReportListCnt(SiteSearch search); + + List getSiteDailyReportList(SiteSearch search); + + int getVendorDailyReportListCnt(SiteSearch search); + + List getVendorDailyReportList(SiteSearch search); + + List getBottomSiteDailyReportList(SiteSearch search); + + HashMap getMonthCredit(SiteSearch search); + + List getUserDailyReportList(SiteSearch search); + + List getUserReportSum(SiteSearch search); + + List getAdminPushInfo(); + + int getAgentReportCnt(SiteSearch search); + + List getAgentReportList(SiteSearch search); + + int getAgentReportCnt2(SiteSearch search); + + List getAgentReportList2(SiteSearch search); + + HashMap getAgentReportTotal(SiteSearch search); + + + + String getlastMonth(SiteSearch search); + + List getVendorDailyReportListDay(SiteSearch search); + + List getVendorDailyReportListMonth(SiteSearch search); + + List getVendorDailyReportListDaySUM(SiteSearch search); + + List getVendorDailyReportListMonthSUM(SiteSearch search); + + List getSiteReportList(SiteSearch search); + + List getSiteReportListSum(SiteSearch search); + + List getSiteReportMemList(SiteSearch search); + + List getSiteReportMemListSum(SiteSearch search); + + List getSiteReportListToDay(SiteSearch search); + + List getSiteReportListSumToDay(SiteSearch search); + + List getDashBoardList(SiteSearch search); + + List getDashBoardMonth(SiteSearch search); + + HashMap getYdayBetInfoBySite(Site targetSite); + + HashMap getMonthBetInfoBySite(Site targetSite); + + HashMap getYdayBetInfoByUser(HashMap targetUser); + + HashMap getMonthBetInfoByUser(HashMap targetUser); + + HashMap getVendorDailyReportMonthByParse(SiteSearch search); + + List getVendorDailyReportListDayByParse(SiteSearch search); + + HashMap getHybridReport(ReportSearch search); + + List getHybridReportList(@Valid ReportSearch search); + + HashMap getHybridReportTotal(@Valid ReportSearch search); + +} diff --git a/src/main/java/com/bb/dao/StatDaoImpl.java b/src/main/java/com/bb/dao/StatDaoImpl.java new file mode 100644 index 0000000..b315225 --- /dev/null +++ b/src/main/java/com/bb/dao/StatDaoImpl.java @@ -0,0 +1,236 @@ +package com.bb.dao; + +import java.util.HashMap; +import java.util.List; + +import org.apache.ibatis.session.SqlSession; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Repository; + +import com.bb.model.ReportSearch; +import com.bb.model.Site; +import com.bb.model.SiteSearch; + +import jakarta.validation.Valid; + +@Repository("statDao") +public class StatDaoImpl implements StatDao { + + /** 메인DB 연결 */ + @Autowired @Qualifier("sqlSessionMain") + protected SqlSession sqlSession; + + /** 서브DB 연결 */ + @Autowired @Qualifier("sqlSessionSub") + protected SqlSession sqlSessionSub; + + @Override + public int getSiteDailyReportListCnt(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getSiteDailyReportListCnt", search); + } + + @Override + public List getSiteDailyReportList(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSession.selectList("getSiteDailyReportList", search); + } + + @Override + public int getVendorDailyReportListCnt(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getVendorDailyReportListCnt", search); + } + + @Override + public List getVendorDailyReportList(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSession.selectList("getVendorDailyReportList", search); + } + + @Override + public List getBottomSiteDailyReportList(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSession.selectList("getBottomSiteDailyReportList", search); + } + + @Override + public HashMap getMonthCredit(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getMonthCredit", search); + } + + @Override + public List getUserDailyReportList(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSession.selectList("getUserDailyReportList", search); + } + + @Override + public List getUserReportSum(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSession.selectList("getUserReportSum", search); + } + + @Override + public List getAdminPushInfo() { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getAdminPushInfo", null); + } + + @Override + public int getAgentReportCnt(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getAgentReportCnt", search); + } + + @Override + public List getAgentReportList(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getAgentReportList", search); + } + + @Override + public int getAgentReportCnt2(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getAgentReportCnt2", search); + } + + @Override + public List getAgentReportList2(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getAgentReportList2", search); + } + + @Override + public HashMap getAgentReportTotal(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getAgentReportTotal", search); + } + + + + @Override + public String getlastMonth(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSession.selectOne("getlastMonth", search); + } + + @Override + public List getVendorDailyReportListDay(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getVendorDailyReportListDay", search); + } + + @Override + public List getVendorDailyReportListMonth(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getVendorDailyReportListMonth", search); + } + + @Override + public List getVendorDailyReportListDaySUM(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getVendorDailyReportListDaySUM", search); + } + + @Override + public List getVendorDailyReportListMonthSUM(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getVendorDailyReportListMonthSUM", search); + } + + @Override + public List getSiteReportList(SiteSearch search) { + return sqlSessionSub.selectList("getSiteReportList", search); + } + + @Override + public List getSiteReportListSum(SiteSearch search) { + return sqlSessionSub.selectList("getSiteReportListSum", search); + } + + @Override + public List getSiteReportMemList(SiteSearch search) { + return sqlSessionSub.selectList("getSiteReportMemList", search); + } + + @Override + public List getSiteReportMemListSum(SiteSearch search) { + return sqlSessionSub.selectList("getSiteReportMemListSum", search); + } + + @Override + public List getSiteReportListToDay(SiteSearch search) { + return sqlSessionSub.selectList("getSiteReportListToDay", search); + } + + @Override + public List getSiteReportListSumToDay(SiteSearch search) { + return sqlSessionSub.selectList("getSiteReportListSumToDay", search); + } + + @Override + public List getDashBoardList(SiteSearch search) { + return sqlSessionSub.selectList("getDashBoardList", search); + } + + @Override + public List getDashBoardMonth(SiteSearch search) { + return sqlSessionSub.selectList("getDashBoardMonth", search); + } + + @Override + public HashMap getYdayBetInfoBySite(Site targetSite) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getYdayBetInfoBySite", targetSite); + } + + @Override + public HashMap getMonthBetInfoBySite(Site targetSite) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getMonthBetInfoBySite", targetSite); + } + + @Override + public HashMap getYdayBetInfoByUser(HashMap targetUser) { + return sqlSessionSub.selectOne("getYdayBetInfoByUser", targetUser); + } + + @Override + public HashMap getMonthBetInfoByUser(HashMap targetUser) { + return sqlSessionSub.selectOne("getMonthBetInfoByUser", targetUser); + } + + @Override + public HashMap getVendorDailyReportMonthByParse(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getVendorDailyReportMonthByParse", search); + } + + @Override + public List getVendorDailyReportListDayByParse(SiteSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getVendorDailyReportListDayByParse", search); + } + + @Override + public HashMap getHybridReport(ReportSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getHybridReport", search); + } + + @Override + public List getHybridReportList(@Valid ReportSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getHybridReportList", search); + } + + @Override + public HashMap getHybridReportTotal(@Valid ReportSearch search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getHybridReportTotal", search); + } + +} diff --git a/src/main/java/com/bb/dao/TplusDao.java b/src/main/java/com/bb/dao/TplusDao.java new file mode 100644 index 0000000..c8f3d39 --- /dev/null +++ b/src/main/java/com/bb/dao/TplusDao.java @@ -0,0 +1,5 @@ +package com.bb.dao; + +public interface TplusDao { + +} diff --git a/src/main/java/com/bb/dao/TplusDaoImpl.java b/src/main/java/com/bb/dao/TplusDaoImpl.java new file mode 100644 index 0000000..e24c5e3 --- /dev/null +++ b/src/main/java/com/bb/dao/TplusDaoImpl.java @@ -0,0 +1,24 @@ +package com.bb.dao; + +import java.util.HashMap; +import java.util.List; + +import org.apache.ibatis.session.SqlSession; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Repository; + +import com.bb.model.CronStatusVo; + +@Repository("tplusDao") +public class TplusDaoImpl implements TplusDao { + + /** 메인DB 연결 */ + @Autowired @Qualifier("sqlSessionMain") + protected SqlSession sqlSession; + + /** 서브DB 연결 */ + @Autowired @Qualifier("sqlSessionSub") + protected SqlSession sqlSessionSub; + +} diff --git a/src/main/java/com/bb/dao/TransDao.java b/src/main/java/com/bb/dao/TransDao.java new file mode 100644 index 0000000..5ab9d0a --- /dev/null +++ b/src/main/java/com/bb/dao/TransDao.java @@ -0,0 +1,36 @@ +package com.bb.dao; + +import java.util.HashMap; +import java.util.List; + +import com.bb.model.BetParam; +import com.bb.model.NexusTrplVO; +import com.bb.model.TransSearchVO; + +public interface TransDao { + + int getTransBetListCnt(TransSearchVO search); + + List> getTransBetList(TransSearchVO search); + + HashMap getTransBetListSum(TransSearchVO search); + + int getTransBetFastListCnt(TransSearchVO search); + + List> getTransBetFastList(TransSearchVO search); + + HashMap getBetListItem(String betId); + + HashMap getTransBetFastListSum(TransSearchVO search); + + HashMap getBetInfoByBetId(BetParam param); + + String getGsoftRoundIdByBetId(String betId); + + HashMap getSiteBetByRefIdFromOld(BetParam param); + + HashMap getApiInfo(String vendorTitle); + + int deleteEvoDetailNull(HashMap detailMap); + +} diff --git a/src/main/java/com/bb/dao/TransDaoImpl.java b/src/main/java/com/bb/dao/TransDaoImpl.java new file mode 100644 index 0000000..b5c03d7 --- /dev/null +++ b/src/main/java/com/bb/dao/TransDaoImpl.java @@ -0,0 +1,98 @@ +package com.bb.dao; + +import java.util.HashMap; +import java.util.List; + +import org.apache.ibatis.session.SqlSession; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Repository; + +import com.bb.model.BetParam; +import com.bb.model.NexusTrplVO; +import com.bb.model.TransSearchVO; + +@Repository("transDao") +public class TransDaoImpl implements TransDao { + + /** 메인DB 연결 */ + @Autowired @Qualifier("sqlSessionMain") + protected SqlSession sqlSession; + + /** 서브DB 연결 */ + @Autowired @Qualifier("sqlSessionSub") + protected SqlSession sqlSessionSub; + + @Override + public int getTransBetListCnt(TransSearchVO search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getTransBetListCnt", search); + } + + @Override + public List> getTransBetList(TransSearchVO search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getTransBetList", search); + } + + @Override + public HashMap getTransBetListSum(TransSearchVO search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getTransBetListSum", search); + } + + @Override + public int getTransBetFastListCnt(TransSearchVO search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getTransBetFastListCnt", search); + } + + @Override + public List> getTransBetFastList(TransSearchVO search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectList("getTransBetFastList", search); + } + + @Override + public HashMap getBetListItem(String betId) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getBetListItem", betId); + } + + @Override + public HashMap getTransBetFastListSum(TransSearchVO search) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getTransBetFastListSum", search); + } + + @Override + public HashMap getBetInfoByBetId(BetParam param) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getBetInfoByBetId", param); + } + + @Override + public String getGsoftRoundIdByBetId(String betId) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getGsoftRoundIdByBetId", betId); + } + + @Override + public HashMap getSiteBetByRefIdFromOld(BetParam param) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getSiteBetByRefIdFromOld", param); + } + + @Override + public HashMap getApiInfo(String vendorTitle) { + // TODO Auto-generated method stub + return sqlSessionSub.selectOne("getApiInfo", vendorTitle); + } + + @Override + public int deleteEvoDetailNull(HashMap detailMap) { + // TODO Auto-generated method stub + return sqlSession.delete("deleteEvoDetailNull", detailMap); + } + +} diff --git a/src/main/java/com/bb/exception/ApiException.java b/src/main/java/com/bb/exception/ApiException.java new file mode 100644 index 0000000..b33d59f --- /dev/null +++ b/src/main/java/com/bb/exception/ApiException.java @@ -0,0 +1,37 @@ +package com.bb.exception; + +import com.bb.model.ApiResponse; + +/** + * @FileName : ApiException + * @Project : skhappy + * @Date : 2019. 04. 10. + * @Author : pulip + * @Description : + */ +public class ApiException extends Exception { + protected ApiResponse apiResponse; + + public ApiException() { + this("E001", "오류가 발생하였습니다."); + } + + public ApiException(String message) { + this("E001", message); + } + + /*public ApiException(ApiResponse apiResponse) { + this(apiResponse, "오류가 발생하였습니다."); + }*/ + + public ApiException(String resultCode, String message) { + this.apiResponse = new ApiResponse(); + + this.apiResponse.setResultCode(resultCode); + this.apiResponse.setResultMessage(message); + } + + public ApiResponse getApiResponse() { + return this.apiResponse; + } +} diff --git a/src/main/java/com/bb/exception/NoDataApiException.java b/src/main/java/com/bb/exception/NoDataApiException.java new file mode 100644 index 0000000..a104a98 --- /dev/null +++ b/src/main/java/com/bb/exception/NoDataApiException.java @@ -0,0 +1,9 @@ +package com.bb.exception; + + + +public class NoDataApiException extends ApiException { + public NoDataApiException() { + super("9004", "조회된 데이터가 없습니다."); + } +} diff --git a/src/main/java/com/bb/exception/RequestArraySizeApiException.java b/src/main/java/com/bb/exception/RequestArraySizeApiException.java new file mode 100644 index 0000000..faef2c4 --- /dev/null +++ b/src/main/java/com/bb/exception/RequestArraySizeApiException.java @@ -0,0 +1,10 @@ +package com.bb.exception; + + + + +public class RequestArraySizeApiException extends ApiException { + public RequestArraySizeApiException(String parameterName) { + super("9003", "요청 배열 파라미터 크기에 오류가 있습니다. : " + parameterName); + } +} diff --git a/src/main/java/com/bb/exception/RequestHeaderApiException.java b/src/main/java/com/bb/exception/RequestHeaderApiException.java new file mode 100644 index 0000000..f6e7a62 --- /dev/null +++ b/src/main/java/com/bb/exception/RequestHeaderApiException.java @@ -0,0 +1,9 @@ +package com.bb.exception; + + + +public class RequestHeaderApiException extends ApiException { + public RequestHeaderApiException(String headerName) { + super("9001", "요청 헤더정보가 없습니다 : " + headerName); + } +} diff --git a/src/main/java/com/bb/exception/RequestParameterApiException.java b/src/main/java/com/bb/exception/RequestParameterApiException.java new file mode 100644 index 0000000..ed816c0 --- /dev/null +++ b/src/main/java/com/bb/exception/RequestParameterApiException.java @@ -0,0 +1,8 @@ +package com.bb.exception; + + +public class RequestParameterApiException extends ApiException { + public RequestParameterApiException(String parameterName) { + super("9002", "필수 요청 파라미터가 없습니다. : " + parameterName); + } +} diff --git a/src/main/java/com/bb/front/ApiCoinController.java b/src/main/java/com/bb/front/ApiCoinController.java new file mode 100644 index 0000000..a4025e2 --- /dev/null +++ b/src/main/java/com/bb/front/ApiCoinController.java @@ -0,0 +1,177 @@ +package com.bb.front; + +import java.io.IOException; +import java.net.InetAddress; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +import com.bb.exception.ApiException; +import com.bb.jwt.JwtManager; +import com.bb.model.ApiResponse; +import com.bb.model.CoinVo; +import com.bb.model.Site; +import com.bb.service.CoinService; +import com.bb.service.SiteService; + +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; + +@RestController +@Slf4j +@RequestMapping("/api/coin") +@RequiredArgsConstructor +@SecurityRequirement(name = "Authorization") +public class ApiCoinController { + + @Autowired + private final JwtManager jwtManager; + + @Autowired + SiteService siteService; + + @Autowired + CoinService coinService; + + @ResponseBody + @PostMapping(value="") + public ApiResponse getCoinInfo(@RequestHeader String token, HttpServletRequest request) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + String coinSymbol = request.getParameter("symbol"); + String currency = request.getParameter("currency"); + try { + + + //apiKey 체크 + Site site = siteService.getSiteInfo(request); + if(site==null) { + throw new ApiException("1000", "accessDinied"); + } + if(token==null) { + throw new ApiException("1000", "accessDinied"); + } + + //토큰체크 + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfo(token); + if(token == null) { + log.error("#-p1::agentBalance::"+ "access denied token"); + throw new ApiException("1000", "access denied token"); + } + + + CoinVo coinVo = coinService.getCoinInfo(coinSymbol, currency); + + + apiResponse.put("info",coinVo); + apiResponse.success(); + return apiResponse; + + + }catch(Exception e) { + log.info("ddd" +e.toString()); + apiResponse.fail(); + return apiResponse; + } + } + + @Scheduled(fixedDelay = 300*1000) // 5분 + public void getCoinAllInfo() throws Exception { + +// Authentication auth = +// new UsernamePasswordAuthenticationToken("system", null, +// AuthorityUtils.createAuthorityList("ROLE_ADMIN")); +// SecurityContextHolder.getContext().setAuthentication(auth); + + String hostname = InetAddress.getLocalHost().getHostName(); + if("ip-172-31-40-216.ap-northeast-3.compute.internal".equals(hostname)) { // 3번 서버 호스트 네임으로 빠꺼야함 + String[] currency = {"usd","krw"}; + String cgApiKey = "CG-wJAwrJWZCSbzmBhk545CTcR3"; + try { + + for(int cu=0;cu= 0) ) { + log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + apiResponse.setResultMessage("access denied IP"); + return apiResponse; + } + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token); + final String LOG_PREFIX = "#-API::USER::userKick::"+tokenInfo.getSid()+"::::"; + + log.info(LOG_PREFIX+ "UserKickParam::"+param.toString()); + + // 회원 정보 조회 + CashParam cashParam = new CashParam(); + cashParam.setSiteIdx(site.getSiteIdx()); + cashParam.setMemberId(param.getUserid()); + Member member = siteService.getMember2(cashParam); + + if(member == null) { + log.error(LOG_PREFIX+ "NOT_FOUND_USER"); + apiResponse.setResultCode("0"); + apiResponse.setResultMessage("존재하지 않는 유저입니다"); + return apiResponse; + } + + // 유저의 마지막 접속 벤더 조회 + String lastVendor = null; + if(member.getLastInVendorIdx() > 0) { + // lastInVendorIdx로 벤더 정보 조회 + HashMap vendorParam = new HashMap<>(); + vendorParam.put("siteIdx", member.getSiteIdx()); + vendorParam.put("vendorIdx", member.getLastInVendorIdx()); + + HashMap vendorInfo = siteService.getSiteOnlyVendorInfo(vendorParam); + if(vendorInfo != null && vendorInfo.containsKey("vendorCode")) { + lastVendor = vendorInfo.get("vendorCode"); + log.info(LOG_PREFIX + "Found last vendor: " + lastVendor + " (vendorIdx: " + member.getLastInVendorIdx() + ")"); + } + } + + boolean kickResult = false; + + if(lastVendor != null && !lastVendor.isEmpty()) { + log.info(LOG_PREFIX + "Last vendor: " + lastVendor); + + // 벤더별 강제 종료 처리 + switch(lastVendor.toLowerCase()) { + case "dpcore": + // TODO: DPCore API 호출 + log.info(LOG_PREFIX + "Calling DPCore kick API"); + kickResult = true; + break; + case "ace2": + // TODO: Ace API 호출 + log.info(LOG_PREFIX + "Calling Ace kick API"); + kickResult = true; + break; + case "onix": + // Onix API 호출 + try { + HashMap onixVendorParam = new HashMap<>(); + onixVendorParam.put("siteIdx", member.getSiteIdx()); + onixVendorParam.put("vendorCode", "onix"); + HashMap onixApiInfo = siteService.getSiteOnlyVendorInfo(onixVendorParam); + + if(onixApiInfo != null && !onixApiInfo.isEmpty()) { + String apiUrl = onixApiInfo.get("apiUrl"); + String apiKey = onixApiInfo.get("apiKey"); + + if(apiUrl != null && apiKey != null) { + String kickUrl = apiUrl + "/csapi/kick"; + log.info(LOG_PREFIX + "Calling Onix kick API: " + kickUrl); + + try { + // Request Body 생성 + HashMap requestBody = new HashMap<>(); + requestBody.put("userid", member.getMemberId()); + + // WebClient로 Onix kick API 호출 + String response = webClient.post() + .uri(kickUrl) + .header("Authorization", "Bearer " + apiKey) + .header("Content-Type", "application/json") + .bodyValue(requestBody) + .retrieve() + .bodyToMono(String.class) + .block(); + + log.info(LOG_PREFIX + "Onix API Response: " + response); + + // Response 파싱 + if(response != null && response.contains("\"result\":1")) { + kickResult = true; + log.info(LOG_PREFIX + "Onix kick success"); + } else { + log.error(LOG_PREFIX + "Onix kick failed: " + response); + } + } catch(Exception apiException) { + log.error(LOG_PREFIX + "Onix API call exception", apiException); + } + } + } + } catch(Exception e) { + log.error(LOG_PREFIX + "Onix kick API error", e); + } + break; + case "pink": + // TODO: Pink API 호출 + log.info(LOG_PREFIX + "Calling Pink kick API"); + kickResult = true; + break; + default: + log.info(LOG_PREFIX + "Vendor not supported for kick: " + lastVendor); + kickResult = true; + break; + } + } else { + log.info(LOG_PREFIX + "No vendor info found, returning success"); + kickResult = true; + } + + if(kickResult) { + log.info(LOG_PREFIX+ "USER_KICK_SUCCESS::"+param.getUserid()); + apiResponse.setResultCode("1"); + apiResponse.setResultMessage("강퇴 성공"); + } else { + log.error(LOG_PREFIX+ "USER_KICK_FAILED::"+param.getUserid()); + apiResponse.setResultCode("0"); + apiResponse.setResultMessage("강퇴 실패"); + } + + } catch(Exception e) { + log.error(e.toString()); + e.printStackTrace(); + apiResponse.setResultCode("0"); + apiResponse.setResultMessage("token is no valid"); + } + + } catch (Exception e) { + log.error("Kick API error", e); + e.printStackTrace(); + apiResponse.setResultCode("0"); + apiResponse.setResultMessage("강퇴 실패"); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping(value="/auth") + public synchronized ApiResponse auth(HttpServletRequest request, @RequestBody AuthParam param) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + final String LOG_PREFIX = "#-auth::"+param.getUserId()+"::::"; + + // apiKey 체크 + Site site = siteService.getSiteInfo(request); + if(site == null) { + log.error(LOG_PREFIX+ "A1001:Access denied Key"); + apiResponse.setResultCode("A1001"); + apiResponse.setResultMessage("Access denied Key"); + return apiResponse; + } + System.out.println("site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(" + +site.getSiteIp()+")" + +IPKit.getIpAddressByRequest(request) +","+ site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) ); + + if( !( site.getSiteIp() == null || "".equals(site.getSiteIp()) || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0 ) ) { + log.error(LOG_PREFIX+ "site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + log.error(LOG_PREFIX+ "A1002:Access denied IP"); + apiResponse.setResultCode("A1002"); + apiResponse.setResultMessage("Access denied IP"); + return apiResponse; + } + + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(param); + JSONObject reqObj = new JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + try { + //회원아이디 유표성체크 + String regex = "^[a-zA-z0-9]{3,25}$"; + Pattern p = Pattern.compile(regex); + + Matcher m = p.matcher(param.getUserId()); + + if(!m.matches()) { + log.error(LOG_PREFIX+ "A1003:Check user id"); + apiResponse.setResultCode("A1003"); + apiResponse.setResultMessage("Check user id"); + return apiResponse; + } + + if(param.getUserId().length() > 19) { + log.error(LOG_PREFIX+ "A1004:Check user id length"); + apiResponse.setResultCode("A1004"); + apiResponse.setResultMessage("Check user id length"); + return apiResponse; + } + + + // 회원 유뮤체크 + CommonParam commonParam = new CommonParam(); + commonParam.setSiteIdx(site.getSiteIdx()); + commonParam.setAuthParam(param); + Member member = siteService.getMember(commonParam); + + // 회원 없을경우 가입시키기 + if(member == null) { + siteService.insertMember(commonParam); + member = siteService.getMember(commonParam); + } + + // 폭탄게임 전용 본인 체크키 업데이트 + if(member.getDowinId() == null || "".equals(member.getDowinId())) { + String bombToken = new TempKey().generateAuthKey(); + member.setBombAccId(bombToken); + member.setDowinId(bombToken); + siteService.updateBombKey(member); + } + + log.info(LOG_PREFIX+ "member::result: " + member.toString()); + + // 토큰생성 + JwtClame jwtinfo = new JwtClame(); + jwtinfo.setSiteId(site.getSiteId()); + jwtinfo.setMemId(commonParam.getAuthParam().getUserId()); + String tok = jwtManager.generateToken(jwtinfo); + + + // 파워볼 API Key 발급 및 site_vendor_map.vendorApiId, site_vendor_map.vendorApiKey 세팅 선처리 + try { + + } catch(Exception e) { + log.error(LOG_PREFIX+ "POWER_BALL::Exception: " + e.getMessage()); + log.error(LOG_PREFIX+ "POWER_BALL::Exception: " + e.toString()); + } + + // 결과보내기 + apiResponse.put("userId", member.getMemberIdx()); + apiResponse.put("token", tok); + apiResponse.success(); + + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.toString()); + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @GetMapping(value="/playBombDemo") + public ApiResponse playBombDemo(HttpServletRequest request) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + String lauchURL=""; + String bombToken = new TempKey().generateAuthKey(); + + siteService.inserDemoUSer(bombToken); + + + String gameUrl ="http://tpabomb.com?"; + String gameUrl2 = "userID="+bombToken; + + String language = "en"; + + + + gameUrl2 += "&cc=pan" ; + gameUrl2 += "&nation=" + language; + gameUrl2 += "&loginToken=" +bombToken; + + + log.info("###-BOMB API-### Request : " + gameUrl2); + lauchURL = gameUrl + AesUtil.getAES128_Encode(gameUrl2); + apiResponse.put("gameurl", lauchURL); + + return apiResponse; + + } + + @ResponseBody + @PostMapping(value="/play") + public ApiResponse play(@RequestHeader String token, HttpServletRequest request, @RequestBody PlayParam param) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + final String LOG_PREFIX = "#-play::"+param.getUserId()+"::::"; + + try { + if(param.getRequestAT() == null || param.getRequestAT().equals("")) { + param.setRequestAT(Long.toString(System.currentTimeMillis())); + } + long requestAT1 = Long.parseLong(param.getRequestAT()); + long currentAT1 = System.currentTimeMillis(); + SimpleDateFormat chkSdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + String requestATStr1 = chkSdf1.format(requestAT1); + String currentATStr1 = chkSdf1.format(currentAT1); + log.info(LOG_PREFIX+ "## /play ##[requestATStr:"+requestATStr1+"][currentATStr:"+currentATStr1+"]"); + log.info(LOG_PREFIX+ "Authorization::"+request.getHeader("Authorization")); + log.info(LOG_PREFIX+ "token::"+token); + + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(param); + JSONObject reqObj = new JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + String ip = param.getUserIp(); + String[] ipArray = ip.split(","); + log.info(LOG_PREFIX+ "ipArray::"+ipArray.toString()); + ip = ipArray[0]; + param.setUserIp(ip); + + log.info(LOG_PREFIX+ "PlayParam::"+param.toString()); + /* Date타입으로 변경 */ + double diff1 = (currentAT1 - requestAT1) / 1000.0; // 초 + if(diff1 > 3.5) { + log.error(LOG_PREFIX+ "/play ## "+diff1+"초 통신 지연발생[requestATStr:"+requestATStr1+"][currentATStr:"+currentATStr1+"]"); + log.error(LOG_PREFIX+ "P1001:Network time delay"); + throw new ApiException("P1001", "Network time delay"); + } + + //apiKey 체크 + Site site = siteService.getSiteInfo(request); + if(site==null) { + log.error(LOG_PREFIX+ "P1002:Access denied Key"); + throw new ApiException("P1002", "Access denied Key"); + } + if(token==null) { + log.error(LOG_PREFIX+ "P1003:Access token check"); + throw new ApiException("P1003", "Access token check"); + } + + //토큰체크 + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfo(token); + log.info(LOG_PREFIX+ "TokenInfo::"+tokenInfo.toString()); + + final String IS_TRANSFER = site.getIsTransfer(); + + //회원정보 + AuthParam authParam = new AuthParam(); + authParam.setUserId(tokenInfo.getMid()); + CommonParam commonParam = new CommonParam(); + commonParam.setSiteIdx(site.getSiteIdx()); + commonParam.setAuthParam(authParam); + commonParam.setPlayParam(param); + log.info(LOG_PREFIX+ "CommonParam::"+commonParam.toString()); + Member member = siteService.getMember(commonParam); + + //회사명 회사연동 벤더변 벤더연동 + HashMap venderInfo = siteService.getVenderApiInfo(commonParam); + if(venderInfo == null) { + venderInfo = siteService.getOnlyVenderInfo(commonParam); + if(venderInfo == null) { + log.error(LOG_PREFIX+ "P1004:Vendor not setting"); + throw new ApiException("P1004", "Vendor not setting"); + } + } + + // userMaxBet 처리 (유저별 최대베팅제한금액) + Long userMaxBet = param.getUserMaxBet(); + if(userMaxBet == null) { + userMaxBet = 0L; // 값이 비워져있으면 0으로 처리 + } + + // site_member 테이블에 userMaxBet 저장 + HashMap userMaxBetParam = new HashMap<>(); + userMaxBetParam.put("siteIdx", site.getSiteIdx()); + userMaxBetParam.put("memberIdx", member.getMemberIdx()); + userMaxBetParam.put("userMaxBet", userMaxBet); + int updateResult = siteService.updateUserMaxBet(userMaxBetParam); + log.info(LOG_PREFIX+ "updateUserMaxBet Result: " + updateResult + ", userMaxBet: " + userMaxBet); + + // tran_log 테이블에 로그 기록 시도 (실패해도 게임 플레이는 계속됨) + try { + HashMap tranLogParam = new HashMap<>(); + tranLogParam.put("siteIdx", site.getSiteIdx()); + tranLogParam.put("vendorIdx", venderInfo.get("vendorIdx")); + tranLogParam.put("gameIdx", param.getGameKey()); + + // body에 memberIdx와 userMaxBet 정보 포함 + JSONObject bodyJson = new JSONObject(); + bodyJson.put("memberIdx", member.getMemberIdx()); + bodyJson.put("memberId", member.getMemberId()); + bodyJson.put("userMaxBet", userMaxBet); + bodyJson.put("userId", param.getUserId()); + bodyJson.put("gameKey", param.getGameKey()); + tranLogParam.put("body", bodyJson.toString()); + + int logResult = siteService.insertTranLog(tranLogParam); + log.info(LOG_PREFIX+ "insertTranLog Result: " + logResult); + } catch (Exception e) { + log.error(LOG_PREFIX+ "insertTranLog failed but continue play: " + e.getMessage()); + } + + long userBalance = 0; + long siteCredit = site.getCredit(); + String lauchURL =""; + String callbackType = "S"; + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("N")) { + if(param.getBalance() == null) { + log.error(LOG_PREFIX+ "P1005:User balance not null"); + throw new ApiException("P1005", "User balance not null"); + } + + userBalance = param.getBalance(); + + if(siteCredit < userBalance) { + log.error(LOG_PREFIX+ "P1006:Insufficient site credit"); + throw new ApiException("P1006", "Insufficient site credit"); + } + } + + log.info(LOG_PREFIX+ "venderInfo::" + venderInfo.toString()); + final int START_VENDOR_IDX = Integer.parseInt(venderInfo.get("vendorIdx").toString()); + final String START_VENDOR_TITLE = venderInfo.get("vendorTitle").toString(); + + Long requestTime = System.currentTimeMillis(); + HashMap accLog = new HashMap<>(); + accLog.put("siteIdx", site.getSiteIdx()); + accLog.put("memberIdx", member.getMemberIdx()); + // Timeout 체크 + Long userTimeout = siteService.getUserTimeout(accLog); + if(userTimeout == null) { + userTimeout = requestTime; + } else { + userTimeout = userTimeout + (1*1000); + } + if(requestTime < userTimeout) { + log.error(LOG_PREFIX+ "P1007:재요청 대기시간(8초)"); + throw new ApiException("P1007", "재요청 대기시간(8초)"); + } else { + log.info(LOG_PREFIX+ "마지막 요청으로부터 8초 이후에 요청"); + accLog.put("requestTime", requestTime); + int result = siteService.updateUserTimeout(accLog); + log.info(LOG_PREFIX+ "updateUserTimeout()::"+userTimeout); + log.info(LOG_PREFIX+ "[TIMEOUT result : " + result + "]"); + } + + + // Parsing start user set + HashMap usePaeseY = siteService.getParseUseYn(site.getSiteIdx()); + boolean isParseStartUser = false; + HashMap pum = new HashMap(); + if(usePaeseY != null && "Y".equals(usePaeseY.get("useYn").toString()) && START_VENDOR_IDX == 1 + && (START_VENDOR_TITLE.equals("dpcore")) + ) { + int parsEvoAmount = (int) usePaeseY.get("parsEvoAmount"); + long totalEvoBetAmt = member.getTotalEvoBetAmt(); + String parseEvoYn = member.getParseEvoYn(); + if(parsEvoAmount == 0) { + isParseStartUser = true; + } else { + if(parsEvoAmount < totalEvoBetAmt && parseEvoYn.equals("Y")) { + isParseStartUser = true; + } else { + isParseStartUser = false; + } + } + } else { + isParseStartUser = false; + } + + // Parsing start user set + String apiUsername = ""; + String apiNickname = ""; + String changeUrl = ""; + String changeApiKey = ""; + if(START_VENDOR_TITLE.equals("svendor") || START_VENDOR_TITLE.equals("pink")) { + apiUsername = member.getVendorUsername(); + if(apiUsername==null || "".equals(apiUsername)) { + + int cnt = 0; + do { + apiUsername = StringUtils.generateString(12); + cnt = siteService.checkMemberId(apiUsername); + } while(cnt != 0); + member.setVendorUsername(apiUsername); + } + apiNickname = site.getSiteId().substring(0, 2) + "_" + member.getMemberId(); + + // ##--isTransfer 처리-## + // Member balance sync + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", member.getSiteIdx()); + balanceMap.put("memberIdx", member.getMemberIdx()); + balanceMap.put("memberId", member.getMemberId()); + balanceMap.put("vendorUsername", member.getVendorUsername()); + int updBalanceResult = siteService.updMemberBalance(balanceMap); + log.info(LOG_PREFIX+ "updMemberBalance Result : " + updBalanceResult); + } else { + apiUsername = site.getSiteIdxHex() + member.getMemberId(); + apiNickname = apiUsername; + } + log.info(LOG_PREFIX+ "[PLAY_INFO] Mamber::" + member.toString()); + log.info(LOG_PREFIX+ "[PLAY_INFO] ParseUserMap::" + pum.toString()); + log.info(LOG_PREFIX+ "[PLAY_INFO] isParseStartUser::" + isParseStartUser); + log.info(LOG_PREFIX+ "[PLAY_INFO] START_VENDOR_IDX::" + START_VENDOR_IDX); + log.info(LOG_PREFIX+ "[PLAY_INFO] userBalance::" + userBalance); + log.info(LOG_PREFIX+ "[PLAY_INFO] apiUsername::" + apiUsername); + log.info(LOG_PREFIX+ "[PLAY_INFO] apiNickname::" + apiNickname); + log.info(LOG_PREFIX+ "[PLAY_INFO] changeUrl::" + changeUrl); + log.info(LOG_PREFIX+ "[PLAY_INFO] changeApiKey::" + changeApiKey); + + if(venderInfo.get("vendorCode").toString().contains("org_pragmatic")) { + + String tok = apiUsername; + log.info(LOG_PREFIX+ "[PLAY_INFO] tok::" + tok); + venderInfo.put("username", apiUsername); + + if("org_pragmatic_casino".equals(venderInfo.get("vendorCode").toString())) { + venderInfo.put("game_key", "101"); + }else { + venderInfo.put("game_key", param.getGameKey()); + + } + + lauchURL = pragmaticService.getLaunchUrl(LOG_PREFIX, tok, venderInfo, param, site.getSiteIdxHex() + member.getMemberId()); + apiResponse.put("gameurl", lauchURL); + apiResponse.put("callbackType", "S"); + callbackType = "S"; + + } else if(venderInfo.get("vendorCode").toString().contains("panda_pragmatic_slot")) { + String apiBaseUrl = venderInfo.get("vendorApiUrl").toString(); + String apiAgentId = venderInfo.get("vendorApiId").toString(); + String apiKey = venderInfo.get("vendorApiKey").toString(); + String apiVendor = venderInfo.get("vendorGameCode").toString(); + String apiGameCode = param.getGameKey(); + + HashMap apiInfo = new HashMap<>(); + apiInfo.put("apiBaseUrl", apiBaseUrl); + apiInfo.put("apiAgentId", apiAgentId); + apiInfo.put("apiKey", apiKey); + apiInfo.put("apiVendor", apiVendor); + apiInfo.put("apiGameCode", apiGameCode); + apiInfo.put("apiUsername", site.getSiteIdxHex() + member.getMemberId()); + apiInfo.put("apiNickname", apiNickname); + log.info(LOG_PREFIX+ "PANDA::API Info::" + apiInfo); + + lauchURL = pandaService.getLaunchUrl(LOG_PREFIX, apiInfo); + + apiResponse.put("gameurl", lauchURL); + apiResponse.put("callbackType", "S"); + callbackType = "S"; + + } else if(venderInfo.get("vendorCode").toString().contains("pracp_pragmatic_slot")) { + + venderInfo.put("username", site.getSiteIdxHex() + member.getMemberId()); + venderInfo.put("vendor_key","pragmatic_slot"); + venderInfo.put("game_key", param.getGameKey()); + + String apiBaseUrl = venderInfo.get("vendorApiUrl").toString(); + String apiAgentCode = venderInfo.get("vendorApiId").toString(); + String apiToken = venderInfo.get("vendorApiKey").toString(); + String apiProviderCode = venderInfo.get("vendorGameCode").toString(); + String apiGameCode = param.getGameKey(); + + HashMap apiInfo = new HashMap<>(); + apiInfo.put("apiBaseUrl", apiBaseUrl); + apiInfo.put("apiAgentCode", apiAgentCode); + apiInfo.put("apiToken", apiToken); + apiInfo.put("apiProviderCode", apiProviderCode); + apiInfo.put("apiGameCode", apiGameCode); + apiInfo.put("apiPlayerCode", site.getSiteIdxHex() + member.getMemberId()); + log.info(LOG_PREFIX+ "PRACP::API Info::" + apiInfo); + + lauchURL = pracpService.getLaunchUrl(LOG_PREFIX, apiInfo); + + apiResponse.put("gameurl", lauchURL); + apiResponse.put("callbackType", "S"); + callbackType = "S"; + + } else if(venderInfo.get("vendorCode").toString().contains("grand_pragmatic_slot")) { + + venderInfo.put("username", site.getSiteIdxHex() + member.getMemberId()); + venderInfo.put("vendor_key","pragmatic_slot"); + venderInfo.put("game_key", param.getGameKey()); + lauchURL = grandService.getLaunchUrl(venderInfo); + apiResponse.put("gameurl", lauchURL); + apiResponse.put("callbackType", "S"); + callbackType = "S"; + + } else if(venderInfo.get("vendorCode").toString().contains("svendor_") + || venderInfo.get("vendorCode").toString().contains("pink_")) { + String apiBaseUrl = venderInfo.get("vendorApiUrl").toString(); + String apiAgent = venderInfo.get("vendorApiId").toString(); + String apiKey = venderInfo.get("vendorApiKey").toString(); + String apiVendor = venderInfo.get("vendorGameCode").toString(); + String apiUserIp = param.getUserIp(); + String apiGameKey = ""; + String apiGameSkin = ""; + + String category = venderInfo.get("vendorGameCategory").toString(); + String vendorKey = venderInfo.get("vendorKey").toString(); + + + if("SLOT".equals(category)) { + apiGameKey = param.getGameKey(); + } else { + // Casino + if(vendorKey.equals("C01")) { + // Evolution + apiGameKey = "top_games"; + if(param.getSkinType() != null && !param.getSkinType().equals("")) { + apiGameSkin = param.getSkinType(); + } else { + apiGameSkin = venderInfo.get("extrSkinType").toString(); + } + } else if(vendorKey.equals("C02")) { + // Pragmatic Live + apiGameKey = "101"; + } else if(vendorKey.equals("C03")) { + // Dream Gaming + apiGameKey = "dgcasino"; + } else if(vendorKey.equals("C04")) { + // 보타 카지노 + apiGameKey = "bota"; + } else if(vendorKey.equals("C10")) { + // Asia Gaming + apiGameKey = "0"; + } else if(vendorKey.equals("C05")) { + // Microgaming Casino + apiGameKey = "MGL_GRAND_LobbyAll"; + } else if(vendorKey.equals("C08")) { + // Oriental Gaming + apiGameKey = "1"; + } else if(vendorKey.equals("C09")) { + // Ezugi + apiGameKey = "1008"; + } else if(vendorKey.equals("C32")) { + // 섹시 바카라 + apiGameKey = "MX-LIVE-001"; + } else { + apiGameKey = ""; + } + } + + HashMap apiInfo = new HashMap<>(); + apiInfo.put("apiBaseUrl", apiBaseUrl); + apiInfo.put("apiAgent", apiAgent); + apiInfo.put("apiKey", apiKey); + apiInfo.put("userid", apiUsername); + apiInfo.put("nickname", apiUsername); + apiInfo.put("userip", param.getUserIp()); + apiInfo.put("category", category); + apiInfo.put("vendor", apiVendor); + apiInfo.put("game", apiGameKey); + apiInfo.put("skin", apiGameSkin); + log.info(LOG_PREFIX+ "PINK::API Info::" + apiInfo); + + // Create User + JSONObject createRes = svendorService.create(LOG_PREFIX, apiInfo); + log.info(LOG_PREFIX+ "PINK::createRes::" + createRes.toString()); + if(createRes.getInt("code") == 0 || createRes.getInt("code") == 97) { + lauchURL = svendorService.playUrl(LOG_PREFIX, apiInfo); + } else { + throw new ApiException("Svendor User Create ERROR"); + } + + log.info(LOG_PREFIX+ "PINK::lauchURL: " + lauchURL); + apiResponse.put("gameurl", lauchURL); + apiResponse.put("callbackType", "S"); + callbackType = "S"; + + } else if((venderInfo.get("vendorCode").toString().startsWith("tower_pragmatic_slot"))) { + + String gameApiUrl = venderInfo.get("vendorApiUrl").toString(); + gameApiUrl += "/v2/play?site_code="+venderInfo.get("vendorApiId").toString(); + gameApiUrl += "&user_id="+site.getSiteIdxHex()+member.getMemberId(); + gameApiUrl += "&nickname="+site.getSiteIdxHex()+member.getMemberId(); + gameApiUrl += "&vendorCode="+venderInfo.get("vendorGameCode").toString(); + gameApiUrl += "&gameCode="+param.getGameKey(); + gameApiUrl += "&user_ip="+param.getUserIp(); + gameApiUrl += "&session_token="+token; + + venderInfo.put("gameApiUrl", gameApiUrl); + String launchUrl = towerService.getLaunchUrl(venderInfo); + + apiResponse.put("gameurl", launchUrl); + apiResponse.put("callbackType", "S"); + + } else if("splus".equals(venderInfo.get("vendorCode").toString())) { + + lauchURL = venderInfo.get("vendorApiUrl").toString() +"?operatorToken="+URLEncoder.encode(token, "UTF-8"); + apiResponse.put("gameurl", lauchURL); + apiResponse.put("callbackType", "S"); + + } else if("bti_zeno".equals(venderInfo.get("vendorCode").toString())) { + + lauchURL = venderInfo.get("vendorApiUrl").toString() +"?operatorToken="+URLEncoder.encode(token, "UTF-8"); + apiResponse.put("gameurl", lauchURL); + apiResponse.put("callbackType", "S"); + + } else if("bet_radar".equals(venderInfo.get("vendorCode").toString())) { + String apiBaseUrl = venderInfo.get("vendorApiUrl").toString(); + String apiKey = venderInfo.get("vendorApiKey").toString(); + String apiDevice = "DESKTOP"; + + if(param.getIsMobile().equals("Y")) { + apiDevice = "MOBILE"; + } + + HashMap apiInfo = new HashMap<>(); + apiInfo.put("apiBaseUrl", apiBaseUrl); + apiInfo.put("apiKey", apiKey); + apiInfo.put("apiUsername", apiUsername); + apiInfo.put("apiNickname", apiNickname); + apiInfo.put("apiDevice", apiDevice); + + lauchURL = betRadarService.gameLaunch(LOG_PREFIX, apiInfo); + if(lauchURL == null || lauchURL.equals("")) { + log.error(LOG_PREFIX+ "BET_RADAR::GAME_LAUNCH:::Error"); + throw new ApiException("P111", "GAME_START_ERROR"); + } else { + apiResponse.put("gameurl", lauchURL); + apiResponse.put("callbackType", "S"); + callbackType = "S"; + } + + } else if("tpabomb".equals(venderInfo.get("vendorCode").toString())) { + log.info(LOG_PREFIX+ "bomb::"+ "###-BOMB API-### param: " + param.toString()); + //String gameUrl ="http://"+venderInfo.get("vendorAuthApiUrl").toString()+"/user/login/"+venderInfo.get("vendorApiId").toString(); + String gameUrl ="http://"+venderInfo.get("vendorAuthApiUrl").toString()+"?"; + String gameUrl2 = "userID="+site.getSiteIdxHex()+member.getMemberId(); + + String language = "KR"; + if( !(param.getLanguage() == null || "".equals(param.getLanguage()))) { + language = param.getLanguage(); + } + + + log.info(LOG_PREFIX+ "bomb::"+ "###-BOMB API-### param.getDecYn(): " + param.getDecYn()); + + + if("Y".equals(param.getDecYn())) { + gameUrl2 += "&cc=tbomb2"; + } else { + gameUrl2 += "&cc=" + venderInfo.get("vendorApiId").toString(); + param.setDecYn("N"); + } + + + HashMap decimalParam = new HashMap(); + decimalParam.put("bombAccId", member.getBombAccId()); + decimalParam.put("decYn",param.getDecYn()); + siteService.updateDecimal(decimalParam); + + + gameUrl2 += "&nation=" + language; + gameUrl2 += "&loginToken=" + member.getBombAccId(); + + + log.info(LOG_PREFIX+ "bomb::"+ "###-BOMB API-### gameUrl2 : " + gameUrl2); + lauchURL = gameUrl + AesUtil.getAES128_Encode(gameUrl2); + log.info(LOG_PREFIX+ "bomb::"+ "###-BOMB API-### lauchURL : " + lauchURL); + apiResponse.put("gameurl", lauchURL); + apiResponse.put("callbackType", "S"); + + } else if(venderInfo.get("vendorCode").toString().contains("pbg_ball")) { + // PowerBall API 게임실행 Proc + venderInfo.put("userId", site.getSiteIdxHex()+member.getMemberId()); + lauchURL = powerBallService.getGameUrl(venderInfo, LOG_PREFIX); + if(lauchURL != null && !lauchURL.equals("")) { + apiResponse.put("gameurl", lauchURL); + apiResponse.put("callbackType", "S"); + callbackType = "S"; + } else { + log.error(LOG_PREFIX+ "PowerBall::getLaunchUrl() FAIL"); + throw new ApiException("PowerBall_99", "Game Start Error"); + } + } else if(venderInfo.get("vendorCode").toString().contains("nexus_")) { + String vendorGameCategory = venderInfo.get("vendorGameCategory").toString(); + String vendorKey = venderInfo.get("vendorKey").toString(); + String apiBaseUrl = venderInfo.get("vendorApiUrl").toString(); + String apiAgentId = venderInfo.get("vendorApiId").toString(); + String apiAgentSecretKey = venderInfo.get("vendorApiKey").toString(); + String apiVendorKey = venderInfo.get("vendorGameCode").toString(); + String apiGameKey = ""; + if("SLOT".equals(vendorGameCategory)) { + apiGameKey = param.getGameKey(); + } else { + // Casino + // apiGameKey = "A"; // 1,000 ~ 1,000,000 + // apiGameKey = venderInfo.get("nexusSkinType").toString(); + if(param.getSkinType() != null && !param.getSkinType().equals("")) { + apiGameKey = param.getSkinType(); + } else { + apiGameKey = venderInfo.get("nexusSkinType").toString(); + } + log.info(LOG_PREFIX+ "NEXUS::apiSkin::" + apiGameKey); + } + + String apiUserIp = param.getUserIp(); + String apiLanguage = "ko"; + String apiPlatform = "desktop"; + + if(param.getIsMobile().equals("Y")) { + apiPlatform = "mobile"; + } + + NexusApiInfo nexusApiInfo = NexusApiInfo.builder() + .siteIdx(member.getSiteIdx()) + .memberIdx(member.getMemberIdx()) + .apiBaseUrl(apiBaseUrl) + .agentId(apiAgentId) + .agentSecretKey(apiAgentSecretKey) + .vendorKey(apiVendorKey) + .gameKey(apiGameKey) + .username(apiUsername) + .nickname(apiNickname) + .siteUsername(apiUsername) + .ip(apiUserIp) + .language(apiLanguage) + .platform(apiPlatform) + .build(); + log.info(LOG_PREFIX+ "NEXUS::NexusApiInfo::" + nexusApiInfo); + + // Create User + JSONObject userObj = nexusService.createUser(LOG_PREFIX, nexusApiInfo); + if(!(userObj.getInt("code")==0 || userObj.getInt("code")==-500)) { + log.error(LOG_PREFIX+ "NEXUS::createUser::error::code::" + userObj.getInt("code")); + log.error(LOG_PREFIX+ "NEXUS::createUser::error::message::" + userObj.getString("msg")); + throw new ApiException("NX"+userObj.getInt("code"), userObj.getString("msg")); + } + + // Game url + lauchURL = nexusService.gameStart(LOG_PREFIX, nexusApiInfo); + if(lauchURL != null && !lauchURL.equals("")) { + apiResponse.put("gameurl", lauchURL); + apiResponse.put("callbackType", "S"); + callbackType = "S"; + } else { + log.error(LOG_PREFIX+ "NEXUS::gameStart() FAIL"); + throw new ApiException("NEXUS_99", "Game Start Error"); + } + + } else if(venderInfo.get("vendorCode").toString().contains("ace2_")) { + String vendorGameCategory = venderInfo.get("vendorGameCategory").toString(); + String vendorKey = venderInfo.get("vendorKey").toString(); + String apiBaseUrl = venderInfo.get("vendorApiUrl").toString(); + String apiAgentId = venderInfo.get("vendorApiId").toString(); + String apiAgentSecretKey = venderInfo.get("vendorApiKey").toString(); + String apiVendorKey = venderInfo.get("vendorGameCode").toString(); + String apiGameKey = ""; + if("SLOT".equals(vendorGameCategory)) { + apiGameKey = param.getGameKey(); + } else { + // Casino + // apiGameKey = "A"; // 1,000 ~ 1,000,000 + // apiGameKey = venderInfo.get("nexusSkinType").toString(); + if(param.getSkinType() != null && !param.getSkinType().equals("")) { + apiGameKey = param.getSkinType(); + } else { + apiGameKey = venderInfo.get("nexusSkinType").toString(); + } + log.info(LOG_PREFIX+ "ACE::apiSkin::" + apiGameKey); + } + + String apiUserIp = param.getUserIp(); + String apiLanguage = "ko"; + String apiPlatform = "desktop"; + + if(param.getIsMobile().equals("Y")) { + apiPlatform = "mobile"; + } + + NexusApiInfo nexusApiInfo = NexusApiInfo.builder() + .siteIdx(member.getSiteIdx()) + .memberIdx(member.getMemberIdx()) + .apiBaseUrl(apiBaseUrl) + .agentId(apiAgentId) + .agentSecretKey(apiAgentSecretKey) + .vendorKey(apiVendorKey) + .gameKey(apiGameKey) + .username(apiUsername) + .nickname(apiNickname) + .siteUsername(apiUsername) + .ip(apiUserIp) + .language(apiLanguage) + .platform(apiPlatform) + .build(); + log.info(LOG_PREFIX+ "ACE::NexusApiInfo::" + nexusApiInfo); + + // Create User + JSONObject userObj = nexusService.createUser(LOG_PREFIX, nexusApiInfo); + if(!(userObj.getInt("code")==0 || userObj.getInt("code")==-500)) { + log.error(LOG_PREFIX+ "ACE::createUser::error::code::" + userObj.getInt("code")); + log.error(LOG_PREFIX+ "ACE::createUser::error::message::" + userObj.getString("msg")); + throw new ApiException("AC"+userObj.getInt("code"), userObj.getString("msg")); + } + + // Game url + lauchURL = nexusService.gameStart(LOG_PREFIX, nexusApiInfo); + if(lauchURL != null && !lauchURL.equals("")) { + apiResponse.put("gameurl", lauchURL); + apiResponse.put("callbackType", "S"); + callbackType = "S"; + } else { + log.error(LOG_PREFIX+ "ACE::gameStart() FAIL"); + throw new ApiException("ACE_99", "Game Start Error"); + } + + } else if(venderInfo.get("vendorCode").toString().contains("tplus_")) { + // 게임실행 API Proc + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + long reqAtL = System.currentTimeMillis(); + String reqAt = sdf.format(reqAtL); + + String apiBaseUrl = venderInfo.get("vendorApiUrl").toString(); + String apiAuthKey = venderInfo.get("vendorApiKey").toString(); + String thirdparty = venderInfo.get("vendorGameCode").toString(); + String uuid = param.getGameKey(); + TplusApiInfo apiInfo = TplusApiInfo.builder() + .siteIdx(member.getSiteIdx()) + .memberIdx(member.getMemberIdx()) + .apiBaseUrl(apiBaseUrl) + .clientId(venderInfo.get("vendorApiId").toString()) + .apiAuthKey(apiAuthKey) + .thirdparty(thirdparty) + .uuid(uuid) + .apiUsername(apiUsername) + .reqAt(reqAt).build(); + + log.info(LOG_PREFIX+ "tplus::apiInfo: " + apiInfo); + + + /* + Long tplusBalance = tplusService.getBalanceUser(LOG_PREFIX, apiInfo); + if(tplusBalance == null) { + log.error(LOG_PREFIX+ "tplus::Get Balance Error"); + throw new ApiException("H999", "BALANCE_ERROR"); + } + */ + + lauchURL = tplusService.getGameLink(LOG_PREFIX, apiInfo); + if(lauchURL == null || lauchURL.equals("")) { + log.error(LOG_PREFIX+"tplus::tplusService.getGameLink() Error"); + throw new ApiException("99", "GET_GAMELINK_ERROR"); + } + log.info(LOG_PREFIX+ "tplus::lauchURL: " + lauchURL); + apiResponse.put("gameurl", lauchURL); + apiResponse.put("callbackType", "S"); + callbackType = "S"; + + } else if(venderInfo.get("vendorCode").toString().contains("prime_") + || venderInfo.get("vendorCode").toString().contains("dpcore_")) { + String apiBaseUrl = venderInfo.get("vendorApiUrl").toString(); + String apiHybrdUrl = venderInfo.get("vendorAuthApiUrl").toString(); + String apiKey = "Bearer "+venderInfo.get("vendorApiKey").toString(); + String apiVendor = venderInfo.get("vendorGameCode").toString(); // Evolution + String apiGameId = venderInfo.get("nexusSkinType").toString(); // Evolution Top Games Lobby + if(param.getSkinType() != null && !param.getSkinType().equals("")) { + apiGameId = param.getSkinType(); + } + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.set("Authorization", apiKey); + String gameUrl = ""; + JSONObject playParams = new JSONObject(); + if(venderInfo.get("vendorCode").toString().contains("prime_")) { + gameUrl = apiBaseUrl + "/aapi/play"; + apiGameId = "evolution_top_games"; + apiVendor = "1"; + } else { + // dpcore의 경우 + + gameUrl = apiBaseUrl + "/dapi/play"; + + apiGameId = "evolution_top_games"; + } + playParams.put("username", apiUsername); + playParams.put("game_id", apiGameId); + playParams.put("vendor", apiVendor); + String apiSkin = ""; + if(param.getSkinType() != null && !param.getSkinType().equals("")) { + apiSkin = param.getSkinType(); + } else { + apiSkin = venderInfo.get("nexusSkinType").toString(); + } + playParams.put("skin", apiSkin); + playParams.put("domain", apiHybrdUrl); + + if(isParseStartUser) { + playParams.put("genuine", false); + } else { + playParams.put("genuine", true); + } + + log.info(LOG_PREFIX+ "PRIME::Play Url: " + gameUrl); + log.info(LOG_PREFIX+ "PRIME::Play Headers: " + headers.toString()); + log.info(LOG_PREFIX+ "PRIME::Play Params: " + playParams.toString()); + + ResponseEntity playRes = null; + JSONObject playJson = null; + try { + playRes = webClient.post() + .uri(gameUrl) + .headers(h -> h.addAll(headers)) + .bodyValue(playParams.toString()) + .retrieve() + .toEntity(String.class) + .block(); + } catch(WebClientResponseException e) { + log.error(LOG_PREFIX+ "PRIME::Play HttpClientErrorException : " + e.getMessage()); + log.error(LOG_PREFIX+ "PRIME::Play status code : " + e.getStatusCode().value()); + log.error(LOG_PREFIX+ "PRIME::Play response body : " + e.getResponseBodyAsString()); + playJson = new JSONObject(e.getResponseBodyAsString()); + log.error(LOG_PREFIX+ "PRIME::Play error : " + playJson.getString("message")); + throw new ApiException("P109", playJson.getString("message")); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "PRIME::Play ConnectTimeoutException::"+rae.getMessage()); + } + if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "PRIME::Play SocketTimeoutException::"+rae.getMessage()); + } + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "PRIME::Play InterruptedException::"+rae.getMessage()); + } + throw new ApiException("P110", rae.getMessage()); + } catch (Exception e) { + log.error(LOG_PREFIX+ "PRIME::Play Exception : " + e.getMessage()); + throw new ApiException("P111", e.getMessage()); + } + + if(playRes != null && playRes.getStatusCode() == HttpStatus.OK) { + log.info(LOG_PREFIX+ "PRIME::Play response : " + playRes.getBody()); + playJson = new JSONObject(playRes.getBody()); + + if(playJson.has("entry") && !apiHybrdUrl.equals("")) { + log.info(LOG_PREFIX+ "수정도메인 실행"); + lauchURL = "https://"+apiHybrdUrl+playJson.getString("entry"); + } else { + log.info(LOG_PREFIX+ "기본도메인 실행"); + lauchURL = playJson.getString("url"); + } + log.info(LOG_PREFIX+ "PRIME::Play lauchURL : " + lauchURL); + + apiResponse.put("gameurl", lauchURL); + apiResponse.put("callbackType", "S"); + callbackType = "S"; + } + + } else if(venderInfo.get("vendorCode").toString().contains("onix_")) { + // Onix API 게임실행 Proc + String apiBaseUrl = venderInfo.get("vendorApiUrl").toString(); + String apiId = venderInfo.get("vendorApiId").toString(); + String apiKey = venderInfo.get("vendorApiKey").toString(); + String apiGameCode = venderInfo.get("vendorGameCode").toString(); + String apiGameLobby = "evolution"; // Evolution 로비 (항상 evolution 고정) + + // if(param.getSkinType() != null && !param.getSkinType().equals("")) { + // apiGameLobby = param.getSkinType(); + // } + + log.info(LOG_PREFIX+ "[ONIX] API Base URL: " + apiBaseUrl); + log.info(LOG_PREFIX+ "[ONIX] API ID: " + apiId); + log.info(LOG_PREFIX+ "[ONIX] Game Code: " + apiGameCode); + + // Step 1: 사용자 생성 + HttpHeaders createHeaders = new HttpHeaders(); + createHeaders.setContentType(MediaType.APPLICATION_JSON); + createHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + createHeaders.set("Authorization", "Bearer " + apiKey); + + String createUrl = apiBaseUrl + "/csapi/create"; + JSONObject createBody = new JSONObject(); + createBody.put("userid", apiUsername); + + log.info(LOG_PREFIX+ "ONIX::Create Url: " + createUrl); + log.info(LOG_PREFIX+ "ONIX::Create Body: " + createBody.toString()); + + ResponseEntity createRes = null; + try { + createRes = webClient.post() + .uri(createUrl) + .headers(h -> h.addAll(createHeaders)) + .bodyValue(createBody.toString()) + .retrieve() + .toEntity(String.class) + .block(); + if(createRes != null && createRes.getStatusCode() == HttpStatus.OK) { + JSONObject createJson = new JSONObject(createRes.getBody()); + log.info(LOG_PREFIX+ "ONIX::Create Response: " + createJson.toString()); + int createResult = createJson.getInt("result"); + if(createResult != 1) { + log.error(LOG_PREFIX+ "ONIX::User Create Failed: " + createJson.getString("msg")); + throw new ApiException("ONX01", "User Create Error"); + } + } else { + throw new ApiException("ONX01", "User Create Response Error"); + } + } catch(ApiException e) { + throw e; + } catch(WebClientResponseException e) { + log.error(LOG_PREFIX+ "ONIX::Create HttpClientErrorException : " + e.getMessage()); + log.error(LOG_PREFIX+ "ONIX::Create status code : " + e.getStatusCode().value()); + log.error(LOG_PREFIX+ "ONIX::Create response body : " + e.getResponseBodyAsString()); + JSONObject errorJson = new JSONObject(e.getResponseBodyAsString()); + String errorMsg = errorJson.has("msg") ? errorJson.getString("msg") : "User Create Error"; + log.error(LOG_PREFIX+ "ONIX::Create error : " + errorMsg); + throw new ApiException("ONX01", errorMsg); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ONIX::Create ConnectTimeoutException::" + rae.getMessage()); + } + if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "ONIX::Create ReadTimeoutException::" + rae.getMessage()); + } + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "ONIX::Create InterruptedException::" + rae.getMessage()); + } + throw new ApiException("ONX01", rae.getMessage()); + } catch(Exception e) { + log.error(LOG_PREFIX+ "ONIX::Create Exception : " + e.getMessage()); + throw new ApiException("ONX01", e.getMessage()); + } + + // Step 2: 게임 URL 생성 + String gameUrl = apiBaseUrl + "/csapi/getGameUrl"; + JSONObject gameUrlBody = new JSONObject(); + gameUrlBody.put("code", apiGameCode); + gameUrlBody.put("subcode", apiGameLobby); + gameUrlBody.put("userid", apiUsername); + gameUrlBody.put("platform", param.getIsMobile().equals("Y") ? "mobile" : "pc"); + gameUrlBody.put("lobby", "0"); + + log.info(LOG_PREFIX+ "ONIX::GameUrl Url: " + gameUrl); + log.info(LOG_PREFIX+ "ONIX::GameUrl Body: " + gameUrlBody.toString()); + + ResponseEntity gameUrlRes = null; + try { + gameUrlRes = webClient.post() + .uri(gameUrl) + .headers(h -> h.addAll(createHeaders)) + .bodyValue(gameUrlBody.toString()) + .retrieve() + .toEntity(String.class) + .block(); + if(gameUrlRes != null && gameUrlRes.getStatusCode() == HttpStatus.OK) { + JSONObject gameUrlJson = new JSONObject(gameUrlRes.getBody()); + log.info(LOG_PREFIX+ "ONIX::GameUrl Response: " + gameUrlJson.toString()); + int gameUrlResult = gameUrlJson.getInt("result"); + if(gameUrlResult == 1) { + lauchURL = gameUrlJson.getString("link"); + log.info(LOG_PREFIX+ "ONIX::Game Launch URL: " + lauchURL); + apiResponse.put("gameurl", lauchURL); + apiResponse.put("callbackType", "S"); + callbackType = "S"; + } else { + log.error(LOG_PREFIX+ "ONIX::Game URL Generation Failed: " + gameUrlJson.getString("msg")); + throw new ApiException("ONX02", gameUrlJson.getString("msg")); + } + } else { + throw new ApiException("ONX02", "Game URL Response Error"); + } + } catch(ApiException e) { + throw e; + } catch(WebClientResponseException e) { + log.error(LOG_PREFIX+ "ONIX::GameUrl HttpClientErrorException : " + e.getMessage()); + log.error(LOG_PREFIX+ "ONIX::GameUrl status code : " + e.getStatusCode().value()); + log.error(LOG_PREFIX+ "ONIX::GameUrl response body : " + e.getResponseBodyAsString()); + JSONObject errorJson = new JSONObject(e.getResponseBodyAsString()); + String errorMsg = errorJson.has("msg") ? errorJson.getString("msg") : "Game URL Generation Error"; + log.error(LOG_PREFIX+ "ONIX::GameUrl error : " + errorMsg); + throw new ApiException("ONX02", errorMsg); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ONIX::GameUrl ConnectTimeoutException::" + rae.getMessage()); + } + if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "ONIX::GameUrl ReadTimeoutException::" + rae.getMessage()); + } + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "ONIX::GameUrl InterruptedException::" + rae.getMessage()); + } + throw new ApiException("ONX02", rae.getMessage()); + } catch(Exception e) { + log.error(LOG_PREFIX+ "ONIX::GameUrl Exception : " + e.getMessage()); + throw new ApiException("ONX02", e.getMessage()); + } + } else if(venderInfo.get("vendorCode").toString().contains("thenut_")) { + String apiBaseUrl = venderInfo.get("vendorApiUrl").toString(); + String apiKey = venderInfo.get("vendorApiKey").toString(); + String vendorGameCategory = venderInfo.get("vendorGameCategory").toString(); + String vendorKey = venderInfo.get("vendorKey").toString(); + String apiVendor = venderInfo.get("vendorGameCode").toString(); + String apiGameCode = ""; + if("SLOT".equals(vendorGameCategory)) { + apiGameCode = param.getGameKey(); + } else { + if(vendorKey.equals("C01")) { + apiGameCode = "evolution_top_games"; + } + } + + HashMap apiInfo = new HashMap<>(); + apiInfo.put("apiBaseUrl", apiBaseUrl); + apiInfo.put("apiKey", apiKey); + apiInfo.put("apiVendor", apiVendor); + apiInfo.put("apiGameCode", apiGameCode); + apiInfo.put("apiUsername", apiUsername); + apiInfo.put("apiNickname", apiNickname); + log.info(LOG_PREFIX+ "THENUT::API Info::" + apiInfo); + + // Get User Info + JSONObject userObj = thenutService.getUser(LOG_PREFIX, apiInfo); + if(userObj == null) { + // Create User + userObj = thenutService.createUser(LOG_PREFIX, apiInfo); + if(userObj == null) { + log.error(LOG_PREFIX+ "THENUT_01::Create User Error"); + throw new ApiException("THENUT_01", "Create User Error"); + } + } + + // Get User Token + String userToken = thenutService.createUserToken(LOG_PREFIX, apiInfo); + if(userToken == null || userToken.equals("")) { + log.error(LOG_PREFIX+ "THENUT_02::Get User Token Error"); + throw new ApiException("THENUT_02", "Get User Token Error"); + } else { + apiInfo.put("apiUserToken", userToken); + } + + // Get Game Url + lauchURL = thenutService.getGameUrl(LOG_PREFIX, apiInfo); + if(lauchURL != null && !lauchURL.equals("")) { + apiResponse.put("gameurl", lauchURL); + apiResponse.put("callbackType", "S"); + callbackType = "S"; + } else { + log.error(LOG_PREFIX+ "getGameUrl() FAIL"); + throw new ApiException("THENUT_99", "Game Start Error"); + } + } + + HashMap memParam = new HashMap<>(); + memParam.put("siteIdx", member.getSiteIdx()); + memParam.put("memberIdx", member.getMemberIdx()); + memParam.put("vendorPrefix", null); + + long lastInVendorIdx = START_VENDOR_IDX; + memParam.put("lastInVendorIdx", lastInVendorIdx); + int updResult = siteService.updMemLastVendorIdx(memParam); + log.info(LOG_PREFIX+ "updMemLastVendorIdx Result : " + updResult); + if(updResult >= 0) { + apiResponse.success(); + log.info(LOG_PREFIX+ "apiResponse : " + apiResponse.toString()); + log.info("#START_PLAY::"+venderInfo.get("vendorCode").toString()+"::"+param.getUserId()); + } else { + throw new ApiException("2000", "not setting"); + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + apiResponse.setResultCode("TE99"); + apiResponse.setResultMessage("ConnectTimeoutException"); + apiResponse.fail(); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + apiResponse.setResultCode("TE99"); + apiResponse.setResultMessage("SocketTimeoutException"); + apiResponse.fail(); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + apiResponse.setResultCode("TE99"); + apiResponse.setResultMessage("InterruptedException"); + apiResponse.fail(); + } + } catch(ApiException e) { + log.error(LOG_PREFIX+ "[ApiException]"+e.getApiResponse()); + apiResponse = e.getApiResponse(); + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + log.error(LOG_PREFIX+ "[Exception]"+e.getLocalizedMessage()); + log.error(LOG_PREFIX+ "[Exception]"+e.getMessage()); + log.error(LOG_PREFIX+ "[Exception]"+e.getStackTrace().toString()); + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + @ResponseBody + @PostMapping(value="/games") + public ApiResponse games(HttpServletRequest request, @RequestBody PlayParam param) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + try { + final String LOG_PREFIX = "#-games::"+param.getUserId()+"::::"; + + //apiKey 체크 + Site site = siteService.getSiteInfo(request); + if(site==null) { + log.error(LOG_PREFIX+ "G1001:Access denied Key"); + throw new ApiException("G1001", "Access denied Key"); + } + + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(param); + JSONObject reqObj = new JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + CommonParam commonParam = new CommonParam(); + commonParam.setSiteIdx(site.getSiteIdx()); + commonParam.setPlayParam(param); + log.info("#-games::"+param.getUserId()+"::::"+ commonParam.toString()); + HashMap venderInfo = siteService.getOnlyVenderInfo(commonParam); + if(venderInfo ==null) { + log.error(LOG_PREFIX+ "G1002:Vendor not setting"); + throw new ApiException("G1002", "Vendor not setting"); + } + + List gameList = new ArrayList<>(); + + if(venderInfo.get("vendorCode").toString().contains("org_pragmatic")) { + + gameList = pragmaticService.getGameList(LOG_PREFIX, venderInfo); + + } else if(venderInfo.get("vendorCode").toString().contains("panda_pragmatic_slot")) { + String apiBaseUrl = venderInfo.get("vendorApiUrl").toString(); + String apiAgentId = venderInfo.get("vendorApiId").toString(); + String apiKey = venderInfo.get("vendorApiKey").toString(); + String apiVendor = venderInfo.get("vendorGameCode").toString(); + + HashMap apiInfo = new HashMap<>(); + apiInfo.put("apiBaseUrl", apiBaseUrl); + apiInfo.put("apiAgentId", apiAgentId); + apiInfo.put("apiKey", apiKey); + apiInfo.put("apiVendor", apiVendor); + log.info(LOG_PREFIX+ "PANDA::API Info::" + apiInfo); + + gameList = pandaService.getGameList(LOG_PREFIX, apiInfo); + + } else if(venderInfo.get("vendorCode").toString().contains("pracp_pragmatic_slot")) { + String apiBaseUrl = venderInfo.get("vendorApiUrl").toString(); + String apiAgentCode = venderInfo.get("vendorApiId").toString(); + String apiToken = venderInfo.get("vendorApiKey").toString(); + String apiProviderCode = venderInfo.get("vendorGameCode").toString(); + + HashMap apiInfo = new HashMap<>(); + apiInfo.put("apiBaseUrl", apiBaseUrl); + apiInfo.put("apiAgentCode", apiAgentCode); + apiInfo.put("apiToken", apiToken); + apiInfo.put("apiProviderCode", apiProviderCode); + log.info(LOG_PREFIX+ "PRACP::API Info::" + apiInfo); + + gameList = pracpService.getGameList(LOG_PREFIX, apiInfo); + + } else if(venderInfo.get("vendorCode").toString().contains("grand_pragmatic_slot")) { + venderInfo.put("vendor_key", "pragmatic_slot"); + gameList = grandService.getGameList(venderInfo); + + } else if((venderInfo.get("vendorCode").toString().startsWith("tower_pragmatic_slot"))) { + gameList = towerService.getGameList(venderInfo); + + } else if(venderInfo.get("vendorCode").toString().contains("nexus_") + || venderInfo.get("vendorCode").toString().contains("ace2_")) { + String apiBaseUrl = venderInfo.get("vendorApiUrl").toString(); + String apiAgentId = venderInfo.get("vendorApiId").toString(); + String apiAgentSecretKey = venderInfo.get("vendorApiKey").toString(); + String apiVendorKey = venderInfo.get("vendorGameCode").toString(); + + NexusApiInfo apiInfo = NexusApiInfo.builder() + .apiBaseUrl(apiBaseUrl) + .agentId(apiAgentId) + .agentSecretKey(apiAgentSecretKey) + .vendorKey(apiVendorKey) + .skin("SLOT") + .type("Slot") + .build(); + + gameList = nexusService.gameList(LOG_PREFIX, apiInfo); + + } else if(venderInfo.get("vendorCode").toString().contains("tplus_")) { + String apiBaseUrl = venderInfo.get("vendorApiUrl").toString(); + String apiAuthKey = venderInfo.get("vendorApiKey").toString(); + String thirdparty = venderInfo.get("vendorGameCode").toString(); + + TplusApiInfo apiInfo = TplusApiInfo.builder() + .apiBaseUrl(apiBaseUrl) + .apiAuthKey(apiAuthKey) + .thirdparty(thirdparty) + .build(); + + log.info(LOG_PREFIX+ "TplusApiInfo : " + apiInfo); + + gameList = tplusService.gameList(LOG_PREFIX, apiInfo); + + } else if(venderInfo.get("vendorCode").toString().contains("svendor_") + || venderInfo.get("vendorCode").toString().contains("pink_")) { + String apiBaseUrl = venderInfo.get("vendorApiUrl").toString(); + String apiAgent = venderInfo.get("vendorApiId").toString(); + String apiKey = venderInfo.get("vendorApiKey").toString(); + String apiVendor = venderInfo.get("vendorGameCode").toString(); + + HashMap apiInfo = new HashMap<>(); + apiInfo.put("apiBaseUrl", apiBaseUrl); + apiInfo.put("apiAgent", apiAgent); + apiInfo.put("apiKey", apiKey); + apiInfo.put("vendor", apiVendor); + + gameList = svendorService.gameList(LOG_PREFIX, apiInfo); + + } else if(venderInfo.get("vendorCode").toString().contains("onix_")) { + String apiBaseUrl = venderInfo.get("vendorApiUrl").toString(); + String apiId = venderInfo.get("vendorApiId").toString(); + String apiKey = venderInfo.get("vendorApiKey").toString(); + String apiGameCode = venderInfo.get("vendorGameCode").toString(); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + + String listUrl = apiBaseUrl + "/csapi/Provider"; + JSONObject listBody = new JSONObject(); + listBody.put("type", "2"); + listBody.put("gameid", apiGameCode); + listBody.put("code", apiGameCode); + listBody.put("gametype", "live"); + + log.info(LOG_PREFIX+ "ONIX::Game List Url: " + listUrl); + log.info(LOG_PREFIX+ "ONIX::Game List Body: " + listBody.toString()); + + try { + ResponseEntity res = webClient.post() + .uri(listUrl) + .headers(h -> h.addAll(headers)) + .bodyValue(listBody.toString()) + .retrieve() + .toEntity(String.class) + .block(); + if(res != null && res.getBody() != null) { + JSONObject resObj = new JSONObject(res.getBody()); + int result = resObj.getInt("result"); + if(result == 1) { + JSONArray games = resObj.getJSONArray("data"); + int length = games.length(); + for(int i=0; i apiInfo = new HashMap<>(); + apiInfo.put("apiBaseUrl", apiBaseUrl); + apiInfo.put("apiKey", apiKey); + apiInfo.put("apiVendor", vendorCode); + log.info(LOG_PREFIX+ "THENUT::API Info::" + apiInfo); + + gameList = thenutService.getGameList(LOG_PREFIX, apiInfo); + apiResponse.put("list", gameList); + + } else { + gameList = siteService.getGameList(venderInfo); + } + + String banGameId = venderInfo.get("banGameId").toString().replaceAll(" ", "").toLowerCase(); + log.info(LOG_PREFIX+ "banGameIds : " + banGameId); + List list = new ArrayList<>(); + for(Game item : gameList) { + String gameId = item.getGameKey().toLowerCase(); + if(!"".equals(gameId) && !"".equals(banGameId) && banGameId.contains(gameId+"|")) { + log.info(LOG_PREFIX+ "banGameId: " + gameId + ", banGame: " + item.getGameName()); + } else { + list.add(item); + } + } + + apiResponse.put("list", list); + + apiResponse.success(); + } catch (Exception e) { + log.info(e.toString()); + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping(value="/members") + public ApiResponse members(@RequestHeader String token, HttpServletRequest request, @RequestBody MemberParam param) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + try { + + apiResponse.success(); + + } catch (Exception e) { + log.info(e.toString()); + e.printStackTrace(); + apiResponse.fail(); + } + return apiResponse; + } + + + @ResponseBody + @PostMapping(value="/creditInfo") + public ApiResponse creditInfo(HttpServletRequest request) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + try { + // apiKey 체크 + Site site = siteService.getSiteInfo(request); + if(site ==null) { + throw new ApiException("1000", "accessDinied"); + } + + long targetSiteCredit = siteService.getSiteCredit(site.getSiteId()); + apiResponse.put("credit", targetSiteCredit); + + long targetSitePoint = siteService.getSitePoint(site.getSiteId()); + apiResponse.put("point", targetSitePoint); + + apiResponse.success(); + + } catch (Exception e) { + log.info(e.toString()); + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + @ResponseBody + @PostMapping(value="/betInfo") + public ApiResponse betinfo(HttpServletRequest request, @RequestBody BetParam param) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + final String LOG_PREFIX = "#-BET-DETAIL::"+param.getBetId()+":::"; + JSONObject saveObj = null; + JSONArray saveObjs = null; + boolean isSaveEvoDetail = false; + + try { + // apiKey 체크 + Site site = siteService.getSiteInfo(request); + if(site ==null) { + throw new ApiException("1000", "accessDinied"); + } + + // 결과보내기 + apiResponse.put("betId", param.getBetId()); + String dType = "detail_0"; + + HashMap betInfo = transService.getBetInfoByBetId(param); + log.info(LOG_PREFIX+ "betInfo {}", betInfo); + + if(betInfo == null) betInfo = transService.getSiteBetByRefIdFromOld(param); + log.info(LOG_PREFIX+ "betInfo_OLD {}", betInfo); + + if(betInfo != null) { + param.setBetId(betInfo.get("refId").toString()); + + String category = betInfo.get("vendorCetegory").toString(); + log.info(LOG_PREFIX+ "Game category : " + category); + + if("pragmatic".equals(betInfo.get("vendorCode").toString())) { + dType = "detail_2"; + apiResponse.put("dType", dType); + + String detailURL = pragmaticService.getDetails(LOG_PREFIX, betInfo); + if(detailURL != null && !detailURL.equals("")) { + HashMap url = new HashMap(); + url.put("url", detailURL); + apiResponse.put("detail", url); + } else { + apiResponse.put("detail", "betId is not exist"); + } + + } else if("svendor".equals(betInfo.get("vendorCode").toString()) + || "pink".equals(betInfo.get("vendorCode").toString())) { + String jsonStr = siteService.getOrgDetailData(param); + log.info(LOG_PREFIX+ "jsonStr : " + jsonStr); + if(jsonStr != null && !"".equals(jsonStr) && !"{}".equals(jsonStr)) { + dType = "detail_6"; + apiResponse.put("dType", dType); + HashMap detailMap = new Gson().fromJson(jsonStr, HashMap.class); + apiResponse.put("detail", detailMap); + } else { + isSaveEvoDetail = true; + JSONObject dataObj = svendorService.getDetail(LOG_PREFIX, betInfo); + if(dataObj == null) { + apiResponse.put("detail", "betId is not exist"); + } else { + if(dataObj.has("gameDetail") && !dataObj.isNull("gameDetail")) { + String detailType = StringUtils.getType(dataObj.getString("gameDetail")); + if(detailType.equals("URL")) { + dType = "detail_2"; + apiResponse.put("dType", dType); + String detailUrl = dataObj.getString("gameDetail"); + HashMap url = new HashMap(); + url.put("url", detailUrl); + apiResponse.put("detail", url); + } else if(detailType.equals("JSON")) { + dType = "detail_6"; + apiResponse.put("dType", dType); + JSONObject detailObj = dataObj.getJSONObject("gameDetail"); + saveObj = detailObj; + HashMap detailMap = new Gson().fromJson(detailObj.toString(), HashMap.class); + apiResponse.put("detail", detailMap); + } else { + apiResponse.put("detail", "betId is not exist"); + } + } else { + apiResponse.put("detail", "betId is not exist"); + } + } + } + + } else if(Integer.parseInt(betInfo.get("vendorIdx").toString())==17 && "tower".equals(betInfo.get("vendorCode").toString())) { + dType = "detail_2"; + apiResponse.put("dType", dType); + String detail_url = + betInfo.get("vendorApiUrl").toString() + +"/v2/detail_url" + + "?site_code="+betInfo.get("vendorApiId").toString() + + "&user_id="+betInfo.get("siteHex").toString()+betInfo.get("memberId").toString() + + "&transaction_id="+betInfo.get("transactionId").toString() + + "&vendorCode=pp" + + "&gameCode="+betInfo.get("gameIdx").toString(); + log.info(LOG_PREFIX+" {}" ,detail_url); + OkHttpClient client = new OkHttpClient().newBuilder().build(); + okhttp3.Request requestok2 = new okhttp3.Request.Builder() + .url(detail_url) + .method("GET", null)// + .addHeader("User-agent", "Mozilla") + .addHeader("Authorization", betInfo.get("vendorApiKey").toString()) + .build(); + okhttp3.Response response = client.newCall(requestok2).execute(); + + if(response.isSuccessful()){ + okhttp3.ResponseBody body = response.body(); + String responseString = body.string(); + log.info(LOG_PREFIX+ "responseString::"+responseString); + log.info(LOG_PREFIX+ "url::"+StringUtils.extractLink(responseString)); + String detailUrl = StringUtils.extractLink(responseString); + String detailType = StringUtils.getType(detailUrl); + if(detailType.equals("URL")) { + dType = "detail_2"; + apiResponse.put("dType", dType); + HashMap url = new HashMap(); + url.put("url", detailUrl); + apiResponse.put("detail", url); + } else { + apiResponse.put("detail", "betId is not exist"); + } + /* + HashMap url = new HashMap(); + url.put("url", StringUtils.extractLink(responseString)); + apiResponse.put("detail", url); + */ + } else { + apiResponse.put("detail", "betId is not exist"); + } + + } else if(Integer.parseInt(betInfo.get("vendorIdx").toString())==83 && "splus".equals(betInfo.get("vendorCode").toString())) { + dType = "detail_1"; + apiResponse.put("dType", dType); + HashMap d = new HashMap(); + List splusDetail = siteService.getSplusDetailData(param); + for(HashMap ttype : splusDetail) { + log.info(LOG_PREFIX+ "{}, {}", ttype.get("tranType").toString(), ttype.get("data").toString()); + HashMap detailMap = new Gson().fromJson(ttype.get("data").toString(), HashMap.class); + d.put(ttype.get("tranType").toString(), detailMap); + } + + apiResponse.put("detail", d); + + } else if("nexus".equals(betInfo.get("vendorCode").toString()) || "ace2".equals(betInfo.get("vendorCode").toString())) { + String jsonStr = siteService.getOrgDetailData(param); + log.info(LOG_PREFIX+ "jsonStr : " + jsonStr); + if(jsonStr != null && !"".equals(jsonStr) && !"{}".equals(jsonStr)) { + dType = "detail_3"; + apiResponse.put("dType", dType); + + JSONObject detailObj = new JSONObject(jsonStr); + String gameType = detailObj.optString("gameType"); + JSONArray participants = detailObj.optJSONArray("participants"); + if (participants != null) { + for (int i = 0; i < participants.length(); i++) { + // result 객체 가져오기 (없으면 생성) + JSONObject participant = participants.optJSONObject(i); + JSONObject result = participant.optJSONObject("result"); + if (result == null) { + result = new JSONObject(); + participant.put("result", result); + } + + // link 값 세팅 + String raw = "betId="+param.getBetId()+"&gameType="+gameType; + String encrypted = AesUtil.encrypt(raw); + result.put("link", "https://fst.tx-direction.cc/detailsPage/"+encrypted); + } + } + HashMap detailMap = new Gson().fromJson(detailObj.toString(), HashMap.class); + apiResponse.put("detail", detailMap); + } else { + isSaveEvoDetail = true; + long siteIdx = (long) betInfo.get("siteIdx"); + long memberIdx = (long) betInfo.get("memberIdx"); + String trxId = betInfo.get("vendorTranKey").toString(); + String apiBaseUrl = betInfo.get("vendorApiUrl").toString(); + String apiAgentId = betInfo.get("vendorApiId").toString(); + String apiSecretKey = betInfo.get("vendorApiKey").toString(); + NexusApiInfo nexusApiInfo = NexusApiInfo.builder() + .siteIdx(siteIdx) + .memberIdx(memberIdx) + .apiBaseUrl(apiBaseUrl) + .agentId(apiAgentId) + .agentSecretKey(apiSecretKey) + .build(); + if("CASINO".equals(betInfo.get("vendorCetegory").toString())) { + dType = "detail_3"; + apiResponse.put("dType", dType); + JSONObject detailObj = nexusService.getDetail(LOG_PREFIX, nexusApiInfo, trxId); + if(detailObj == null) { + apiResponse.put("detail", "betId is not exist"); + } else { + int resultCode = detailObj.getInt("code"); + if(resultCode == 0) { + JSONArray transactions = detailObj.getJSONArray("transactions"); + if(transactions.length() > 0) { + List> detailMap = new Gson().fromJson(transactions.toString(), List.class); + saveObjs = transactions; + apiResponse.put("detail", detailMap); + } else { + apiResponse.put("detail", "betId is not exist"); + } + } else { + apiResponse.put("detail", "betId is not exist"); + } + } + } else { + dType = "detail_2"; + apiResponse.put("dType", dType); + JSONObject detailObj = nexusService.getDetailUrl(LOG_PREFIX, nexusApiInfo, trxId); + if(detailObj == null) { + apiResponse.put("detail", "betId is not exist"); + } else { + log.info(LOG_PREFIX+ "detailObj::"+detailObj.toString()); + int resultCode = detailObj.getInt("code"); + if(resultCode == 0) { + HashMap url = new HashMap<>(); + url.put("url", detailObj.getString("url")); + apiResponse.put("detail", url); + } else { + apiResponse.put("detail", "betId is not exist"); + } + } + } + } + } else if("prime".equals(betInfo.get("vendorCode").toString()) + || "dpcore".equals(betInfo.get("vendorCode").toString())) { + log.info(LOG_PREFIX+ "========== BetDetail::PRIME =========="); + dType = "detail_9"; + apiResponse.put("dType", dType); + + String jsonStr = siteService.getOrgDetailData(param); + if(jsonStr != null && !"".equals(jsonStr) && !"{}".equals(jsonStr)) { + + JSONObject detailObj = new JSONObject(jsonStr); + String gameType = detailObj.optString("gameType"); + JSONArray participants = detailObj.optJSONArray("participants"); + if (participants != null) { + for (int i = 0; i < participants.length(); i++) { + // result 객체 가져오기 (없으면 생성) + JSONObject participant = participants.optJSONObject(i); + JSONObject result = participant.optJSONObject("result"); + if (result == null) { + result = new JSONObject(); + participant.put("result", result); + } + + // link 값 세팅 + String raw = "betId="+param.getBetId()+"&gameType="+gameType; + String encrypted = AesUtil.encrypt(raw); + result.put("link", "https://fst.tx-direction.cc/detailsPage/"+encrypted); + } + } + HashMap detailMap = new Gson().fromJson(detailObj.toString(), HashMap.class); + apiResponse.put("detail", detailMap); + } else { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + String apiKey = "Bearer "+betInfo.get("vendorApiKey").toString(); + headers.set("Authorization", apiKey); + String detailUrl = betInfo.get("vendorApiUrl").toString() + "/api/getBettingDetails5?"; + String detailParam = "referer="+param.getBetId(); + detailUrl = detailUrl + detailParam; + + log.info(LOG_PREFIX+ "PRIME::Detail Url: " + detailUrl); + log.info(LOG_PREFIX+ "PRIME::Detail Headers: " + headers.toString()); + ResponseEntity response = null; + JSONObject resJson = null; + try { + response = webClient.get() + .uri(detailUrl) + .headers(h -> h.addAll(headers)) + .retrieve() + .toEntity(String.class) + .block(); + } catch(WebClientResponseException e) { + log.error(LOG_PREFIX+ "PRIME::Detail HttpClientErrorException : " + e.getMessage()); + log.error(LOG_PREFIX+ "PRIME::Detail status code : " + e.getStatusCode().value()); + log.error(LOG_PREFIX+ "PRIME::Detail response body : " + e.getResponseBodyAsString()); + resJson = new JSONObject(e.getResponseBodyAsString()); + log.error(LOG_PREFIX+ "PRIME::Detail error : " + resJson.getString("message")); + throw new ApiException("P209", resJson.getString("message")); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "PRIME::Detail ConnectTimeoutException::"+rae.getMessage()); + } + if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "PRIME::Detail SocketTimeoutException::"+rae.getMessage()); + } + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "PRIME::Detail InterruptedException::"+rae.getMessage()); + } + throw new ApiException("P210", rae.getMessage()); + } catch (Exception e) { + log.error(LOG_PREFIX+ "PRIME::Detail Exception : " + e.getMessage()); + throw new ApiException("P211", e.getMessage()); + } + + if(response != null && response.getStatusCode() == HttpStatus.OK) { + isSaveEvoDetail = true; + log.info(LOG_PREFIX+ "PRIME::Detail response : " + response.getBody()); + resJson = new JSONObject(response.getBody()); + + JSONObject dataObj = resJson; + String gameType = dataObj.optString("gameType"); + JSONArray participants = dataObj.optJSONArray("participants"); + if (participants != null) { + for (int i = 0; i < participants.length(); i++) { + // result 객체 가져오기 (없으면 생성) + JSONObject participant = participants.optJSONObject(i); + JSONObject result = participant.optJSONObject("result"); + if (result == null) { + result = new JSONObject(); + participant.put("result", result); + } + + // link 값 세팅 + String raw = "betId="+param.getBetId()+"&gameType="+gameType; + String encrypted = AesUtil.encrypt(raw); + result.put("link", "https://fst.tx-direction.cc/detailsPage/"+encrypted); + } + } + saveObj = dataObj; + HashMap detailMap = new Gson().fromJson(dataObj.toString(), HashMap.class); + apiResponse.put("detail", detailMap); + } else { + apiResponse.put("detail", "betId is not exist"); + } + } + } else if("grand".equals(betInfo.get("vendorCode").toString())) { + dType = "detail_2"; + apiResponse.put("dType", dType); + String detailUrl = + betInfo.get("vendorApiUrl").toString() + +"/transactions/detail" + + "?round_id="+betInfo.get("vendorTranKey").toString(); + log.info(LOG_PREFIX+"Request Url : {}" ,detailUrl); + OkHttpClient client = new OkHttpClient().newBuilder().build(); + okhttp3.Request requestok2 = new okhttp3.Request.Builder() + .url(detailUrl) + .method("GET", null)// + .addHeader("User-agent", "Mozilla") + .addHeader("Authorization", "Bearer "+betInfo.get("vendorApiKey").toString()) + .build(); + okhttp3.Response response = client.newCall(requestok2).execute(); + + if(response.isSuccessful()){ + okhttp3.ResponseBody body = response.body(); + String responseString = body.string(); + log.info(LOG_PREFIX+ "responseString : " , responseString); + JSONObject responseObj = new JSONObject(responseString); + JSONObject dataObj = responseObj.getJSONObject("data"); + if(dataObj != null) { + HashMap url = new HashMap(); + url.put("url", dataObj.getString("url")); + apiResponse.put("detail", url); + } else { + apiResponse.put("detail", "betId is not exist"); + } + } else { + apiResponse.put("detail", "betId is not exist"); + } + } else if("pracp".equals(betInfo.get("vendorCode").toString())) { + dType = "detail_2"; + apiResponse.put("dType", dType); + + HashMap apiInfo = new HashMap<>(); + apiInfo.put("apiAgentCode", betInfo.get("vendorApiId").toString()); + apiInfo.put("apiToken", betInfo.get("vendorApiKey").toString()); + apiInfo.put("apiBaseUrl", betInfo.get("vendorApiUrl").toString()); + apiInfo.put("uuid", betInfo.get("uuid").toString()); + apiInfo.put("round_id", betInfo.get("roundId").toString()); + + JSONObject dataObj = pracpService.getDetail(LOG_PREFIX, apiInfo); + log.info(LOG_PREFIX+ "dataObj : " + dataObj.toString()); + if(dataObj != null) { + HashMap url = new HashMap(); + url.put("url", dataObj.getString("url")); + apiResponse.put("detail", url); + } else { + apiResponse.put("detail", "betId is not exist"); + } + } else if("tplus".equals(betInfo.get("vendorCode").toString())) { + dType = "detail_2"; + apiResponse.put("dType", dType); + + String apiBaseUrl = betInfo.get("vendorApiUrl").toString(); + String apiAuthKey = betInfo.get("vendorApiKey").toString(); + String pairTransactionKey = betInfo.get("refId").toString(); + TplusApiInfo apiInfo = TplusApiInfo.builder() + .apiBaseUrl(apiBaseUrl) + .apiAuthKey(apiAuthKey) + .pairTransactionKey(pairTransactionKey).build(); + + log.info(LOG_PREFIX+ "tplus::apiInfo: " + apiInfo); + + String detailURL = tplusService.getDetails(LOG_PREFIX, apiInfo); + if(detailURL != null && !detailURL.equals("")) { + HashMap url = new HashMap(); + url.put("url", detailURL); + apiResponse.put("detail", url); + } else { + apiResponse.put("detail", "betId is not exist"); + } + } else if("onix".equals(betInfo.get("vendorCode").toString())) { + log.info(LOG_PREFIX+ "========== BetDetail::ONIX =========="); + dType = "detail_8"; + apiResponse.put("dType", dType); + + String jsonStr = siteService.getOrgDetailData(param); + if(jsonStr != null && !"".equals(jsonStr) && !"{}".equals(jsonStr)) { + JSONObject detailObj = new JSONObject(jsonStr); + String gameType = detailObj.optString("gameType"); + JSONArray participants = detailObj.optJSONArray("participants"); + if (participants != null) { + for (int i = 0; i < participants.length(); i++) { + // result 객체 가져오기 (없으면 생성) + JSONObject participant = participants.optJSONObject(i); + JSONObject result = participant.optJSONObject("result"); + if (result == null) { + result = new JSONObject(); + participant.put("result", result); + } + + // link 값 세팅 + String raw = "betId="+param.getBetId()+"&gameType="+gameType; + String encrypted = AesUtil.encrypt(raw); + result.put("link", "https://fst.tx-direction.cc/detailsPage/"+encrypted); + } + } + HashMap detailMap = new Gson().fromJson(detailObj.toString(), HashMap.class); + apiResponse.put("detail", detailMap); + } else { + String apiBaseUrl = betInfo.get("vendorApiUrl").toString(); + String fullDateTime = betInfo.get("betTime").toString(); + String dateOnly = fullDateTime.substring(0, 10); + + // Step 1: Get round info from /csapi/getBetting + String bettingUrl = apiBaseUrl + "/csapi/getBetting"; + JSONObject bettingBody = new JSONObject(); + bettingBody.put("userid", betInfo.get("siteIdxHex").toString()+betInfo.get("memberId").toString()); + bettingBody.put("sdate", dateOnly+" 00:00:00.000"); + bettingBody.put("edate", dateOnly+" 23:59:59.999"); + bettingBody.put("pagesize", "1"); + bettingBody.put("gameid", "0"); + bettingBody.put("roundcode", betInfo.get("uuid").toString()); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.set("Authorization", "Bearer " + betInfo.get("vendorApiKey").toString()); + + log.info(LOG_PREFIX+ "ONIX::Step1 getBetting Url: " + bettingUrl); + log.info(LOG_PREFIX+ "ONIX::Step1 getBetting Body: " + bettingBody.toString()); + + try { + ResponseEntity bettingRes = webClient.post() + .uri(bettingUrl) + .headers(h -> h.addAll(headers)) + .bodyValue(bettingBody.toString()) + .retrieve() + .toEntity(String.class) + .block(); + if(bettingRes != null && bettingRes.getBody() != null) { + JSONObject bettingObj = new JSONObject(bettingRes.getBody()); + log.info(LOG_PREFIX+ "ONIX::Step1 getBetting Response: " + bettingObj.toString()); + + int bettingResult = bettingObj.getInt("result"); + if(bettingResult == 1 && bettingObj.has("data")) { + JSONArray dataArray = bettingObj.getJSONArray("data"); + if(dataArray.length() > 0) { + isSaveEvoDetail = true; + JSONObject dataObj = dataArray.getJSONObject(0); + JSONObject detailObj = dataObj.getJSONArray("details").getJSONObject(0); + String gameType = detailObj.optString("gameType"); + JSONArray participants = detailObj.optJSONArray("participants"); + if (participants != null) { + for (int i = 0; i < participants.length(); i++) { + // result 객체 가져오기 (없으면 생성) + JSONObject participant = participants.optJSONObject(i); + JSONObject result = participant.optJSONObject("result"); + if (result == null) { + result = new JSONObject(); + participant.put("result", result); + } + + // link 값 세팅 + String raw = "betId="+param.getBetId()+"&gameType="+gameType; + String encrypted = AesUtil.encrypt(raw); + result.put("link", "https://fst.tx-direction.cc/detailsPage/"+encrypted); + } + } + HashMap detailMap = new Gson().fromJson(detailObj.toString(), HashMap.class); + apiResponse.put("detail", detailMap); + saveObj = detailObj; + + } else { + apiResponse.put("detail", "betId is not exist"); + } + } else { + apiResponse.put("detail", "betId is not exist"); + String errorMsg = bettingObj.has("msg") ? bettingObj.getString("msg") : "Unknown error"; + log.error(LOG_PREFIX+ "ONIX::Betting Error: " + errorMsg); + } + } else { + apiResponse.put("detail", "betId is not exist"); + log.error(LOG_PREFIX+ "ONIX::Betting Response is null"); + } + } catch(WebClientResponseException e) { + log.error(LOG_PREFIX+ "ONIX::Betting HttpClientErrorException : " + e.getMessage()); + log.error(LOG_PREFIX+ "ONIX::Betting status code : " + e.getStatusCode().value()); + log.error(LOG_PREFIX+ "ONIX::Betting response body : " + e.getResponseBodyAsString()); + JSONObject errorJson = new JSONObject(e.getResponseBodyAsString()); + String errorMsg = errorJson.has("msg") ? errorJson.getString("msg") : "Betting API error"; + log.error(LOG_PREFIX+ "ONIX::Betting error : " + errorMsg); + throw new ApiException("P209", errorMsg); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ONIX::Betting ConnectTimeoutException::" + rae.getMessage()); + } + if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "ONIX::Betting ReadTimeoutException::" + rae.getMessage()); + } + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "ONIX::Betting InterruptedException::" + rae.getMessage()); + } + throw new ApiException("P210", rae.getMessage()); + } catch(Exception e) { + log.error(LOG_PREFIX+ "ONIX::Betting Exception : " + e.getMessage()); + throw new ApiException("P211", e.getMessage()); + } + } + } else if("bet_radar".equals(betInfo.get("vendorCode").toString())) { + log.info(LOG_PREFIX+ "========== BetDetail::BET_RADAR =========="); + // TODO: 베팅상세 내려주기 + /* + * param.getBetId() 기준으로 bet_radar_log 테이블 조회시 베팅과 결과 두가지가 나옴. + * 결과가 없는경우 베팅만 한가지 있을 수 있음. + * param.getBetId() 기준 bet_radar_log에서 jsonstr(베팅상세 json 원본)을 가져와서 + * 하나의 json으로 합쳐서 내려주기 구현. + */ + // bet_radar_log 테이블에서 조회 + + String radarLogJson = siteService.getMergedBetRadarLog(param.getBetId()); + if(radarLogJson != null && !radarLogJson.isEmpty()) { + log.info(LOG_PREFIX+ "bet_radar_log found, returning merged json"); + dType = "detail_radar"; + apiResponse.put("dType", dType); + HashMap detailMap = new Gson().fromJson(radarLogJson, HashMap.class); + String detailUrl = "https://sportsbook.spokok.com/bets/detail/"+param.getBetId(); + detailMap.put("dLink", detailUrl); + apiResponse.put("detail", detailMap); + apiResponse.success(); + return apiResponse; + } + + } else if("thenut".equals(betInfo.get("vendorCode").toString())) { + log.info(LOG_PREFIX+ "========== BetDetail::THENUT =========="); + String jsonStr = siteService.getOrgDetailData(param); + log.info(LOG_PREFIX+ "jsonStr : " + jsonStr); + if(jsonStr != null && !"".equals(jsonStr) && !"{}".equals(jsonStr)) { + String detailType = StringUtils.getType(jsonStr); + if(detailType.equals("URL")) { + dType = "detail_2"; + apiResponse.put("dType", dType); + String detailUrl = jsonStr; + HashMap url = new HashMap(); + url.put("url", detailUrl); + apiResponse.put("detail", url); + } else if(detailType.equals("JSON")) { + dType = "detail_3"; + apiResponse.put("dType", dType); + + JSONObject detailObj = new JSONObject(jsonStr); + String gameType = detailObj.optString("gameType"); + JSONArray participants = detailObj.optJSONArray("participants"); + if (participants != null) { + for (int i = 0; i < participants.length(); i++) { + // result 객체 가져오기 (없으면 생성) + JSONObject participant = participants.optJSONObject(i); + JSONObject result = participant.optJSONObject("result"); + if (result == null) { + result = new JSONObject(); + participant.put("result", result); + } + + // link 값 세팅 + String raw = "betId="+param.getBetId()+"&gameType="+gameType; + String encrypted = AesUtil.encrypt(raw); + result.put("link", "https://fst.tx-direction.cc/detailsPage/"+encrypted); + } + } + HashMap detailMap = new Gson().fromJson(detailObj.toString(), HashMap.class); + apiResponse.put("detail", detailMap); + } else { + apiResponse.put("dType", dType); + apiResponse.put("detail", "betId is not exist"); + } + } else { + String apiBaseUrl = betInfo.get("vendorApiUrl").toString(); + String apiKey = betInfo.get("vendorApiKey").toString(); + HashMap apiInfo = new HashMap<>(); + apiInfo.put("apiBaseUrl", apiBaseUrl); + apiInfo.put("apiKey", apiKey); + apiInfo.put("betId", param.getBetId()); + + if("CASINO".equals(betInfo.get("vendorCetegory").toString())) { + isSaveEvoDetail = true; + dType = "detail_3"; + apiResponse.put("dType", dType); + JSONObject detailObj = thenutService.getBetDetail(LOG_PREFIX, apiInfo); + if(detailObj == null) { + apiResponse.put("detail", "betId is not exist"); + } else { + String gameType = detailObj.optString("gameType"); + JSONArray participants = detailObj.optJSONArray("participants"); + if (participants != null) { + for (int i = 0; i < participants.length(); i++) { + // result 객체 가져오기 (없으면 생성) + JSONObject participant = participants.optJSONObject(i); + JSONObject result = participant.optJSONObject("result"); + if (result == null) { + result = new JSONObject(); + participant.put("result", result); + } + + // link 값 세팅 + String raw = "betId="+param.getBetId()+"&gameType="+gameType; + String encrypted = AesUtil.encrypt(raw); + result.put("link", "https://fst.tx-direction.cc/detailsPage/"+encrypted); + } + } + HashMap detailMap = new Gson().fromJson(detailObj.toString(), HashMap.class); + apiResponse.put("detail", detailMap); + saveObj = detailObj; + } + } else { + dType = "detail_2"; + apiResponse.put("dType", dType); + String detailUrl = thenutService.getBetDetailUrl(LOG_PREFIX, apiInfo); + if(detailUrl == null) { + apiResponse.put("detail", "betId is not exist"); + } else { + log.info(LOG_PREFIX+ "detailUrl::"+detailUrl); + HashMap url = new HashMap<>(); + url.put("url", detailUrl); + apiResponse.put("detail", url); + } + } + } + } else if("panda".equals(betInfo.get("vendorCode").toString())) { + dType = "detail_2"; + apiResponse.put("dType", dType); + String apiBaseUrl = betInfo.get("vendorApiUrl").toString(); + String apiKey = betInfo.get("vendorApiKey").toString(); + String tranId = betInfo.get("uuid").toString(); + + HashMap apiInfo = new HashMap<>(); + apiInfo.put("apiBaseUrl", apiBaseUrl); + apiInfo.put("apiKey", apiKey); + apiInfo.put("tranId", tranId); + String detailUrl = pandaService.getDetail(LOG_PREFIX, apiInfo); + if(detailUrl == null) { + apiResponse.put("detail", "betId is not exist"); + } else { + log.info(LOG_PREFIX+ "detailUrl::"+detailUrl); + HashMap url = new HashMap<>(); + url.put("url", detailUrl); + apiResponse.put("detail", url); + } + } else { + apiResponse.put("dType", dType); + apiResponse.put("detail", "betId is not exist"); + } + } else { + apiResponse.put("dType", dType); + apiResponse.put("detail", "betId is not exist"); + } + + if(saveObj != null || saveObjs != null) { + // check detail data + if(isSaveEvoDetail) { + asyncSiteService.insertEvoDetailProc(LOG_PREFIX, param.getBetId(), saveObj, saveObjs); + } + } else { + log.info(LOG_PREFIX+ "saved detail is null"); + } + + apiResponse.success(); + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]::"+e.toString()); + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping(value="/betList") + public ApiResponse betList(HttpServletRequest request, @RequestBody BetParam param) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + try { + // apiKey 체크 + Site site = siteService.getSiteInfo(request); + if(site ==null) { + throw new ApiException("1000", "accessDinied"); + } + param.setSiteIdx(site.getSiteIdx()); + // 결과보내기 + List betList = new ArrayList<>(); + String nextStartDate = ""; + if(betList.size()>0) { + nextStartDate = betList.get(betList.size()-1).get("regDate").toString(); + } else { + + } + + apiResponse.put("list", betList); + apiResponse.put("nextStartDate", nextStartDate); + + apiResponse.success(); + + } catch (Exception e) { + log.info(e.toString()); + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + public ApiResponse parseUseUpdate(HttpServletRequest request, @RequestBody PlayParam param) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + try { + //apiKey 체크 + Site site = siteService.getSiteInfo(request); + if(site==null) { + throw new ApiException("1000", "accessDinied"); + } + + if(param.getParseUseYn()!=null && !"".equals(param.getParseUseYn())) { + HashMap parseParam = new HashMap(); + parseParam.put("siteIdx", site.getSiteIdx()); + parseParam.put("siteId", site.getSiteId()); + parseParam.put("useYn", param.getParseUseYn()); + siteService.insertParseUse(parseParam); + } + HashMap ParseUseYn = siteService.getParseUseYn(site.getSiteIdx()); + if(ParseUseYn==null || "N".equals(ParseUseYn.get("useYn").toString())) { + apiResponse.put("currentUseYn","N"); + }else { + apiResponse.put("currentUseYn","Y"); + } + + + + apiResponse.success(); + } catch (Exception e) { + log.info(e.toString()); + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + /** + * 파싱 API 사용하기 위한 토큰 발급 + * @param request + * @return + * @throws Exception + */ + @ResponseBody + @PostMapping(value="/getToken") + public synchronized ApiResponse getToken(HttpServletRequest request) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + // apiKey 체크 + String Authorization = request.getHeader("Authorization").toString(); + String LOG_PREFIX = "#-getToken::"+Authorization+"::::"; + Site site = siteService.getSiteInfo(request); + if(site == null) { + log.error(LOG_PREFIX+ "T1001:Access denied Key"); + apiResponse.setResultCode("T1001"); + apiResponse.setResultMessage("Access denied Key"); + return apiResponse; + } + LOG_PREFIX = "#-getToken::"+Authorization+"::"+site.getSiteId()+"::::"; +// +// if(!( +// site.getSiteIp() == null || +// "".equals(site.getSiteIp()) || +// "3.3.3.3".equals(site.getSiteIp()) || +// site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0 +// )) { +// log.error(LOG_PREFIX+ "site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); +// log.error(LOG_PREFIX+ "T1002:Access denied IP"); +// apiResponse.setResultCode("T1002"); +// apiResponse.setResultMessage("Access denied IP"); +// return apiResponse; +// } +// + // 토큰생성 + JwtClame jwtinfo = new JwtClame(); + jwtinfo.setSiteId(site.getSiteId()); + jwtinfo.setMemId(""); + String tok = jwtManager.generateToken(jwtinfo); + + // 결과보내기 + apiResponse.put("token", tok); + apiResponse.success(); + + return apiResponse; + } + + /** + * 파싱 API - 보유중인 알 + * @param request + * @param token + * @return + * @throws Exception + */ + @ResponseBody + @PostMapping(value="/p1/agentBalance") + public ApiResponse agentBalance(HttpServletRequest request, @RequestHeader String token) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + try { + // apiKey 체크 + Site site = siteService.getSiteInfo(request); + if(site == null) { + log.error("#-p1::agentBalance::"+ "T1001:Access denied Key"); + apiResponse.setResultCode("T1001"); + apiResponse.setResultMessage("Access denied Key"); + return apiResponse; + } + + //토큰체크 + if(token == null) { + log.error("#-p1::agentBalance::"+ "T1003:Access token check"); + apiResponse.setResultCode("T1003"); + apiResponse.setResultMessage("Access token check"); + return apiResponse; + } + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfo(token); + final String LOG_PREFIX = "#-p1::agentBalance::"+tokenInfo.getSid()+"::::"; + + + long targetSiteCredit = siteService.getSiteCredit(tokenInfo.getSid()); + log.info(LOG_PREFIX + "targetSiteCredit: " + targetSiteCredit); + apiResponse.put("credit", targetSiteCredit); + + long targetSitePoint = siteService.getSitePoint(tokenInfo.getSid()); + log.info(LOG_PREFIX + "targetSitePoint: " + targetSitePoint); + apiResponse.put("point", targetSitePoint); + + apiResponse.success(); + + } catch (Exception e) { + log.error("#-p1::agentBalance::"+e.toString()); + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @ResponseBody + @PostMapping(value="/p1/balance") + public ApiResponse apiBalance(HttpServletRequest request, @RequestHeader String token, @RequestBody CashParam param) { + ApiResponse apiResponse = new ApiResponse(); + final String LOG_PREFIX = "#-apiBalance::"+param.getMemberId()+"::::"; + + try { + // apiKey 체크 + Site site = siteService.getSiteInfo(request); + if(site == null) { + log.error(LOG_PREFIX+ "T1001:Access denied Key"); + apiResponse.setResultCode("T1001"); + apiResponse.setResultMessage("Access denied Key"); + return apiResponse; + } + + //토큰체크 + if(token == null) { + log.error(LOG_PREFIX+ "T1003:Access token check"); + apiResponse.setResultCode("T1003"); + apiResponse.setResultMessage("Access token check"); + return apiResponse; + } + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfo(token); + + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(param); + JSONObject reqObj = new JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + final String IS_TRANSFER = site.getIsTransfer(); + if(IS_TRANSFER.equals("N")) { + log.error(LOG_PREFIX+ "T1008:NOT_TRANSFER_SITE"); + apiResponse.setResultCode("T1008"); + apiResponse.setResultMessage("NOT_TRANSFER_SITE"); + return apiResponse; + } + + //회원정보 + AuthParam authParam = new AuthParam(); + authParam.setUserId(param.getMemberId()); + CommonParam commonParam = new CommonParam(); + commonParam.setSiteIdx(site.getSiteIdx()); + commonParam.setAuthParam(authParam); + log.info(LOG_PREFIX+ "CommonParam::"+commonParam.toString()); + Member member = siteService.getMember(commonParam); + if(member == null) { + // Fail + log.error(LOG_PREFIX+ "T1004:NOT_FOUND_USER"); + apiResponse.setResultCode("T1004"); + apiResponse.setResultMessage("NOT_FOUND_USER"); + return apiResponse; + } + log.info(LOG_PREFIX+ "Member::"+member.toString()); + + apiResponse.put("balance", member.getUserBalance()); + + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.toString()); + e.printStackTrace(); + apiResponse.fail(); + } + + apiResponse.success(); + + return apiResponse; + } + + + @ResponseBody + @PostMapping(value="/p1/deposit") + public ApiResponse apiDeposit(HttpServletRequest request, @RequestHeader String token, @RequestBody CashParam param) { + ApiResponse apiResponse = new ApiResponse(); + final String LOG_PREFIX = "#-apiDeposit::"+param.getMemberId()+"::::"; + + try { + // apiKey 체크 + Site site = siteService.getSiteInfo(request); + if(site == null) { + log.error(LOG_PREFIX+ "T1001:Access denied Key"); + apiResponse.setResultCode("T1001"); + apiResponse.setResultMessage("Access denied Key"); + return apiResponse; + } + + //토큰체크 + if(token == null) { + log.error(LOG_PREFIX+ "T1003:Access token check"); + apiResponse.setResultCode("T1003"); + apiResponse.setResultMessage("Access token check"); + return apiResponse; + } + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfo(token); + + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(param); + JSONObject reqObj = new JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + final String IS_TRANSFER = site.getIsTransfer(); + if(IS_TRANSFER.equals("N")) { + log.error(LOG_PREFIX+ "T1008:NOT_TRANSFER_SITE"); + apiResponse.setResultCode("T1008"); + apiResponse.setResultMessage("NOT_TRANSFER_SITE"); + return apiResponse; + } + + //회원정보 + param.setSiteIdx(site.getSiteIdx()); + Member member = siteService.getMember2(param); + if(member == null) { + // Fail + log.error(LOG_PREFIX+ "T1004:NOT_FOUND_USER"); + apiResponse.setResultCode("T1004"); + apiResponse.setResultMessage("NOT_FOUND_USER"); + return apiResponse; + } + log.info(LOG_PREFIX+ "Member::"+member.toString()); + + long amount = Long.parseLong(param.getAmount()); + long userBalance = member.getUserBalance(); + long siteCredit = site.getCredit(); + if(siteCredit < amount) { + log.error(LOG_PREFIX+ "T1006:사이트 크레딧 부족"); + apiResponse.setResultCode("T1006"); + apiResponse.setResultMessage("사이트 크레딧 부족"); + return apiResponse; + } + + // Insert credit_info : MAI, IN + Credit credit = new Credit(); + credit.setSiteIdx(site.getSiteIdx()); + credit.setSiteId(site.getSiteId()); + credit.setTargetSiteIdx(member.getMemberIdx()); + credit.setTargetSiteId(member.getMemberId()); + credit.setCreditType("MAI"); + credit.setCreditRate(null); + credit.setInOut("IN"); + credit.setTranId("회원 충전"); + credit.setCreditAmt(Long.parseLong(param.getAmount())); + credit.setUserAmt(Long.parseLong(param.getAmount())); + credit.setCreditStatus(1); + credit.setWaitTime(-10); // 재요청 대기시간 10초 + int cnt = creditService.checkRequestTime(credit); + if(cnt > 0) { + // Fail + log.error(LOG_PREFIX+ "T1005:재요청 대기시간 10초"); + apiResponse.setResultCode("T1005"); + apiResponse.setResultMessage("재요청 대기시간 10초"); + return apiResponse; + } + int result = creditService.insertCreditByCash(credit); + if(result < 0) { + // Fail + log.error(LOG_PREFIX+ "T1009:DEPOSIT_FAIL"); + apiResponse.setResultCode("T1009"); + apiResponse.setResultMessage("DEPOSIT_FAIL"); + return apiResponse; + } else { + // TODO: 성공 시 잔액 담아서 내려주기 + apiResponse.put("bfBalance", userBalance); + apiResponse.put("balance", userBalance+amount); + } + + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.toString()); + e.printStackTrace(); + apiResponse.fail(); + } + + apiResponse.success(); + + return apiResponse; + } + + + @ResponseBody + @PostMapping(value="/p1/withdraw") + public ApiResponse apiWithdraw(HttpServletRequest request, @RequestHeader String token, @RequestBody CashParam param) { + ApiResponse apiResponse = new ApiResponse(); + final String LOG_PREFIX = "#-apiWithdraw::"+param.getMemberId()+"::::"; + + try { + // apiKey 체크 + Site site = siteService.getSiteInfo(request); + if(site == null) { + log.error(LOG_PREFIX+ "T1001:Access denied Key"); + apiResponse.setResultCode("T1001"); + apiResponse.setResultMessage("Access denied Key"); + return apiResponse; + } + + //토큰체크 + if(token == null) { + log.error(LOG_PREFIX+ "T1003:Access token check"); + apiResponse.setResultCode("T1003"); + apiResponse.setResultMessage("Access token check"); + return apiResponse; + } + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfo(token); + + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(param); + JSONObject reqObj = new JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + final String IS_TRANSFER = site.getIsTransfer(); + if(IS_TRANSFER.equals("N")) { + log.error(LOG_PREFIX+ "T1008:NOT_TRANSFER_SITE"); + apiResponse.setResultCode("T1008"); + apiResponse.setResultMessage("NOT_TRANSFER_SITE"); + return apiResponse; + } + + //회원정보 + param.setSiteIdx(site.getSiteIdx()); + Member member = siteService.getMember2(param); + if(member == null) { + // Fail + log.error(LOG_PREFIX+ "T1004:NOT_FOUND_USER"); + apiResponse.setResultCode("T1004"); + apiResponse.setResultMessage("NOT_FOUND_USER"); + return apiResponse; + } + log.info(LOG_PREFIX+ "Member::"+member.toString()); + + long amount = Long.parseLong(param.getAmount()); + long userBalance = member.getUserBalance(); + + if(param.getWithAll() != null && param.getWithAll().equals("Y")) { + amount = userBalance; + param.setAmount(Long.toString(amount)); + } + + if(userBalance < amount) { + log.error(LOG_PREFIX+ "T1007:유저 잔액 부족"); + apiResponse.setResultCode("T1007"); + apiResponse.setResultMessage("유저 잔액 부족"); + return apiResponse; + } + + // Insert credit_info : MAO, OUT + Credit credit = new Credit(); + credit.setSiteIdx(site.getSiteIdx()); + credit.setSiteId(site.getSiteId()); + credit.setTargetSiteIdx(member.getMemberIdx()); + credit.setTargetSiteId(member.getMemberId()); + credit.setCreditType("MAO"); + credit.setCreditRate(null); + credit.setInOut("OUT"); + credit.setTranId("회원 환전"); + credit.setCreditAmt(Long.parseLong(param.getAmount())); + credit.setUserAmt(Long.parseLong(param.getAmount())); + credit.setCreditStatus(1); + credit.setWaitTime(-10); // 재요청 대기시간 10초 + int cnt = creditService.checkRequestTime(credit); + if(cnt > 0) { + // Fail + log.error(LOG_PREFIX+ "T1005:재요청 대기시간 10초"); + apiResponse.setResultCode("T1005"); + apiResponse.setResultMessage("재요청 대기시간 10초"); + return apiResponse; + } + int result = creditService.insertCreditByCash(credit); + if(result < 0) { + // Fail + log.error(LOG_PREFIX+ "T1009:WITHDRAW_FAIL"); + apiResponse.setResultCode("T1009"); + apiResponse.setResultMessage("WITHDRAW_FAIL"); + return apiResponse; + } else { + // TODO: 성공 시 잔액 담아서 내려주기 + apiResponse.put("bfBalance", userBalance); + apiResponse.put("balance", userBalance-amount); + } + + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.toString()); + e.printStackTrace(); + apiResponse.fail(); + } + + apiResponse.success(); + + return apiResponse; + } + + + /** + * 파싱 API - 충환전내역 가져오기 + * @param request + * @param token + * @param param + * @return + * @throws Exception + */ + @ResponseBody + @PostMapping(value="/p1/cashInOut") + public ApiResponse apiCashInOut(HttpServletRequest request, @RequestHeader String token, @RequestBody CashParam param) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + JwtManager.TokenInfo tokenInfo = null; + + try { + //토큰체크 + if(token == null) { + log.error("#-p1::apiCashInOut::TOKEN_ERROR::"+request.getHeader("Authorization").toString()+"::"+ "access denied token"); + log.error("#-p1::apiCashInOut::"+ "T1003:Access token check"); + apiResponse.setResultCode("T1003"); + apiResponse.setResultMessage("Access token check"); + return apiResponse; + } + tokenInfo = jwtManager.getTokenInfo(token); + + } catch (Exception e) { + log.error("#-p1::apiCashInOut::TOKEN_ERROR::"+request.getHeader("Authorization").toString()+"::"+ "[Exception]"+e.toString()); + e.printStackTrace(); + apiResponse.fail(); + } + + final String LOG_PREFIX = "#-p1::apiCashInOut::"+tokenInfo.getSid()+"::::"; + + try { + // apiKey 체크 + Site site = siteService.getSiteInfo(request); + if(site == null) { + log.error(LOG_PREFIX+ "T1001:Access denied Key"); + apiResponse.setResultCode("T1001"); + apiResponse.setResultMessage("Access denied Key"); + return apiResponse; + } + + param.setSiteIdx(site.getSiteIdx()); + if(param.getCount() == null || param.getCount().equals("")) { + param.setCount("100"); + } + + int count = Integer.parseInt(param.getCount()); + if(count > 2000) { + param.setCount("2000"); + } + + if(param.getStartDate() == null || param.getStartDate().equals("")) { + log.error(LOG_PREFIX+ "T1011:StartDate is not null"); + apiResponse.setResultCode("T1011"); + apiResponse.setResultMessage("StartDate is not null"); + return apiResponse; + } + param.setStartDate(param.getStartDate().replace("T", " ")); + + if(param.getEndDate() != null && !"".equals(param.getEndDate())) { + param.setEndDate(param.getEndDate().replace("T", " ")); + } + + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(param); + JSONObject reqObj = new JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + final String IS_TRANSFER = site.getIsTransfer(); + if(IS_TRANSFER.equals("N")) { + log.error(LOG_PREFIX+ "T1008:NOT_TRANSFER_SITE"); + apiResponse.setResultCode("T1008"); + apiResponse.setResultMessage("NOT_TRANSFER_SITE"); + return apiResponse; + } + + // TODO: 입출금 내역 API 구현.. + int totalCnt = creditService.getCashInOutListCnt(param); + List list = creditService.getCashInOutList(param); + String nextStartDate = ""; + if(list.size() > 0) { + nextStartDate = list.get(list.size()-1).get("regDate").toString(); + } else { + nextStartDate = param.getStartDate(); + } + + apiResponse.put("total", totalCnt); + apiResponse.put("list", list); + apiResponse.put("nextStartDate", nextStartDate); + + apiResponse.success(); + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + + /** + * 파싱 API - 사용가능한 벤더사 리스트 + * @param request + * @param token + * @return + * @throws Exception + */ + @ResponseBody + @PostMapping(value="/p1/vendorList") + public ApiResponse betVendorList(HttpServletRequest request, @RequestHeader String token) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + try { + // apiKey 체크 + Site site = siteService.getSiteInfo(request); + if(site == null) { + log.error("#-p1::vendorList::"+ "T1001:Access denied Key"); + apiResponse.setResultCode("T1001"); + apiResponse.setResultMessage("Access denied Key"); + return apiResponse; + } + + //토큰체크 + if(token == null) { + log.error("#-p1::vendorList::"+ "T1003:Access token check"); + apiResponse.setResultCode("T1003"); + apiResponse.setResultMessage("Access token check"); + return apiResponse; + } + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfo(token); + final String LOG_PREFIX = "#-p1::betVendorList::"+tokenInfo.getSid()+"::::"; + + // 결과보내기 + List vendorList = siteService.getApiBetVendorList(site.getSiteIdx()); + log.info(LOG_PREFIX + "vendorList size: " + vendorList.size()); + apiResponse.put("list", vendorList); + apiResponse.success(); + + } catch (Exception e) { + log.error("#-p1::betVendorList::"+e.toString()); + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + /** + * 파싱 API - 배팅내역 가져오기 + * @param request + * @param token + * @param param + * @return + * @throws Exception + */ + @ResponseBody + @PostMapping(value="/p1/transaction") + public ApiResponse betTransactionList(HttpServletRequest request, @RequestHeader String token, @RequestBody BetParam param) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + JwtManager.TokenInfo tokenInfo = null; + + try { + //토큰체크 + if(token == null) { + log.error("#-p1::betTransactionList::TOKEN_ERROR::"+request.getHeader("Authorization").toString()+"::"+ "access denied token"); + log.error("#-p1::betTransactionList::"+ "T1003:Access token check"); + apiResponse.setResultCode("T1003"); + apiResponse.setResultMessage("Access token check"); + return apiResponse; + } + tokenInfo = jwtManager.getTokenInfo(token); + + } catch (Exception e) { + log.error("#-p1::betTransactionList::TOKEN_ERROR::"+request.getHeader("Authorization").toString()+"::"+ "[Exception]"+e.toString()); + e.printStackTrace(); + apiResponse.fail(); + } + + final String LOG_PREFIX = "#-p1::betTransactionList::"+tokenInfo.getSid()+"::::"; + + try { + // apiKey 체크 + Site site = siteService.getSiteInfo(request); + if(site == null) { + log.error(LOG_PREFIX+ "T1001:Access denied Key"); + apiResponse.setResultCode("T1001"); + apiResponse.setResultMessage("Access denied Key"); + return apiResponse; + } + + param.setSiteIdx(site.getSiteIdx()); + if(param.getCount() == null || param.getCount().equals("")) { + param.setCount("100"); + } + + int count = Integer.parseInt(param.getCount()); + if(count > 2000) { + param.setCount("3000"); + } + + if(param.getIsDetail() == null || param.getIsDetail().equals("")) param.setIsDetail("N"); + log.info(LOG_PREFIX + "BetParam: " + param); + + // 결과보내기 + int betCnt = siteService.getApiBetTransactionCnt(param); + log.info(LOG_PREFIX + "total: " + betCnt); + List betList = siteService.getApiBetTransactionList(param); + if(param.getIsDetail().equals("Y")) { + for(HashMap item : betList) { + if(item.get("detail") != null && !"".equals(item.get("detail").toString())) { + JSONObject detailObj = new JSONObject(item.get("detail").toString()); + HashMap detailMap = new Gson().fromJson(detailObj.toString(), HashMap.class); + item.put("detail", detailMap); + } + } + } + log.info(LOG_PREFIX + "list size: " + betList.size()); + String nextStartDate = ""; + if(betList.size() > 0) { + nextStartDate = betList.get(betList.size()-1).get("regDate").toString(); + } else { + nextStartDate = param.getStartDate(); + } + + apiResponse.put("total", betCnt); + apiResponse.put("list", betList); + apiResponse.put("nextStartDate", nextStartDate); + + apiResponse.success(); + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + /** + * 파싱 API - 배팅내역 가져오기 + * @param request + * @param token + * @param param + * @return + * @throws Exception + */ + @ResponseBody + @PostMapping(value="/p1/transactionPage") + public ApiResponse transactionPage(HttpServletRequest request, @RequestHeader String token, @RequestBody BetParam param) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + JwtManager.TokenInfo tokenInfo = null; + + try { + //토큰체크 + if(token == null) { + log.error("#-p1::transactionPage::TOKEN_ERROR::"+request.getHeader("Authorization").toString()+"::"+ "access denied token"); + log.error("#-p1::transactionPage::"+ "T1003:Access token check"); + apiResponse.setResultCode("T1003"); + apiResponse.setResultMessage("Access token check"); + return apiResponse; + } + tokenInfo = jwtManager.getTokenInfo(token); + + } catch (Exception e) { + log.error("#-p1::transactionPage::TOKEN_ERROR::"+request.getHeader("Authorization").toString()+"::"+ "[Exception]"+e.toString()); + e.printStackTrace(); + apiResponse.fail(); + } + + final String LOG_PREFIX = "#-p1::transactionPage::"+tokenInfo.getSid()+"::::"; + + try { + // apiKey 체크 + Site site = siteService.getSiteInfo(request); + if(site == null) { + log.error(LOG_PREFIX+ "T1001:Access denied Key"); + apiResponse.setResultCode("T1001"); + apiResponse.setResultMessage("Access denied Key"); + return apiResponse; + } + + param.setSiteIdx(site.getSiteIdx()); + if(param.getCount() == null || param.getCount().equals("")) { + param.setCount("100"); + } + + int count = Integer.parseInt(param.getCount()); + if(count > 2000) { + param.setCount("3000"); + } + + if(param.getIsDetail() == null || param.getIsDetail().equals("")) param.setIsDetail("N"); + + log.info(LOG_PREFIX + "BetParam: " + param); + + // 결과보내기 + int betCnt = siteService.getApiBetTransactionCnt(param); + log.info(LOG_PREFIX + "total: " + betCnt); + List betList = siteService.getApiBetTransactionList(param); + if(param.getIsDetail().equals("Y")) { + for(HashMap item : betList) { + if(item.get("detail") != null && !"".equals(item.get("detail").toString())) { + JSONObject detailObj = new JSONObject(item.get("detail").toString()); + HashMap detailMap = new Gson().fromJson(detailObj.toString(), HashMap.class); + item.put("detail", detailMap); + } + } + } + log.info(LOG_PREFIX + "list size: " + betList.size()); + String nextStartDate = ""; + if(betList.size() > 0) { + nextStartDate = betList.get(betList.size()-1).get("regDate").toString(); + } else { + nextStartDate = param.getStartDate(); + } + + apiResponse.put("total", betCnt); + apiResponse.put("list", betList); + apiResponse.put("nextStartDate", nextStartDate); + + apiResponse.success(); + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + /** + * 파싱 API - 배팅내역 가져오기 (에볼루션전용-상세내용 포함) + * @param request + * @param token + * @param param + * @return + * @throws Exception + */ + @ResponseBody + @PostMapping(value="/p1/betListDetail") + public ApiResponse betListDetail(HttpServletRequest request, @RequestHeader String token, @RequestBody BetParam param) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + try { + // apiKey 체크 + Site site = siteService.getSiteInfo(request); + if(site == null) { + log.error("#-p1::betTransactionList::"+ "access denied Key"); + throw new ApiException("999", "access denied Key"); + } + + //토큰체크 + if(token == null) { + log.error("#-p1::betTransactionList::"+ "access denied token"); + throw new ApiException("1000", "access denied token"); + } + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfo(token); + final String LOG_PREFIX = "#-p1::betListDetail::"+tokenInfo.getSid()+"::::"; + log.info(LOG_PREFIX + "Request Body: " + param.toString()); + + long siteIdx = site.getSiteIdx(); + String startDateStr = param.getStartDate(); + String endDateStr = param.getEndDate(); + String memberId = param.getMemberId(); + int count = Integer.parseInt(param.getCount()); + + if(count < 100) { + count = 100; + } + if(count > 2000) { + count = 2000; + } + + NexusApiInfo nexusApiInfo = NexusApiInfo.builder() + .siteIdx(siteIdx) + .build(); + JSONObject detailObj = nexusService.getTransaction(LOG_PREFIX, nexusApiInfo); + + apiResponse.success(); + + } catch (Exception e) { + log.error("#-p1::betTransactionList::"+e.toString()); + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + /** + * 파싱 API - 배팅상세 가져오기 + * @param request + * @param token + * @param param + * @return + * @throws Exception + */ + @ResponseBody + @PostMapping(value="/p1/betDetail") + public ApiResponse betDetail(HttpServletRequest request, @RequestHeader String token, @RequestBody BetParam param) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + JSONObject saveObj = null; + JSONArray saveObjs = null; + boolean isSaveEvoDetail = false; + + try { + // apiKey 체크 + Site site = siteService.getSiteInfo(request); + if(site == null) { + log.error("#-p1::betDetail::"+ "T1001:Access denied Key"); + apiResponse.setResultCode("T1001"); + apiResponse.setResultMessage("Access denied Key"); + return apiResponse; + } + + //토큰체크 + if(token == null) { + log.error("#-p1::betDetail::"+ "T1003:Access token check"); + apiResponse.setResultCode("T1003"); + apiResponse.setResultMessage("Access token check"); + return apiResponse; + } + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfo(token); + final String LOG_PREFIX = "#-p1::betDetail::"+tokenInfo.getSid()+"::"+param.getBetId()+"::::"; + + ObjectMapper objectMapper = new ObjectMapper(); + String reqJsonStr = objectMapper.writeValueAsString(param); + JSONObject reqObj = new JSONObject(reqJsonStr); + log.info(LOG_PREFIX+ "Request {}", reqObj); + + // 결과보내기 + apiResponse.put("betId", param.getBetId()); + String dType = "detail_0"; + + HashMap betInfo = transService.getBetInfoByBetId(param); + log.info(LOG_PREFIX+ "betInfo {}", betInfo); + + if(betInfo == null) betInfo = transService.getSiteBetByRefIdFromOld(param); + log.info(LOG_PREFIX+ "betInfo_OLD {}", betInfo); + + if(betInfo != null) { + param.setBetId(betInfo.get("refId").toString()); + + String category = betInfo.get("vendorCetegory").toString(); + log.info(LOG_PREFIX+ "Game category : " + category); + + if("pragmatic".equals(betInfo.get("vendorCode").toString())) { + dType = "detail_2"; + apiResponse.put("dType", dType); + + String detailURL = pragmaticService.getDetails(LOG_PREFIX, betInfo); + if(detailURL != null && !detailURL.equals("")) { + HashMap url = new HashMap(); + url.put("url", detailURL); + apiResponse.put("detail", url); + } else { + apiResponse.put("detail", "betId is not exist"); + } + + } else if("svendor".equals(betInfo.get("vendorCode").toString()) + || "pink".equals(betInfo.get("vendorCode").toString())) { + String jsonStr = siteService.getOrgDetailData(param); + log.info(LOG_PREFIX+ "jsonStr : " + jsonStr); + if(jsonStr != null && !"".equals(jsonStr) && !"{}".equals(jsonStr)) { + dType = "detail_6"; + apiResponse.put("dType", dType); + HashMap detailMap = new Gson().fromJson(jsonStr, HashMap.class); + apiResponse.put("detail", detailMap); + } else { + isSaveEvoDetail = true; + JSONObject dataObj = svendorService.getDetail(LOG_PREFIX, betInfo); + if(dataObj == null) { + apiResponse.put("detail", "betId is not exist"); + } else { + if(dataObj.has("gameDetail") && !dataObj.isNull("gameDetail")) { + String detailType = StringUtils.getType(dataObj.getString("gameDetail")); + if(detailType.equals("URL")) { + dType = "detail_2"; + apiResponse.put("dType", dType); + String detailUrl = dataObj.getString("gameDetail"); + HashMap url = new HashMap(); + url.put("url", detailUrl); + apiResponse.put("detail", url); + } else if(detailType.equals("JSON")) { + dType = "detail_6"; + apiResponse.put("dType", dType); + JSONObject detailObj = dataObj.getJSONObject("gameDetail"); + saveObj = detailObj; + HashMap detailMap = new Gson().fromJson(detailObj.toString(), HashMap.class); + apiResponse.put("detail", detailMap); + } else { + apiResponse.put("detail", "betId is not exist"); + } + } else { + apiResponse.put("detail", "betId is not exist"); + } + } + } + + } else if(Integer.parseInt(betInfo.get("vendorIdx").toString())==17 && "tower".equals(betInfo.get("vendorCode").toString())) { + dType = "detail_2"; + apiResponse.put("dType", dType); + String detail_url = + betInfo.get("vendorApiUrl").toString() + +"/v2/detail_url" + + "?site_code="+betInfo.get("vendorApiId").toString() + + "&user_id="+betInfo.get("siteHex").toString()+betInfo.get("memberId").toString() + + "&transaction_id="+betInfo.get("transactionId").toString() + + "&vendorCode=pp" + + "&gameCode="+betInfo.get("gameIdx").toString(); + log.info(LOG_PREFIX+" {}" ,detail_url); + OkHttpClient client = new OkHttpClient().newBuilder().build(); + okhttp3.Request requestok2 = new okhttp3.Request.Builder() + .url(detail_url) + .method("GET", null)// + .addHeader("User-agent", "Mozilla") + .addHeader("Authorization", betInfo.get("vendorApiKey").toString()) + .build(); + okhttp3.Response response = client.newCall(requestok2).execute(); + + if(response.isSuccessful()){ + okhttp3.ResponseBody body = response.body(); + String responseString = body.string(); + log.info(LOG_PREFIX+ "responseString::"+responseString); + log.info(LOG_PREFIX+ "url::"+StringUtils.extractLink(responseString)); + String detailUrl = StringUtils.extractLink(responseString); + String detailType = StringUtils.getType(detailUrl); + if(detailType.equals("URL")) { + dType = "detail_2"; + apiResponse.put("dType", dType); + HashMap url = new HashMap(); + url.put("url", detailUrl); + apiResponse.put("detail", url); + } else { + apiResponse.put("detail", "betId is not exist"); + } + /* + HashMap url = new HashMap(); + url.put("url", StringUtils.extractLink(responseString)); + apiResponse.put("detail", url); + */ + } else { + apiResponse.put("detail", "betId is not exist"); + } + + } else if(Integer.parseInt(betInfo.get("vendorIdx").toString())==83 && "splus".equals(betInfo.get("vendorCode").toString())) { + dType = "detail_1"; + apiResponse.put("dType", dType); + HashMap d = new HashMap(); + List splusDetail = siteService.getSplusDetailData(param); + for(HashMap ttype : splusDetail) { + log.info(LOG_PREFIX+ "{}, {}", ttype.get("tranType").toString(), ttype.get("data").toString()); + HashMap detailMap = new Gson().fromJson(ttype.get("data").toString(), HashMap.class); + d.put(ttype.get("tranType").toString(), detailMap); + } + + apiResponse.put("detail", d); + + } else if("nexus".equals(betInfo.get("vendorCode").toString()) || "ace2".equals(betInfo.get("vendorCode").toString())) { + String jsonStr = siteService.getOrgDetailData(param); + log.info(LOG_PREFIX+ "jsonStr : " + jsonStr); + if(jsonStr != null && !"".equals(jsonStr) && !"{}".equals(jsonStr)) { + dType = "detail_3"; + apiResponse.put("dType", dType); + + JSONObject detailObj = new JSONObject(jsonStr); + String gameType = detailObj.optString("gameType"); + JSONArray participants = detailObj.optJSONArray("participants"); + if (participants != null) { + for (int i = 0; i < participants.length(); i++) { + // result 객체 가져오기 (없으면 생성) + JSONObject participant = participants.optJSONObject(i); + JSONObject result = participant.optJSONObject("result"); + if (result == null) { + result = new JSONObject(); + participant.put("result", result); + } + + // link 값 세팅 + String raw = "betId="+param.getBetId()+"&gameType="+gameType; + String encrypted = AesUtil.encrypt(raw); + result.put("link", "https://fst.tx-direction.cc/detailsPage/"+encrypted); + } + } + HashMap detailMap = new Gson().fromJson(detailObj.toString(), HashMap.class); + apiResponse.put("detail", detailMap); + } else { + isSaveEvoDetail = true; + long siteIdx = (long) betInfo.get("siteIdx"); + long memberIdx = (long) betInfo.get("memberIdx"); + String trxId = betInfo.get("vendorTranKey").toString(); + String apiBaseUrl = betInfo.get("vendorApiUrl").toString(); + String apiAgentId = betInfo.get("vendorApiId").toString(); + String apiSecretKey = betInfo.get("vendorApiKey").toString(); + NexusApiInfo nexusApiInfo = NexusApiInfo.builder() + .siteIdx(siteIdx) + .memberIdx(memberIdx) + .apiBaseUrl(apiBaseUrl) + .agentId(apiAgentId) + .agentSecretKey(apiSecretKey) + .build(); + if("CASINO".equals(betInfo.get("vendorCetegory").toString())) { + dType = "detail_3"; + apiResponse.put("dType", dType); + JSONObject detailObj = nexusService.getDetail(LOG_PREFIX, nexusApiInfo, trxId); + if(detailObj == null) { + apiResponse.put("detail", "betId is not exist"); + } else { + int resultCode = detailObj.getInt("code"); + if(resultCode == 0) { + JSONArray transactions = detailObj.getJSONArray("transactions"); + if(transactions.length() > 0) { + List> detailMap = new Gson().fromJson(transactions.toString(), List.class); + saveObjs = transactions; + apiResponse.put("detail", detailMap); + } else { + apiResponse.put("detail", "betId is not exist"); + } + } else { + apiResponse.put("detail", "betId is not exist"); + } + } + } else { + dType = "detail_2"; + apiResponse.put("dType", dType); + JSONObject detailObj = nexusService.getDetailUrl(LOG_PREFIX, nexusApiInfo, trxId); + if(detailObj == null) { + apiResponse.put("detail", "betId is not exist"); + } else { + log.info(LOG_PREFIX+ "detailObj::"+detailObj.toString()); + int resultCode = detailObj.getInt("code"); + if(resultCode == 0) { + HashMap url = new HashMap<>(); + url.put("url", detailObj.getString("url")); + apiResponse.put("detail", url); + } else { + apiResponse.put("detail", "betId is not exist"); + } + } + } + } + } else if("prime".equals(betInfo.get("vendorCode").toString()) + || "dpcore".equals(betInfo.get("vendorCode").toString())) { + log.info(LOG_PREFIX+ "========== BetDetail::PRIME =========="); + dType = "detail_9"; + apiResponse.put("dType", dType); + + String jsonStr = siteService.getOrgDetailData(param); + if(jsonStr != null && !"".equals(jsonStr) && !"{}".equals(jsonStr)) { + + JSONObject detailObj = new JSONObject(jsonStr); + String gameType = detailObj.optString("gameType"); + JSONArray participants = detailObj.optJSONArray("participants"); + if (participants != null) { + for (int i = 0; i < participants.length(); i++) { + // result 객체 가져오기 (없으면 생성) + JSONObject participant = participants.optJSONObject(i); + JSONObject result = participant.optJSONObject("result"); + if (result == null) { + result = new JSONObject(); + participant.put("result", result); + } + + // link 값 세팅 + String raw = "betId="+param.getBetId()+"&gameType="+gameType; + String encrypted = AesUtil.encrypt(raw); + result.put("link", "https://fst.tx-direction.cc/detailsPage/"+encrypted); + } + } + HashMap detailMap = new Gson().fromJson(detailObj.toString(), HashMap.class); + apiResponse.put("detail", detailMap); + } else { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + String apiKey = "Bearer "+betInfo.get("vendorApiKey").toString(); + headers.set("Authorization", apiKey); + String detailUrl = betInfo.get("vendorApiUrl").toString() + "/api/getBettingDetails5?"; + String detailParam = "referer="+param.getBetId(); + detailUrl = detailUrl + detailParam; + + log.info(LOG_PREFIX+ "PRIME::Detail Url: " + detailUrl); + log.info(LOG_PREFIX+ "PRIME::Detail Headers: " + headers.toString()); + ResponseEntity response = null; + JSONObject resJson = null; + try { + response = webClient.get() + .uri(detailUrl) + .headers(h -> h.addAll(headers)) + .retrieve() + .toEntity(String.class) + .block(); + } catch(WebClientResponseException e) { + log.error(LOG_PREFIX+ "PRIME::Detail HttpClientErrorException : " + e.getMessage()); + log.error(LOG_PREFIX+ "PRIME::Detail status code : " + e.getStatusCode().value()); + log.error(LOG_PREFIX+ "PRIME::Detail response body : " + e.getResponseBodyAsString()); + resJson = new JSONObject(e.getResponseBodyAsString()); + log.error(LOG_PREFIX+ "PRIME::Detail error : " + resJson.getString("message")); + throw new ApiException("P209", resJson.getString("message")); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "PRIME::Detail ConnectTimeoutException::"+rae.getMessage()); + } + if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "PRIME::Detail SocketTimeoutException::"+rae.getMessage()); + } + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "PRIME::Detail InterruptedException::"+rae.getMessage()); + } + throw new ApiException("P210", rae.getMessage()); + } catch (Exception e) { + log.error(LOG_PREFIX+ "PRIME::Detail Exception : " + e.getMessage()); + throw new ApiException("P211", e.getMessage()); + } + + if(response != null && response.getStatusCode() == HttpStatus.OK) { + isSaveEvoDetail = true; + log.info(LOG_PREFIX+ "PRIME::Detail response : " + response.getBody()); + resJson = new JSONObject(response.getBody()); + + JSONObject dataObj = resJson; + String gameType = dataObj.optString("gameType"); + JSONArray participants = dataObj.optJSONArray("participants"); + if (participants != null) { + for (int i = 0; i < participants.length(); i++) { + // result 객체 가져오기 (없으면 생성) + JSONObject participant = participants.optJSONObject(i); + JSONObject result = participant.optJSONObject("result"); + if (result == null) { + result = new JSONObject(); + participant.put("result", result); + } + + // link 값 세팅 + String raw = "betId="+param.getBetId()+"&gameType="+gameType; + String encrypted = AesUtil.encrypt(raw); + result.put("link", "https://fst.tx-direction.cc/detailsPage/"+encrypted); + } + } + saveObj = dataObj; + HashMap detailMap = new Gson().fromJson(dataObj.toString(), HashMap.class); + apiResponse.put("detail", detailMap); + } else { + apiResponse.put("detail", "betId is not exist"); + } + } + } else if("grand".equals(betInfo.get("vendorCode").toString())) { + dType = "detail_2"; + apiResponse.put("dType", dType); + String detailUrl = + betInfo.get("vendorApiUrl").toString() + +"/transactions/detail" + + "?round_id="+betInfo.get("vendorTranKey").toString(); + log.info(LOG_PREFIX+"Request Url : {}" ,detailUrl); + OkHttpClient client = new OkHttpClient().newBuilder().build(); + okhttp3.Request requestok2 = new okhttp3.Request.Builder() + .url(detailUrl) + .method("GET", null)// + .addHeader("User-agent", "Mozilla") + .addHeader("Authorization", "Bearer "+betInfo.get("vendorApiKey").toString()) + .build(); + okhttp3.Response response = client.newCall(requestok2).execute(); + + if(response.isSuccessful()){ + okhttp3.ResponseBody body = response.body(); + String responseString = body.string(); + log.info(LOG_PREFIX+ "responseString : " , responseString); + JSONObject responseObj = new JSONObject(responseString); + JSONObject dataObj = responseObj.getJSONObject("data"); + if(dataObj != null) { + HashMap url = new HashMap(); + url.put("url", dataObj.getString("url")); + apiResponse.put("detail", url); + } else { + apiResponse.put("detail", "betId is not exist"); + } + } else { + apiResponse.put("detail", "betId is not exist"); + } + } else if("pracp".equals(betInfo.get("vendorCode").toString())) { + dType = "detail_2"; + apiResponse.put("dType", dType); + + HashMap apiInfo = new HashMap<>(); + apiInfo.put("apiAgentCode", betInfo.get("vendorApiId").toString()); + apiInfo.put("apiToken", betInfo.get("vendorApiKey").toString()); + apiInfo.put("apiBaseUrl", betInfo.get("vendorApiUrl").toString()); + apiInfo.put("uuid", betInfo.get("uuid").toString()); + apiInfo.put("round_id", betInfo.get("roundId").toString()); + + JSONObject dataObj = pracpService.getDetail(LOG_PREFIX, apiInfo); + log.info(LOG_PREFIX+ "dataObj : " + dataObj.toString()); + if(dataObj != null) { + HashMap url = new HashMap(); + url.put("url", dataObj.getString("url")); + apiResponse.put("detail", url); + } else { + apiResponse.put("detail", "betId is not exist"); + } + } else if("tplus".equals(betInfo.get("vendorCode").toString())) { + dType = "detail_2"; + apiResponse.put("dType", dType); + + String apiBaseUrl = betInfo.get("vendorApiUrl").toString(); + String apiAuthKey = betInfo.get("vendorApiKey").toString(); + String pairTransactionKey = betInfo.get("refId").toString(); + TplusApiInfo apiInfo = TplusApiInfo.builder() + .apiBaseUrl(apiBaseUrl) + .apiAuthKey(apiAuthKey) + .pairTransactionKey(pairTransactionKey).build(); + + log.info(LOG_PREFIX+ "tplus::apiInfo: " + apiInfo); + + String detailURL = tplusService.getDetails(LOG_PREFIX, apiInfo); + if(detailURL != null && !detailURL.equals("")) { + HashMap url = new HashMap(); + url.put("url", detailURL); + apiResponse.put("detail", url); + } else { + apiResponse.put("detail", "betId is not exist"); + } + } else if("onix".equals(betInfo.get("vendorCode").toString())) { + log.info(LOG_PREFIX+ "========== BetDetail::ONIX =========="); + dType = "detail_8"; + apiResponse.put("dType", dType); + + String jsonStr = siteService.getOrgDetailData(param); + if(jsonStr != null && !"".equals(jsonStr) && !"{}".equals(jsonStr)) { + JSONObject detailObj = new JSONObject(jsonStr); + String gameType = detailObj.optString("gameType"); + JSONArray participants = detailObj.optJSONArray("participants"); + if (participants != null) { + for (int i = 0; i < participants.length(); i++) { + // result 객체 가져오기 (없으면 생성) + JSONObject participant = participants.optJSONObject(i); + JSONObject result = participant.optJSONObject("result"); + if (result == null) { + result = new JSONObject(); + participant.put("result", result); + } + + // link 값 세팅 + String raw = "betId="+param.getBetId()+"&gameType="+gameType; + String encrypted = AesUtil.encrypt(raw); + result.put("link", "https://fst.tx-direction.cc/detailsPage/"+encrypted); + } + } + HashMap detailMap = new Gson().fromJson(detailObj.toString(), HashMap.class); + apiResponse.put("detail", detailMap); + } else { + String apiBaseUrl = betInfo.get("vendorApiUrl").toString(); + String fullDateTime = betInfo.get("betTime").toString(); + String dateOnly = fullDateTime.substring(0, 10); + + // Step 1: Get round info from /csapi/getBetting + String bettingUrl = apiBaseUrl + "/csapi/getBetting"; + JSONObject bettingBody = new JSONObject(); + bettingBody.put("userid", betInfo.get("siteIdxHex").toString()+betInfo.get("memberId").toString()); + bettingBody.put("sdate", dateOnly+" 00:00:00.000"); + bettingBody.put("edate", dateOnly+" 23:59:59.999"); + bettingBody.put("pagesize", "1"); + bettingBody.put("gameid", "0"); + bettingBody.put("roundcode", betInfo.get("uuid").toString()); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.set("Authorization", "Bearer " + betInfo.get("vendorApiKey").toString()); + + log.info(LOG_PREFIX+ "ONIX::Step1 getBetting Url: " + bettingUrl); + log.info(LOG_PREFIX+ "ONIX::Step1 getBetting Body: " + bettingBody.toString()); + + try { + ResponseEntity bettingRes = webClient.post() + .uri(bettingUrl) + .headers(h -> h.addAll(headers)) + .bodyValue(bettingBody.toString()) + .retrieve() + .toEntity(String.class) + .block(); + if(bettingRes != null && bettingRes.getBody() != null) { + JSONObject bettingObj = new JSONObject(bettingRes.getBody()); + log.info(LOG_PREFIX+ "ONIX::Step1 getBetting Response: " + bettingObj.toString()); + + int bettingResult = bettingObj.getInt("result"); + if(bettingResult == 1 && bettingObj.has("data")) { + JSONArray dataArray = bettingObj.getJSONArray("data"); + if(dataArray.length() > 0) { + isSaveEvoDetail = true; + JSONObject dataObj = dataArray.getJSONObject(0); + JSONObject detailObj = dataObj.getJSONArray("details").getJSONObject(0); + String gameType = detailObj.optString("gameType"); + JSONArray participants = detailObj.optJSONArray("participants"); + if (participants != null) { + for (int i = 0; i < participants.length(); i++) { + // result 객체 가져오기 (없으면 생성) + JSONObject participant = participants.optJSONObject(i); + JSONObject result = participant.optJSONObject("result"); + if (result == null) { + result = new JSONObject(); + participant.put("result", result); + } + + // link 값 세팅 + String raw = "betId="+param.getBetId()+"&gameType="+gameType; + String encrypted = AesUtil.encrypt(raw); + result.put("link", "https://fst.tx-direction.cc/detailsPage/"+encrypted); + } + } + HashMap detailMap = new Gson().fromJson(detailObj.toString(), HashMap.class); + apiResponse.put("detail", detailMap); + saveObj = detailObj; + + } else { + apiResponse.put("detail", "betId is not exist"); + } + } else { + apiResponse.put("detail", "betId is not exist"); + String errorMsg = bettingObj.has("msg") ? bettingObj.getString("msg") : "Unknown error"; + log.error(LOG_PREFIX+ "ONIX::Betting Error: " + errorMsg); + } + } else { + apiResponse.put("detail", "betId is not exist"); + log.error(LOG_PREFIX+ "ONIX::Betting Response is null"); + } + } catch(WebClientResponseException e) { + log.error(LOG_PREFIX+ "ONIX::Betting HttpClientErrorException : " + e.getMessage()); + log.error(LOG_PREFIX+ "ONIX::Betting status code : " + e.getStatusCode().value()); + log.error(LOG_PREFIX+ "ONIX::Betting response body : " + e.getResponseBodyAsString()); + JSONObject errorJson = new JSONObject(e.getResponseBodyAsString()); + String errorMsg = errorJson.has("msg") ? errorJson.getString("msg") : "Betting API error"; + log.error(LOG_PREFIX+ "ONIX::Betting error : " + errorMsg); + throw new ApiException("P209", errorMsg); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ONIX::Betting ConnectTimeoutException::" + rae.getMessage()); + } + if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "ONIX::Betting ReadTimeoutException::" + rae.getMessage()); + } + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "ONIX::Betting InterruptedException::" + rae.getMessage()); + } + throw new ApiException("P210", rae.getMessage()); + } catch(Exception e) { + log.error(LOG_PREFIX+ "ONIX::Betting Exception : " + e.getMessage()); + throw new ApiException("P211", e.getMessage()); + } + } + } else if("bet_radar".equals(betInfo.get("vendorCode").toString())) { + log.info(LOG_PREFIX+ "========== BetDetail::BET_RADAR =========="); + // TODO: 베팅상세 내려주기 + /* + * param.getBetId() 기준으로 bet_radar_log 테이블 조회시 베팅과 결과 두가지가 나옴. + * 결과가 없는경우 베팅만 한가지 있을 수 있음. + * param.getBetId() 기준 bet_radar_log에서 jsonstr(베팅상세 json 원본)을 가져와서 + * 하나의 json으로 합쳐서 내려주기 구현. + */ + // bet_radar_log 테이블에서 조회 + String radarLogJson = siteService.getMergedBetRadarLog(param.getBetId()); + if(radarLogJson != null && !radarLogJson.isEmpty()) { + log.info(LOG_PREFIX+ "bet_radar_log found, returning merged json"); + dType = "detail_radar"; + apiResponse.put("dType", dType); + HashMap detailMap = new Gson().fromJson(radarLogJson, HashMap.class); + String detailUrl = "https://sportsbook.spokok.com/bets/detail/"+param.getBetId(); + detailMap.put("dLink", detailUrl); + apiResponse.put("detail", detailMap); + apiResponse.success(); + return apiResponse; + } + } else if("thenut".equals(betInfo.get("vendorCode").toString())) { + log.info(LOG_PREFIX+ "========== BetDetail::THENUT =========="); + String jsonStr = siteService.getOrgDetailData(param); + log.info(LOG_PREFIX+ "jsonStr : " + jsonStr); + if(jsonStr != null && !"".equals(jsonStr) && !"{}".equals(jsonStr)) { + String detailType = StringUtils.getType(jsonStr); + if(detailType.equals("URL")) { + dType = "detail_2"; + apiResponse.put("dType", dType); + String detailUrl = jsonStr; + HashMap url = new HashMap(); + url.put("url", detailUrl); + apiResponse.put("detail", url); + } else if(detailType.equals("JSON")) { + dType = "detail_3"; + apiResponse.put("dType", dType); + + JSONObject detailObj = new JSONObject(jsonStr); + String gameType = detailObj.optString("gameType"); + JSONArray participants = detailObj.optJSONArray("participants"); + if (participants != null) { + for (int i = 0; i < participants.length(); i++) { + // result 객체 가져오기 (없으면 생성) + JSONObject participant = participants.optJSONObject(i); + JSONObject result = participant.optJSONObject("result"); + if (result == null) { + result = new JSONObject(); + participant.put("result", result); + } + + // link 값 세팅 + String raw = "betId="+param.getBetId()+"&gameType="+gameType; + String encrypted = AesUtil.encrypt(raw); + result.put("link", "https://fst.tx-direction.cc/detailsPage/"+encrypted); + } + } + HashMap detailMap = new Gson().fromJson(detailObj.toString(), HashMap.class); + apiResponse.put("detail", detailMap); + } else { + apiResponse.put("dType", dType); + apiResponse.put("detail", "betId is not exist"); + } + } else { + String apiBaseUrl = betInfo.get("vendorApiUrl").toString(); + String apiKey = betInfo.get("vendorApiKey").toString(); + HashMap apiInfo = new HashMap<>(); + apiInfo.put("apiBaseUrl", apiBaseUrl); + apiInfo.put("apiKey", apiKey); + apiInfo.put("betId", param.getBetId()); + + if("CASINO".equals(betInfo.get("vendorCetegory").toString())) { + isSaveEvoDetail = true; + dType = "detail_3"; + apiResponse.put("dType", dType); + JSONObject detailObj = thenutService.getBetDetail(LOG_PREFIX, apiInfo); + if(detailObj == null) { + apiResponse.put("detail", "betId is not exist"); + } else { + String gameType = detailObj.optString("gameType"); + JSONArray participants = detailObj.optJSONArray("participants"); + if (participants != null) { + for (int i = 0; i < participants.length(); i++) { + // result 객체 가져오기 (없으면 생성) + JSONObject participant = participants.optJSONObject(i); + JSONObject result = participant.optJSONObject("result"); + if (result == null) { + result = new JSONObject(); + participant.put("result", result); + } + + // link 값 세팅 + String raw = "betId="+param.getBetId()+"&gameType="+gameType; + String encrypted = AesUtil.encrypt(raw); + result.put("link", "https://fst.tx-direction.cc/detailsPage/"+encrypted); + } + } + HashMap detailMap = new Gson().fromJson(detailObj.toString(), HashMap.class); + apiResponse.put("detail", detailMap); + saveObj = detailObj; + } + } else { + dType = "detail_2"; + apiResponse.put("dType", dType); + String detailUrl = thenutService.getBetDetailUrl(LOG_PREFIX, apiInfo); + if(detailUrl == null) { + apiResponse.put("detail", "betId is not exist"); + } else { + log.info(LOG_PREFIX+ "detailUrl::"+detailUrl); + HashMap url = new HashMap<>(); + url.put("url", detailUrl); + apiResponse.put("detail", url); + } + } + } + } else if("panda".equals(betInfo.get("vendorCode").toString())) { + dType = "detail_2"; + apiResponse.put("dType", dType); + String apiBaseUrl = betInfo.get("vendorApiUrl").toString(); + String apiKey = betInfo.get("vendorApiKey").toString(); + String tranId = betInfo.get("uuid").toString(); + + HashMap apiInfo = new HashMap<>(); + apiInfo.put("apiBaseUrl", apiBaseUrl); + apiInfo.put("apiKey", apiKey); + apiInfo.put("tranId", tranId); + String detailUrl = pandaService.getDetail(LOG_PREFIX, apiInfo); + if(detailUrl == null) { + apiResponse.put("detail", "betId is not exist"); + } else { + log.info(LOG_PREFIX+ "detailUrl::"+detailUrl); + HashMap url = new HashMap<>(); + url.put("url", detailUrl); + apiResponse.put("detail", url); + } + } else { + apiResponse.put("dType", dType); + apiResponse.put("detail", "betId is not exist"); + } + } else { + apiResponse.put("dType", dType); + apiResponse.put("detail", "betId is not exist"); + } + + if(saveObj != null || saveObjs != null) { + // check detail data + if(isSaveEvoDetail) { + asyncSiteService.insertEvoDetailProc(LOG_PREFIX, param.getBetId(), saveObj, saveObjs); + } + } else { + log.info(LOG_PREFIX+ "saved detail is null"); + } + + apiResponse.success(); + } catch (Exception e) { + log.info(e.toString()); + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + /** + * 파싱 API - 파싱설정 + * @param request + * @param token + * @param param + * @return + * @throws Exception + */ + + @ResponseBody + @PostMapping(value="/p1/parseUseUpdate") + public ApiResponse parseUseUpdate(HttpServletRequest request, @RequestHeader String token, @RequestBody PlayParam param) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + try { + //apiKey 체크 + Site site = siteService.getSiteInfo(request); + if(site == null) { + log.error("#-p1::parseUseUpdate::"+ "access denied Key"); + throw new ApiException("999", "access denied Key"); + } + + //토큰체크 + if(token == null) { + log.error("#-p1::parseUseUpdate::"+ "access denied token"); + throw new ApiException("1000", "access denied token"); + } + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfo(token); + final String LOG_PREFIX = "#-p1::parseUseUpdate::"+tokenInfo.getSid()+"::::"; + + + if(param.getParseUseYn()!=null && !"".equals(param.getParseUseYn())) { + HashMap parseParam = new HashMap(); + parseParam.put("siteIdx", site.getSiteIdx()); + parseParam.put("siteId", site.getSiteId()); + parseParam.put("useYn", param.getParseUseYn()); + siteService.insertParseUse(parseParam); + log.info(LOG_PREFIX + "insertParseUse SUCC"); + } + + HashMap ParseUseYn = siteService.getParseUseYn(site.getSiteIdx()); + if(ParseUseYn==null || "N".equals(ParseUseYn.get("useYn").toString())) { + apiResponse.put("currentUseYn","N"); + } else { + apiResponse.put("currentUseYn","Y"); + } + log.info(LOG_PREFIX + "ParseUseYn: " + apiResponse.toString()); + + apiResponse.success(); + } catch (Exception e) { + log.error("#-p1::parseUseUpdate::"+e.toString()); + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + /** + * url과 파라미터 및 헤더정보를 가지고 그대로 해당 url에 바이패스하는 함수 + */ + @PostMapping("/bypass") + public ResponseEntity bypass( + @RequestParam String targetUrl, + @RequestParam String targetMethod, + @RequestParam(required = false) String targetParameter, + @RequestParam(defaultValue = "JSON") String parameterType, + @RequestParam(required = false) String targetContentType, + HttpServletRequest request) { + + log.info("=== Bypass Request Started ==="); + log.info("Target URL: {}", targetUrl); + log.info("Target Method: {}", targetMethod); + log.info("Parameter Type: {}", parameterType); + + try { + HttpMethod httpMethod = HttpMethod.valueOf(targetMethod.toUpperCase()); + + // 헤더 설정 + HttpHeaders headers = createHeaders(request, targetContentType, parameterType); + + // URL 및 요청 엔티티 준비 + String finalUrl; + + if (isGetOrDelete(httpMethod)) { + // GET/DELETE: 쿼리 파라미터로 추가 + finalUrl = buildUrlWithQueryParams(targetUrl, targetParameter, parameterType); + log.info("GET/DELETE request to: {}", finalUrl); + } else { + // POST/PUT: Body에 데이터 포함 + finalUrl = targetUrl; + } + + WebClient.RequestBodySpec requestSpec = webClient.method(httpMethod).uri(finalUrl); + requestSpec.headers(h -> h.addAll(headers)); + + if (!isGetOrDelete(httpMethod)) { + String body = hasParameter(targetParameter) ? targetParameter : null; + if (body != null) { + requestSpec.bodyValue(body); + } + log.info("POST/PUT request to: {} with body length: {}", + finalUrl, body != null ? body.length() : 0); + } + + ResponseEntity response = requestSpec.retrieve() + .toEntity(String.class) + .block(); + + log.info("Response received - Status: {}, Body length: {}", + response.getStatusCode(), + response.getBody() != null ? response.getBody().length() : 0); + + // 응답 헤더 복사 (일부 시스템 헤더 제외) + HttpHeaders responseHeaders = new HttpHeaders(); + response.getHeaders().forEach((key, value) -> { + if (!isSystemHeader(key)) { + responseHeaders.put(key, value); + } + }); + + return ResponseEntity.status(response.getStatusCode()) + .headers(responseHeaders) + .body(response.getBody()); + + } catch (WebClientResponseException e) { + // 4xx 에러 (클라이언트 에러) + log.error("Client error - Status: {}, Body: {}", e.getStatusCode().value(), e.getResponseBodyAsString()); + return ResponseEntity.status(e.getStatusCode().value()) + .body(e.getResponseBodyAsString()); + + } catch (WebClientRequestException e) { + // 타임아웃이나 연결 에러 + log.error("Connection error: {}", e.getMessage()); + return ResponseEntity.status(HttpStatus.REQUEST_TIMEOUT) + .body(createErrorResponse("연결 타임아웃 또는 네트워크 에러: " + e.getMessage())); + + } catch (IllegalArgumentException e) { + log.error("Invalid HTTP method: {}", targetMethod); + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(createErrorResponse("잘못된 HTTP 메소드: " + targetMethod)); + + } catch (Exception e) { + log.error("Bypass failed: ", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(createErrorResponse("요청 처리 중 오류 발생: " + e.getMessage())); + } + } + + + /** + * 에볼루션 상세 콜백 + * @param request + * @param requestBody + * @return + * @throws Exception + */ + @ResponseBody + @RequestMapping(path = "/evoDetail") + public ApiResponse evoDetail(HttpServletRequest request, @RequestBody BetParam param) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + final String LOG_PREFIX = "#-API::evoDetail::"+param.getBetId()+"::::"; + + try { + String jsonStr = siteService.getOrgDetailData(param); + log.info(LOG_PREFIX+ "jsonStr : " + jsonStr); + if(jsonStr != null && !"".equals(jsonStr) && !"{}".equals(jsonStr)) { + + JSONObject detailObj = new JSONObject(jsonStr); + String gameType = detailObj.optString("gameType"); + JSONArray participants = detailObj.optJSONArray("participants"); + if (participants != null) { + for (int i = 0; i < participants.length(); i++) { + // result 객체 가져오기 (없으면 생성) + JSONObject participant = participants.optJSONObject(i); + JSONObject result = participant.optJSONObject("result"); + if (result == null) { + result = new JSONObject(); + participant.put("result", result); + } + + // link 값 세팅 + String raw = "betId="+param.getBetId()+"&gameType="+gameType; + String encrypted = AesUtil.encrypt(raw); + result.put("link", "https://fst.tx-direction.cc/detailsPage/"+encrypted); + } + } + + HashMap detailMap = new Gson().fromJson(detailObj.toString(), HashMap.class); + apiResponse.put("detail", detailMap); + } + + apiResponse.success(); + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + apiResponse.fail(); + } + + return apiResponse; + } + + + /** + * 헤더 생성 + */ + private HttpHeaders createHeaders(HttpServletRequest request, String targetContentType, String parameterType) { + HttpHeaders headers = new HttpHeaders(); + + // 원본 요청의 주요 헤더들 복사 + copyImportantHeaders(request, headers); + + // Content-Type 설정 + setContentType(headers, targetContentType, parameterType); + + // 브라우저와 유사한 추가 헤더들 + setBrowserLikeHeaders(headers); + + log.debug("Request headers: {}", headers); + return headers; + } + + /** + * 중요한 헤더들 복사 + */ + private void copyImportantHeaders(HttpServletRequest request, HttpHeaders headers) { + // Authorization 헤더 (인증 정보) + String authorization = request.getHeader("Authorization"); + if (authorization != null) { + headers.add("Authorization", authorization); + log.debug("Copied Authorization header"); + } + + // API Key 관련 헤더들 + String apiKey = request.getHeader("X-API-Key"); + if (apiKey != null) { + headers.add("X-API-Key", apiKey); + } + + String apiToken = request.getHeader("X-API-Token"); + if (apiToken != null) { + headers.add("X-API-Token", apiToken); + } + + // 커스텀 헤더들 (X-로 시작하는 것들) + Enumeration headerNames = request.getHeaderNames(); + while (headerNames.hasMoreElements()) { + String headerName = headerNames.nextElement(); + if (headerName.startsWith("X-") && !headerName.equals("X-Forwarded-For")) { + headers.add(headerName, request.getHeader(headerName)); + log.debug("Copied custom header: {}", headerName); + } + } + } + + /** + * Content-Type 설정 + */ + private void setContentType(HttpHeaders headers, String targetContentType, String parameterType) { + if (targetContentType != null && !targetContentType.trim().isEmpty()) { + // 명시적으로 지정된 Content-Type 사용 + try { + headers.setContentType(MediaType.parseMediaType(targetContentType)); + log.debug("Set explicit Content-Type: {}", targetContentType); + } catch (Exception e) { + log.warn("Invalid targetContentType: {}, using parameterType instead", targetContentType); + setContentTypeByParameterType(headers, parameterType); + } + } else { + // parameterType을 기반으로 Content-Type 설정 + setContentTypeByParameterType(headers, parameterType); + } + } + + /** + * 파라미터 타입에 따른 Content-Type 설정 + */ + private void setContentTypeByParameterType(HttpHeaders headers, String parameterType) { + String upperParamType = parameterType.toUpperCase(); + switch (upperParamType) { + case "FORM": + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + break; + case "XML": + headers.setContentType(MediaType.APPLICATION_XML); + break; + case "TEXT": + headers.setContentType(MediaType.TEXT_PLAIN); + break; + case "HTML": + headers.setContentType(MediaType.TEXT_HTML); + break; + default: + headers.setContentType(MediaType.APPLICATION_JSON); + break; + } + log.debug("Set Content-Type by parameter type: {}", headers.getContentType()); + } + + /** + * 브라우저와 유사한 헤더 설정 + */ + private void setBrowserLikeHeaders(HttpHeaders headers) { + // User-Agent가 없으면 설정 + if (!headers.containsKey("User-Agent")) { + headers.add("User-Agent", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"); + } + + // Accept 헤더 + if (!headers.containsKey("Accept")) { + headers.add("Accept", "*/*"); + } + + // 기타 브라우저 헤더들 + headers.add("Accept-Language", "ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7"); + headers.add("Accept-Encoding", "gzip, deflate, br"); + headers.add("Cache-Control", "no-cache"); + headers.add("Pragma", "no-cache"); + } + + /** + * GET/DELETE 메소드 확인 + */ + private boolean isGetOrDelete(HttpMethod method) { + return method == HttpMethod.GET || method == HttpMethod.DELETE; + } + + /** + * 파라미터 존재 확인 + */ + private boolean hasParameter(String parameter) { + return parameter != null && !parameter.trim().isEmpty(); + } + + /** + * 쿼리 파라미터가 포함된 URL 생성 + */ + private String buildUrlWithQueryParams(String baseUrl, String parameter, String parameterType) { + if (!hasParameter(parameter)) { + return baseUrl; + } + + try { + UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(baseUrl); + + String upperParamType = parameterType.toUpperCase(); + if ("FORM".equals(upperParamType)) { + // Form 데이터를 쿼리 파라미터로 파싱 + String[] pairs = parameter.split("&"); + for (String pair : pairs) { + String[] keyValue = pair.split("=", 2); + if (keyValue.length == 2) { + builder.queryParam(keyValue[0], keyValue[1]); + } + } + } else { + // JSON이나 기타 형식은 data 파라미터로 + builder.queryParam("data", URLEncoder.encode(parameter, "UTF-8")); + } + + return builder.toUriString(); + } catch (Exception e) { + log.warn("Failed to build URL with query params: {}", e.getMessage()); + String separator = baseUrl.contains("?") ? "&" : "?"; + return baseUrl + separator + "data=" + parameter; + } + } + + /** + * 시스템 헤더 확인 (응답에서 제외할 헤더들) + */ + private boolean isSystemHeader(String headerName) { + String lowerName = headerName.toLowerCase(); + return lowerName.equals("transfer-encoding") || + lowerName.equals("connection") || + lowerName.equals("server") || + lowerName.equals("date") || + lowerName.startsWith("access-control-"); + } + + /** + * 에러 응답 생성 + */ + private String createErrorResponse(String message) { + return String.format("{\"success\":false,\"error\":\"%s\",\"timestamp\":%d}", + message.replace("\"", "\\\""), System.currentTimeMillis()); + } + +} diff --git a/src/main/java/com/bb/front/CallBackAceController.java b/src/main/java/com/bb/front/CallBackAceController.java new file mode 100644 index 0000000..986380a --- /dev/null +++ b/src/main/java/com/bb/front/CallBackAceController.java @@ -0,0 +1,1679 @@ +package com.bb.front; + +import java.net.SocketTimeoutException; +import java.text.SimpleDateFormat; +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; + +import jakarta.servlet.http.HttpServletRequest; + +import org.apache.http.conn.ConnectTimeoutException; +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.ResourceAccessException; + +import com.bb.model.NexusBalanceData; +import com.bb.model.NexusResponse; +import com.bb.model.NexusSmlData; +import com.bb.model.NexusSmlRequest; +import com.bb.service.AsyncSiteService; +import com.bb.service.CallBackService; +import com.bb.service.SiteService; + +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@RequestMapping("/api/callback/ace2") +@RequiredArgsConstructor +@SecurityRequirement(name = "Authorization") +@EnableScheduling +@RestController +public class CallBackAceController { + + @Autowired + SiteService siteService; + + @Autowired + CallBackService callBackService; + + @Autowired + AsyncSiteService asyncCallBackService; + + + @ResponseBody + @RequestMapping(path = "/callBalance") + public ResponseEntity callBalance(HttpServletRequest request, @RequestBody net.sf.json.JSONObject requestBody) throws Exception { + NexusResponse response = null; + HttpStatus httpStatus = null; + + String apiKey = requestBody.getString("apiKey"); + net.sf.json.JSONObject params = requestBody.getJSONObject("params"); + String siteUsername = params.getString("siteUsername"); + String requestedAt = params.getString("requestedAt"); + + if(siteUsername == null || siteUsername.equals("") || siteUsername.equals("invalid-user")) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("존재하지 않는 회원입니다"); + httpStatus = HttpStatus.OK; + return new ResponseEntity(response, httpStatus); + } + + long siteIdx = Long.parseLong(siteUsername.substring(0, 3), 16); + String memberId = siteUsername.substring(3, siteUsername.length()); + final String LOG_PREFIX = "#-CB::ACE::::callBalance::"+memberId+"::"+requestedAt+":::"; + log.info(LOG_PREFIX+ "Request::" + requestBody.toString()); + + try { + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "ace2"); + sParam.put("apiKey", apiKey); + log.info(LOG_PREFIX + "getSiteVendorInfo::"+sParam.toString()); + HashMap siteApiInfo = siteService.getSiteApiInfoByApiKey(sParam); + if(siteApiInfo == null) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("API키가 일치하지 않습니다"); + httpStatus = HttpStatus.OK; + return new ResponseEntity(response, httpStatus); + } + + if(siteApiInfo.get("memberIdx") == null) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("존재하지 않는 회원입니다"); + httpStatus = HttpStatus.OK; + return new ResponseEntity(response, httpStatus); + } + + // ##--isTransfer 처리-## + int balance = 0; + if("N".equals(siteApiInfo.get("isTransfer").toString())) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + JSONObject member = new JSONObject(); + member.put("userId", memberId); + long startTimestamp = System.currentTimeMillis(); + JSONObject resData = callBackService.getBalance(siteApiInfo, member); + if(resData == null) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("BALANCE_CALLBACK_ERROR"); + httpStatus = HttpStatus.OK; + return new ResponseEntity(response, httpStatus); + } + long endTimestamp = System.currentTimeMillis(); + double diffTime = (startTimestamp - endTimestamp)/1000.0; //두 시간에 차 계산 + if(diffTime < -1.5) { + log.error(LOG_PREFIX+ "잔액요청 응답시간("+diffTime+"초) 초과"); + } + log.info(LOG_PREFIX + "resData::"+resData.toString()); + balance = resData.getInt("balance"); + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + balance = siteService.getUserBalance(balanceMap); + + if(siteApiInfo.get("siteCbUrl") != null && !"".equals(siteApiInfo.get("siteCbUrl").toString())) { + JSONObject member = new JSONObject(); + member.put("userId", memberId); + member.put("balance", balance); + asyncCallBackService.asyncBalance(LOG_PREFIX, siteApiInfo, member); + } + } + + NexusBalanceData data = new NexusBalanceData(); + data.setBalance(balance); + data.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(data); + httpStatus = HttpStatus.OK; + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + response = new NexusResponse(); + response.setCode(-999); + response.setMsg("TIMEOUT_ERROR"); + httpStatus = HttpStatus.OK; + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + response = new NexusResponse(); + response.setCode(-999); + response.setMsg("BALANCE_SERVER_ERROR"); + httpStatus = HttpStatus.OK; + } + + ResponseEntity res = new ResponseEntity(response, httpStatus); + log.info(LOG_PREFIX+ "Response::" + response.toString()); + + return res; + } + + + @ResponseBody + @RequestMapping(path = "/callBet") + public ResponseEntity callBet(HttpServletRequest request, @RequestBody NexusSmlRequest requestBody) throws Exception { + NexusResponse response = null; + HttpStatus httpStatus = null; + + String apiKey = requestBody.getApiKey(); + NexusSmlData data = requestBody.getParams(); + String siteUsername = data.getSiteUsername(); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + String betDateTimeStr = data.getCreatedAt(); + if(betDateTimeStr == null || betDateTimeStr.equals("")) { + betDateTimeStr = sdf.format(System.currentTimeMillis()); + } else { + betDateTimeStr = betDateTimeStr.replace("T", " ").replace("Z", ""); + betDateTimeStr = makeEdate(betDateTimeStr, 32400000); + } + data.setBetDateTime(betDateTimeStr); + + if(siteUsername == null || siteUsername.equals("") || siteUsername.equals("invalid-user")) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("존재하지 않는 회원입니다"); + httpStatus = HttpStatus.OK; + return new ResponseEntity(response, httpStatus); + } + + long siteIdx = Long.parseLong(siteUsername.substring(0, 3), 16); + String memberId = siteUsername.substring(3, siteUsername.length()); + final String LOG_PREFIX = "#-CB::ACE::"+memberId+"::"+data.getTransactionKey()+"::callBet:::"; + log.info(LOG_PREFIX+ "Request::" + requestBody.toString()); + + try { + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "ace2"); + sParam.put("vendorGameCode", data.getVendorKey()); + log.info(LOG_PREFIX + "getSiteVendorInfo::"+sParam.toString()); + HashMap siteVendorInfo = siteService.getSiteVendorInfo(sParam); + if(siteVendorInfo == null) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("존재하지 않는 회원입니다"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "존재하지 않는 회원입니다::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + if(!apiKey.equals(siteVendorInfo.get("vendorApiKey").toString())) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("API키가 일치하지 않습니다"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "API키가 일치하지 않습니다::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + // ##--isTransfer 처리-## + final String IS_TRANSFER = siteVendorInfo.get("isTransfer").toString(); + + // vendors_info.useYn 게임막기 기능 + if("N".equals(siteVendorInfo.get("vendorAllUseYn").toString())) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("사용불가 벤더사"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "사용불가 벤더사::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + if(siteVendorInfo.get("lastInVendorIdx")==null || "0".equals(siteVendorInfo.get("lastInVendorIdx").toString())) { + HashMap memParam = new HashMap<>(); + memParam.put("siteIdx", siteIdx); + memParam.put("memberIdx", memberIdx); + memParam.put("lastInVendorIdx", Integer.parseInt(siteVendorInfo.get("vendorIdx").toString())); + int updResult = siteService.updMemLastVendorIdx(memParam); + } else { + Long lastInVendorIdx = Long.parseLong(siteVendorInfo.get("lastInVendorIdx").toString()); + Long vendorIdx = Long.parseLong(siteVendorInfo.get("vendorIdx").toString()); + if(lastInVendorIdx.longValue() != vendorIdx.longValue()) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("VendorIdx doesn't match"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "VendorIdx doesn't match::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + } + + Double amountD = Double.parseDouble(data.getAmount()); + int amount = Math.abs(amountD.intValue()); + long siteCredit = Long.parseLong(siteVendorInfo.get("credit").toString()); + // ##--isTransfer 처리-## + if(siteCredit < amount && IS_TRANSFER.equals("N")) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("NO_SITE_CREDIT"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "NO_SITE_CREDIT::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + if(amount < 0) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("금액이 올바르지 않습니다"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "금액이 올바르지 않습니다::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + long siteMaxBet = Long.parseLong(siteVendorInfo.get("siteMaxBet").toString()); + long userMaxBet = 0; + if(siteVendorInfo.get("userMaxBet") != null && !siteVendorInfo.get("userMaxBet").toString().isEmpty()) { + try { + userMaxBet = Long.parseLong(siteVendorInfo.get("userMaxBet").toString()); + } catch (NumberFormatException e) { + userMaxBet = 0; + } + } + + // 최종 maxBet 결정: userMaxBet이 0이면 siteMaxBet 사용, 0이 아니면 userMaxBet 사용 + long finalMaxBet = (userMaxBet > 0) ? userMaxBet : siteMaxBet; + log.info(LOG_PREFIX+ "MaxBet Info - siteMaxBet: " + siteMaxBet + ", userMaxBet: " + userMaxBet + ", finalMaxBet: " + finalMaxBet); + + if(finalMaxBet < amount) { + log.error(LOG_PREFIX+ "MAX_BET_AMOUNT_OVER"); + log.error(LOG_PREFIX+ "finalMaxBet : " + finalMaxBet +", amount : " + amount); + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("MAX_BET_AMOUNT_OVER"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "MAX_BET_AMOUNT_OVER::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + String vendorTranKey = data.getTransactionKey(); + String tranId = data.getTransactionKey(); + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("Y")) { + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(tranId); + if(cntTr > 0) { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(balance); + balanceData.setBeforeBalance(balance + amount); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "중복요청::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + } + + String betId = data.getParentTransactionKey(); + if(betId == null || betId.equals("")) { + betId = data.getTransactionKey(); + } + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + + String gameName = data.getGameName(); + String gameType = data.getGameType().replaceAll(" ", "").toLowerCase(); + if(data.getGameId() == null) data.setGameId(""); + String gameId = data.getGameId().replaceAll(" ", "").toLowerCase(); + String banGameType = siteVendorInfo.get("banGameType").toString().replaceAll(" ", "").toLowerCase(); + String banGameId = siteVendorInfo.get("banGameId").toString().replaceAll(" ", "").toLowerCase(); + + if(!"".equals(gameType) && !"".equals(banGameType) && banGameType.contains(gameType+"|")) { + // Ban Game Type Exception + HashMap logParam = new HashMap(); + logParam.put("siteIdx", siteIdx); + logParam.put("memberIdx", memberIdx); + logParam.put("vendorIdx", vendorIdx); + logParam.put("statusCode", 501L); + logParam.put("callBackType", "debit"); + logParam.put("tranId", tranId); + logParam.put("callBackReqBody", "gameType:"+gameType+"이 블락설정"); + logParam.put("callBackResBody", ""); + logParam.put("errorCode", "BLOCK_GAME_TYPE"); + logParam.put("errorMsg", "gameType:"+gameType+"이 블락설정"); + long startTimestamp = System.currentTimeMillis(); + logParam.put("regDate", startTimestamp); + logParam.put("updDate", startTimestamp); + callBackService.insertCallBackErrLog(logParam); + log.error(LOG_PREFIX+ "Ban Game Type : " + gameType); + + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("Ban Game Type : " + gameType); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "VendorIdx doesn't match::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + if(!"".equals(gameId) && !"".equals(banGameId) && banGameId.contains(gameId+"|")) { + // Ban Game Id Exception + HashMap logParam = new HashMap(); + logParam.put("siteIdx", siteIdx); + logParam.put("memberIdx", memberIdx); + logParam.put("vendorIdx", vendorIdx); + logParam.put("statusCode", 502L); + logParam.put("callBackType", "debit"); + logParam.put("tranId", tranId); + logParam.put("callBackReqBody", "gameId:"+gameId+"("+gameName+")이 블락설정"); + logParam.put("callBackResBody", ""); + logParam.put("errorCode", "BLOCK_GAME_ID"); + logParam.put("errorMsg", "gameId:"+gameId+"("+gameName+")이 블락설정"); + long startTimestamp = System.currentTimeMillis(); + logParam.put("regDate", startTimestamp); + logParam.put("updDate", startTimestamp); + callBackService.insertCallBackErrLog(logParam); + log.error(LOG_PREFIX+ "Ban Game Id : " + gameId); + + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("Ban Game Id : " + gameId); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "VendorIdx doesn't match::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "ace2"); + tranParam.put("vendorTranKey", vendorTranKey); + tranParam.put("gameType", data.getGameType()); + tranParam.put("gameId", data.getGameId()); + tranParam.put("gameIdx", data.getGameName()); + tranParam.put("tranType", "debit"); + tranParam.put("depositAmt", amount); + tranParam.put("creditAmt", "0"); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "ace2"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", data.getGameName()); + + if(data.getGameId() == null) data.setGameId(""); + callBackObj.put("gameId", data.getGameId()); + callBackObj.put("gameType", data.getGameType()); + + callBackObj.put("tranType", "debit"); + callBackObj.put("debit", amount); + callBackObj.put("credit", 0); + callBackObj.put("isCancel", 0); + if(data.getIsBonus().equals("true")) { + callBackObj.put("isBonus", 1); + } else { + callBackObj.put("isBonus", 0); + } + callBackObj.put("requestAt", betDateTimeStr); + log.info(LOG_PREFIX + "SEND_BET request body: " + callBackObj.toString()); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("N")) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + log.info(LOG_PREFIX + "-----INSERT_BET_START-----"); + long startTime = System.currentTimeMillis(); + siteService.commonBetinsert(tranParam); + long endTime = System.currentTimeMillis(); // 코드 실행 후에 시간 받아오기 + double diffTime = (startTime - endTime)/1000.0; //두 시간에 차 계산 + if(diffTime < -1.0) { + log.error(LOG_PREFIX + "commonBetinsert::배팅 쓰기지연::"+diffTime+"초 지연발생"); + response = new NexusResponse(); + response.setCode(-999); + response.setMsg("TIMEOUT_ERROR"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "TIMEOUT_ERROR::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + log.info(LOG_PREFIX + "-----INSERT_BET_END-----"); + + JSONObject resData = null; + if(data.getGameCategory().equals("casino")) { + resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } else { + resData = callBackService.changeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } + log.info(LOG_PREFIX + "SEND_BET status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_BET response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(balance); + balanceData.setBeforeBalance(balance + amount); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + } else if(resData.getLong("result_code") == 80) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("금액을 확인하여 주세요"); + httpStatus = HttpStatus.OK; + } else if(resData.getLong("result_code") == 98) { + int balance = resData.getInt("balance"); + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(balance); + balanceData.setBeforeBalance(balance + amount); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + } else { + response = new NexusResponse(); + response.setCode(-999); + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + response.setMsg(msg); + httpStatus = HttpStatus.OK; + } + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + int afBalance = balance - amount; + + if(balance < amount) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("금액을 확인하여 주세요"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + log.info(LOG_PREFIX + "-----INSERT_BET_START-----"); + long startTime = System.currentTimeMillis(); + siteService.commonBetinsert(tranParam); + long endTime = System.currentTimeMillis(); // 코드 실행 후에 시간 받아오기 + double diffTime = (startTime - endTime)/1000.0; //두 시간에 차 계산 + if(diffTime < -1.0) { + log.error(LOG_PREFIX + "commonBetinsert::배팅 쓰기지연::"+diffTime+"초 지연발생"); + response = new NexusResponse(); + response.setCode(-999); + response.setMsg("TIMEOUT_ERROR"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "TIMEOUT_ERROR::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + log.info(LOG_PREFIX + "-----INSERT_BET_END-----"); + + tranParam.put("balance", afBalance); + tranParam.put("preBalance", balance); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(afBalance); + balanceData.setBeforeBalance(balance); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + + if(siteVendorInfo.get("siteCbUrl") != null && !"".equals(siteVendorInfo.get("siteCbUrl").toString())) { + callBackObj.put("balance", afBalance); + if(data.getGameCategory().equals("casino")) { + asyncCallBackService.asyncChangeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } else { + asyncCallBackService.asyncChangeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } + } + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + response = new NexusResponse(); + response.setCode(-999); + response.setMsg("TIMEOUT_ERROR"); + httpStatus = HttpStatus.OK; + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + response = new NexusResponse(); + response.setCode(-999); + response.setMsg("BET_SERVER_ERROR"); + httpStatus = HttpStatus.OK; + } + + ResponseEntity res = new ResponseEntity(response, httpStatus); + log.info(LOG_PREFIX+ "Response::" + response.toString()); + + return res; + } + + + @ResponseBody + @RequestMapping(path = "/callResult") + public ResponseEntity callResult(HttpServletRequest request, @RequestBody NexusSmlRequest requestBody) throws Exception { + NexusResponse response = null; + HttpStatus httpStatus = null; + + String apiKey = requestBody.getApiKey(); + NexusSmlData data = requestBody.getParams(); + String siteUsername = data.getSiteUsername(); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + String betDateTimeStr = data.getCreatedAt(); + if(betDateTimeStr == null || betDateTimeStr.equals("")) { + betDateTimeStr = sdf.format(System.currentTimeMillis()); + } else { + betDateTimeStr = betDateTimeStr.replace("T", " ").replace("Z", ""); + betDateTimeStr = makeEdate(betDateTimeStr, 32400000); + } + data.setBetDateTime(betDateTimeStr); + + if(siteUsername == null || siteUsername.equals("") || siteUsername.equals("invalid-user")) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("존재하지 않는 회원입니다"); + httpStatus = HttpStatus.OK; + return new ResponseEntity(response, httpStatus); + } + + long siteIdx = Long.parseLong(siteUsername.substring(0, 3), 16); + String memberId = siteUsername.substring(3, siteUsername.length()); + final String LOG_PREFIX = "#-CB::ACE::"+memberId+"::"+data.getTransactionKey()+"::callResult:::"; + log.info(LOG_PREFIX+ "Request::" + requestBody.toString()); + + if(data.getType().equals("turn_promotion")) { + data.setVendorKey("pragmaticplay_casino"); + } + + try { + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "ace2"); + sParam.put("vendorGameCode", data.getVendorKey()); + log.info(LOG_PREFIX + "getSiteVendorInfo::"+sParam.toString()); + HashMap siteVendorInfo = siteService.getSiteVendorInfo(sParam); + if(siteVendorInfo == null) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("존재하지 않는 회원입니다"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "존재하지 않는 회원입니다::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + if(!apiKey.equals(siteVendorInfo.get("vendorApiKey").toString())) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("API키가 일치하지 않습니다"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "API키가 일치하지 않습니다::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + // ##--isTransfer 처리-## + final String IS_TRANSFER = siteVendorInfo.get("isTransfer").toString(); + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + Double amountD = Double.parseDouble(data.getAmount()); + int amount = Math.abs(amountD.intValue()); + if(amount < 0) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("금액이 올바르지 않습니다"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "금액이 올바르지 않습니다::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + String vendorTranKey = data.getTransactionKey(); + String tranId = data.getTransactionKey(); + String betId = data.getParentTransactionKey(); + if(betId == null || betId.equals("")) { + betId = data.getTransactionKey(); + } + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("Y")) { + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(tranId); + if(cntTr > 0) { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(balance); + balanceData.setBeforeBalance(balance + amount); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "중복요청::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + // 베팅 체크 + int cntBet = siteService.getBetIdCheck2(betId); + if(cntBet == 0) { + response = new NexusResponse(); + response.setCode(-999); + response.setMsg("NOT_FOUND_REF_DATA"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "NOT_FOUND_REF_DATA::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + } + + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + String gameName = data.getGameName(); + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "ace2"); + tranParam.put("vendorTranKey", vendorTranKey); + tranParam.put("gameType", data.getGameType()); + tranParam.put("gameId", data.getGameId()); + tranParam.put("gameIdx", gameName); + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "ace2"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", gameName); + if(data.getGameId() == null) data.setGameId(""); + callBackObj.put("gameId", data.getGameId()); + callBackObj.put("gameType", data.getGameType()); + callBackObj.put("tranType", "credit"); + callBackObj.put("debit", 0); + callBackObj.put("credit", amount); + callBackObj.put("isCancel", 0); + if(data.getIsBonus().equals("true") || data.getIsPromo().equals("true") || data.getType().equals("turn_promotion")) { + callBackObj.put("isBonus", 1); + } else { + callBackObj.put("isBonus", 0); + } + callBackObj.put("requestAt", betDateTimeStr); + log.info(LOG_PREFIX + "SEND_RESULT request body: " + callBackObj.toString()); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("N")) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + log.info(LOG_PREFIX + "-----INSERT_RESULT_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_RESULT_END-----"); + + JSONObject resData = null; + if(data.getGameCategory().equals("casino")) { + resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } else { + resData = callBackService.changeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } + log.info(LOG_PREFIX + "SEND_RESULT status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_RESULT response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(balance); + balanceData.setBeforeBalance(balance - amount); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + } else if(resData.getLong("result_code") == 98) { + int balance = resData.getInt("balance"); + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(balance); + balanceData.setBeforeBalance(balance - amount); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + } else { + response = new NexusResponse(); + response.setCode(-999); + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + response.setMsg(msg); + httpStatus = HttpStatus.OK; + } + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + int afBalance = balance + amount; + + log.info(LOG_PREFIX + "-----INSERT_RESULT_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_RESULT_END-----"); + + tranParam.put("balance", afBalance); + tranParam.put("preBalance", balance); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(afBalance); + balanceData.setBeforeBalance(balance); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + + if(siteVendorInfo.get("siteCbUrl") != null && !"".equals(siteVendorInfo.get("siteCbUrl").toString())) { + callBackObj.put("balance", afBalance); + if(data.getGameCategory().equals("casino")) { + asyncCallBackService.asyncChangeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } else { + asyncCallBackService.asyncChangeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } + } + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + response = new NexusResponse(); + response.setCode(-999); + response.setMsg("TIMEOUT_ERROR"); + httpStatus = HttpStatus.OK; + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + response = new NexusResponse(); + response.setCode(-999); + response.setMsg("RESULT_SERVER_ERROR"); + httpStatus = HttpStatus.OK; + } + + ResponseEntity res = new ResponseEntity(response, httpStatus); + log.info(LOG_PREFIX+ "Response::" + response.toString()); + + return res; + } + + + @ResponseBody + @RequestMapping(path = "/callCancel") + public ResponseEntity callCancel(HttpServletRequest request, @RequestBody NexusSmlRequest requestBody) throws Exception { + NexusResponse response = null; + HttpStatus httpStatus = null; + + String apiKey = requestBody.getApiKey(); + NexusSmlData data = requestBody.getParams(); + String siteUsername = data.getSiteUsername(); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + String betDateTimeStr = data.getCreatedAt(); + if(betDateTimeStr == null || betDateTimeStr.equals("")) { + betDateTimeStr = sdf.format(System.currentTimeMillis()); + } else { + betDateTimeStr = betDateTimeStr.replace("T", " ").replace("Z", ""); + betDateTimeStr = makeEdate(betDateTimeStr, 32400000); + } + data.setBetDateTime(betDateTimeStr); + + if(siteUsername == null || siteUsername.equals("") || siteUsername.equals("invalid-user")) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("존재하지 않는 회원입니다"); + httpStatus = HttpStatus.OK; + return new ResponseEntity(response, httpStatus); + } + + long siteIdx = Long.parseLong(siteUsername.substring(0, 3), 16); + String memberId = siteUsername.substring(3, siteUsername.length()); + final String LOG_PREFIX = "#-CB::ACE::"+memberId+"::"+data.getTransactionKey()+"::callCancel:::"; + log.info(LOG_PREFIX+ "Request::" + requestBody.toString()); + + try { + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "ace2"); + sParam.put("vendorGameCode", data.getVendorKey()); + log.info(LOG_PREFIX + "getSiteVendorInfo::"+sParam.toString()); + HashMap siteVendorInfo = siteService.getSiteVendorInfo(sParam); + if(siteVendorInfo == null) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("존재하지 않는 회원입니다"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "존재하지 않는 회원입니다::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + if(!apiKey.equals(siteVendorInfo.get("vendorApiKey").toString())) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("API키가 일치하지 않습니다"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "API키가 일치하지 않습니다::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + // ##--isTransfer 처리-## + final String IS_TRANSFER = siteVendorInfo.get("isTransfer").toString(); + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + Double amountD = Double.parseDouble(data.getAmount()); + int amount = Math.abs(amountD.intValue()); + if(amount < 0) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("금액이 올바르지 않습니다"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "금액이 올바르지 않습니다::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + String vendorTranKey = data.getTransactionKey(); + String tranId = data.getTransactionKey(); + String betId = data.getParentTransactionKey(); + if(betId == null || betId.equals("")) { + betId = data.getTransactionKey(); + } + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("Y")) { + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(tranId); + if(cntTr > 0) { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(balance); + balanceData.setBeforeBalance(balance + amount); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "중복요청::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + // 베팅 체크 + int cntBet = siteService.getBetIdCheck2(betId); + if(cntBet == 0) { + response = new NexusResponse(); + response.setCode(-999); + response.setMsg("NOT_FOUND_REF_DATA"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "NOT_FOUND_REF_DATA::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + } + + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + String gameName = data.getGameName(); + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "ace2"); + tranParam.put("vendorTranKey", vendorTranKey); + tranParam.put("gameType", data.getGameType()); + tranParam.put("gameId", data.getGameId()); + tranParam.put("gameIdx", gameName); + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + tranParam.put("isCancel", "Y"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "ace2"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", gameName); + if(data.getGameId() == null) data.setGameId(""); + callBackObj.put("gameId", data.getGameId()); + callBackObj.put("gameType", data.getGameType()); + callBackObj.put("tranType", "credit"); + callBackObj.put("debit", 0); + callBackObj.put("credit", amount); + callBackObj.put("isCancel", 1); + callBackObj.put("isBonus", 0); + callBackObj.put("requestAt", betDateTimeStr); + log.info(LOG_PREFIX + "SEND_CANCEL request body: " + callBackObj.toString()); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("N")) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + log.info(LOG_PREFIX + "-----INSERT_CANCEL_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_CANCEL_END-----"); + + JSONObject resData = null; + if(data.getGameCategory().equals("casino")) { + resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } else { + resData = callBackService.changeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } + log.info(LOG_PREFIX + "SEND_CANCEL status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_CANCEL response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(balance); + balanceData.setBeforeBalance(balance - amount); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + } else if(resData.getLong("result_code") == 98) { + int balance = resData.getInt("balance"); + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(balance); + balanceData.setBeforeBalance(balance - amount); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + } else { + response = new NexusResponse(); + response.setCode(-999); + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + response.setMsg(msg); + httpStatus = HttpStatus.OK; + } + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + int afBalance = balance + amount; + + log.info(LOG_PREFIX + "-----INSERT_CANCEL_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_CANCEL_END-----"); + + tranParam.put("balance", afBalance); + tranParam.put("preBalance", balance); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(afBalance); + balanceData.setBeforeBalance(balance); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + + if(siteVendorInfo.get("siteCbUrl") != null && !"".equals(siteVendorInfo.get("siteCbUrl").toString())) { + callBackObj.put("balance", afBalance); + if(data.getGameCategory().equals("casino")) { + asyncCallBackService.asyncChangeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } else { + asyncCallBackService.asyncChangeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } + } + } + + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + response = new NexusResponse(); + response.setCode(-999); + response.setMsg("TIMEOUT_ERROR"); + httpStatus = HttpStatus.OK; + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + response = new NexusResponse(); + response.setCode(-999); + response.setMsg("RESULT_SERVER_ERROR"); + httpStatus = HttpStatus.OK; + } + + ResponseEntity res = new ResponseEntity(response, httpStatus); + log.info(LOG_PREFIX+ "Response::" + response.toString()); + + return res; + } + + + @ResponseBody + @RequestMapping(path = "/callAdjust") + public ResponseEntity callAdjust(HttpServletRequest request, @RequestBody NexusSmlRequest requestBody) throws Exception { + NexusResponse response = null; + HttpStatus httpStatus = null; + + String apiKey = requestBody.getApiKey(); + NexusSmlData data = requestBody.getParams(); + String siteUsername = data.getSiteUsername(); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + String betDateTimeStr = data.getCreatedAt(); + if(betDateTimeStr == null || betDateTimeStr.equals("")) { + betDateTimeStr = sdf.format(System.currentTimeMillis()); + } else { + betDateTimeStr = betDateTimeStr.replace("T", " ").replace("Z", ""); + betDateTimeStr = makeEdate(betDateTimeStr, 32400000); + } + data.setBetDateTime(betDateTimeStr); + + if(siteUsername == null || siteUsername.equals("") || siteUsername.equals("invalid-user")) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("존재하지 않는 회원입니다"); + httpStatus = HttpStatus.OK; + return new ResponseEntity(response, httpStatus); + } + + long siteIdx = Long.parseLong(siteUsername.substring(0, 3), 16); + String memberId = siteUsername.substring(3, siteUsername.length()); + final String LOG_PREFIX = "#-CB::ACE::"+memberId+"::"+data.getTransactionKey()+"::callAdjust:::"; + log.info(LOG_PREFIX+ "Request::" + requestBody.toString()); + + try { + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "ace2"); + sParam.put("vendorGameCode", data.getVendorKey()); + log.info(LOG_PREFIX + "getSiteVendorInfo::"+sParam.toString()); + HashMap siteVendorInfo = siteService.getSiteVendorInfo(sParam); + if(siteVendorInfo == null) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("존재하지 않는 회원입니다"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "존재하지 않는 회원입니다::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + if(!apiKey.equals(siteVendorInfo.get("vendorApiKey").toString())) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("API키가 일치하지 않습니다"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "API키가 일치하지 않습니다::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + // ##--isTransfer 처리-## + final String IS_TRANSFER = siteVendorInfo.get("isTransfer").toString(); + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + Double amountD = Double.parseDouble(data.getAmount()); + int amount = amountD.intValue(); + + String vendorTranKey = data.getTransactionKey(); + String tranId = data.getTransactionKey(); + String betId = data.getParentTransactionKey(); + if(betId == null || betId.equals("")) { + betId = data.getTransactionKey(); + } + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("Y")) { + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(tranId); + if(cntTr > 0) { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(balance); + balanceData.setBeforeBalance(balance + amount); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "중복요청::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + // 베팅 체크 + int cntBet = siteService.getBetIdCheck2(betId); + if(cntBet == 0) { + response = new NexusResponse(); + response.setCode(-999); + response.setMsg("NOT_FOUND_REF_DATA"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "NOT_FOUND_REF_DATA::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + } + + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + String gameName = data.getGameName(); + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "ace2"); + tranParam.put("vendorTranKey", vendorTranKey); + tranParam.put("gameType", data.getGameType()); + tranParam.put("gameId", data.getGameId()); + tranParam.put("gameIdx", gameName); + if(amount >= 0) { + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + } else { + tranParam.put("tranType", "debit"); + tranParam.put("depositAmt", amount*-1); + tranParam.put("creditAmt", "0"); + } + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "ace2"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", gameName); + if(data.getGameId() == null) data.setGameId(""); + callBackObj.put("gameId", data.getGameId()); + callBackObj.put("gameType", data.getGameType()); + callBackObj.put("tranType", "adjust"); + if(amount >= 0) { + callBackObj.put("debit", 0); + callBackObj.put("credit", amount); + } else { + callBackObj.put("debit", amount*-1); + callBackObj.put("credit", 0); + } + callBackObj.put("isCancel", 0); + callBackObj.put("isBonus", 0); + callBackObj.put("requestAt", betDateTimeStr); + log.info(LOG_PREFIX + "SEND_ADJUST request body: " + callBackObj.toString()); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("N")) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + log.info(LOG_PREFIX + "-----INSERT_ADJUST_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_ADJUST_END-----"); + + JSONObject resData = null; + if(data.getGameCategory().equals("casino")) { + resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } else { + resData = callBackService.changeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } + log.info(LOG_PREFIX + "SEND_ADJUST status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_ADJUST response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(balance); + balanceData.setBeforeBalance(balance + amount); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + } else if(resData.getLong("result_code") == 98) { + int balance = resData.getInt("balance"); + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(balance); + balanceData.setBeforeBalance(balance + amount); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + } else { + response = new NexusResponse(); + response.setCode(-999); + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + response.setMsg(msg); + httpStatus = HttpStatus.OK; + } + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + int afBalance = balance + amount; + + log.info(LOG_PREFIX + "-----INSERT_ADJUST_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_ADJUST_END-----"); + + tranParam.put("balance", afBalance); + tranParam.put("preBalance", balance); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(afBalance); + balanceData.setBeforeBalance(balance); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + + if(siteVendorInfo.get("siteCbUrl") != null && !"".equals(siteVendorInfo.get("siteCbUrl").toString())) { + callBackObj.put("balance", afBalance); + if(data.getGameCategory().equals("casino")) { + asyncCallBackService.asyncChangeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } else { + asyncCallBackService.asyncChangeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } + } + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + response = new NexusResponse(); + response.setCode(-999); + response.setMsg("TIMEOUT_ERROR"); + httpStatus = HttpStatus.OK; + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + response = new NexusResponse(); + response.setCode(-999); + response.setMsg("RESULT_SERVER_ERROR"); + httpStatus = HttpStatus.OK; + } + + ResponseEntity res = new ResponseEntity(response, httpStatus); + log.info(LOG_PREFIX+ "Response::" + response.toString()); + + return res; + } + + + /** + * 에볼루션 상세 콜백 + * @param request + * @param requestBody + * @return + * @throws Exception + */ + @ResponseBody + @RequestMapping(path = "/callDetail") + public ResponseEntity callDetail(HttpServletRequest request, @RequestBody net.sf.json.JSONObject requestBody) throws Exception { + NexusResponse response = null; + HttpStatus httpStatus = null; + + String apiKey = requestBody.getString("apiKey"); + final String LOG_PREFIX = "#-CB::ACE::callDetail::"+apiKey+":::"; + // log.info(LOG_PREFIX+ "Request::" + requestBody.toString()); + + try { + JSONObject bodyObj = new JSONObject(requestBody.toString()); + JSONArray params = bodyObj.getJSONArray("params"); + String prevRefId = ""; + for(int i=0; i(); + detailMap.put("refId", refId); + detailMap.put("orgDetail", orgDetail.toString()); + detailMap.put("parDetail", null); + try { + int result = siteService.insertEvoDetail(detailMap); + log.info(LOG_PREFIX2+ "insertEvoDetail result::" + result); + } catch(DataIntegrityViolationException de) { + log.error(LOG_PREFIX2+ "Duplicate refId"); + continue; + } + + } + + + response = new NexusResponse(); + response.setCode(0); + response.setMsg("SUCCESS"); + httpStatus = HttpStatus.OK; + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + response = new NexusResponse(); + response.setCode(-8); + response.setMsg("TIMEOUT_ERROR"); + httpStatus = HttpStatus.OK; + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + response = new NexusResponse(); + response.setCode(-9); + response.setMsg("DETAIL_SERVER_ERROR"); + httpStatus = HttpStatus.OK; + } + + ResponseEntity res = new ResponseEntity(response, httpStatus); + log.info(LOG_PREFIX+ "Response::" + response.toString()); + + return res; + } + + + /** + * UTC 시간을 한국 시간(KST)으로 변환 + * @param utcTimeStr UTC 시간 문자열 (예: 2026-02-06T04:39:05.243Z) + * @return 한국 시간 문자열 (예: 2026-02-06T13:39:05.243+09:00) + */ + private static String convertUtcToKstTime(String utcTimeStr) { + try { + if (utcTimeStr == null || !utcTimeStr.endsWith("Z")) { + return utcTimeStr; + } + + // UTC 시간 파싱 + Instant instant = Instant.parse(utcTimeStr); + // 한국 시간대로 변환 (UTC+9) + ZonedDateTime kstTime = instant.atZone(ZoneId.of("Asia/Seoul")); + // ISO 8601 형식으로 포맷 (타임존 포함) + return kstTime.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME); + } catch (Exception e) { + log.error("UTC to KST conversion error: " + e.getMessage()); + return utcTimeStr; // 변환 실패시 원본 반환 + } + } + + /** + * JSON 객체를 재귀적으로 순회하며 시간 필드를 UTC에서 KST로 변환 + * @param jsonObj 변환할 JSON 객체 + */ + private static void convertUtcToKst(JSONObject jsonObj) { + try { + // 변환할 시간 필드 목록 + String[] timeFields = {"startedAt", "settledAt", "placedOn", "recordedAt"}; + + Iterator keys = jsonObj.keys(); + while (keys.hasNext()) { + String key = keys.next(); + Object value = jsonObj.get(key); + + // 시간 필드인 경우 변환 + for (String timeField : timeFields) { + if (key.equals(timeField) && value instanceof String) { + String utcTime = (String) value; + String kstTime = convertUtcToKstTime(utcTime); + jsonObj.put(key, kstTime); + break; + } + } + + // 중첩된 JSONObject인 경우 재귀 호출 + if (value instanceof JSONObject) { + convertUtcToKst((JSONObject) value); + } + // 중첩된 JSONArray인 경우 각 요소 처리 + else if (value instanceof JSONArray) { + JSONArray jsonArray = (JSONArray) value; + for (int i = 0; i < jsonArray.length(); i++) { + Object arrayItem = jsonArray.get(i); + if (arrayItem instanceof JSONObject) { + convertUtcToKst((JSONObject) arrayItem); + } + } + } + } + } catch (Exception e) { + log.error("JSON time conversion error: " + e.getMessage()); + } + } + + private static String makeDateStrForUTC(boolean flag, String strDate) { + String result = ""; + if(flag) { + // 2022-05-01 00:00:00.000 => 2022-05-01T00:00:00.000Z + result = strDate.replace(" ", "T") + "Z"; + } else { + // 2022-05-01T00:00:00.000Z => 2022-05-01 00:00:00.000 + result = strDate.replace("T", " ").replace("Z", ""); + } + return result; + } + + private static String makeEdate(String paramDate, int flag) { + // TODO Auto-generated method stub + String eDate = ""; + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + try { + if(paramDate == null) { + // eDate = sdf.format(System.currentTimeMillis()); + eDate = sdf.format(System.currentTimeMillis() - 32400000); + } else { + Date date = sdf.parse(paramDate); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + calendar.add(Calendar.MILLISECOND, flag); + Date date2 = calendar.getTime(); + eDate = sdf.format(date2); + } + } catch(Exception e) { + log.error(e.getMessage()); + } + return eDate; + } +} diff --git a/src/main/java/com/bb/front/CallBackBetGambleController.java b/src/main/java/com/bb/front/CallBackBetGambleController.java new file mode 100644 index 0000000..a4a08fd --- /dev/null +++ b/src/main/java/com/bb/front/CallBackBetGambleController.java @@ -0,0 +1,964 @@ +package com.bb.front; + +import java.util.HashMap; +import java.util.Random; + +import jakarta.servlet.http.HttpServletRequest; + +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.WebClientRequestException; +import org.springframework.web.reactive.function.client.WebClientResponseException; + +import com.bb.jwt.JwtManager; +import com.bb.model.ApiResponse; +import com.bb.model.AuthParam; +import com.bb.model.CheckVo; +import com.bb.model.CommonParam; +import com.bb.model.EvoResponse; +import com.bb.model.EvolutionVo; +import com.bb.model.Member; +import com.bb.model.PlayParam; +import com.bb.service.SiteService; + +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@RestController +@Slf4j +@RequestMapping("/api/callback/evot") +@RequiredArgsConstructor +@SecurityRequirement(name = "Authorization") +public class CallBackBetGambleController { + + @Autowired + private final JwtManager jwtManager; + + @Autowired + SiteService siteService; + + @Autowired + WebClient webClient; + + + + @ResponseBody + @RequestMapping(value="/test") + public EvoResponse test(HttpServletRequest request, @RequestBody EvolutionVo evo) throws Exception { + EvoResponse evoResponse = new EvoResponse(); + try { + log.debug(evo.toString()); + + JSONObject member = new JSONObject(); + member.put("userId", "moka_gk01"); + + log.info("# site.getSiteCbUrl() : " + "https://dev-api.allboxstage.com/triple/balance"); + log.info("# site.getSiteCbUrl() : " + member.toString()); + + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/json"); + header.add("Accept", "application/json"); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + + ResponseEntity responseEntity = null; + try { + responseEntity = webClient.post() + .uri("https://dev-api.allboxstage.com/triple/balance") + .headers(h -> h.addAll(header)) + .bodyValue(member.toString()) + .retrieve() + .toEntity(String.class) + .block(); + } catch(WebClientResponseException e) { + log.error("test::HttpClientErrorException : " + e.getMessage()); + log.error("test::status code : " + e.getStatusCode().value()); + log.error("test::response body : " + e.getResponseBodyAsString()); + evoResponse.fail(); + return evoResponse; + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) { + log.error("test::ConnectTimeoutException::" + rae.getMessage()); + } + if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error("test::SocketTimeoutException::" + rae.getMessage()); + } + if(rae.getCause() instanceof InterruptedException) { + log.error("test::InterruptedException::" + rae.getMessage()); + } + log.error("test::WebClientRequestException : " + rae.getMessage()); + evoResponse.fail(); + return evoResponse; + } + + if(responseEntity != null && responseEntity.getStatusCode() == HttpStatus.OK) { + log.info("status code : {}", responseEntity.getStatusCode()); + log.info("body: {}", responseEntity.getBody()); + + JSONObject resData = new JSONObject(responseEntity.getBody()); + + if(resData.getInt("result_code") == 0) { + evoResponse.setUuid(evo.getUuid()); + evoResponse.setBalance( resData.getDouble("balance")); + evoResponse.setBonus(0.0); + evoResponse.success(); + }else { + evoResponse.setBalance( resData.getDouble("balance")); + evoResponse.fail(); + } + } else { + log.error("test::Unexpected response status code"); + evoResponse.fail(); + } + + + } catch (Exception e) { + log.info(e.toString()); + e.printStackTrace(); + evoResponse.fail(); + } + + return evoResponse; + } + + + @ResponseBody + @RequestMapping(value="/") + public ApiResponse main(HttpServletRequest request, @RequestBody CheckVo check) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + try { + + + + apiResponse.success(); + + } catch (Exception e) { + log.info(e.toString()); + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + @ResponseBody + @RequestMapping(value={"/sid"}) + public EvoResponse sid(HttpServletRequest request, @RequestBody CheckVo check) throws Exception { + EvoResponse evoResponse = new EvoResponse(); + System.out.print("sid CHECK " + check.toString()); + try { + + + + + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx",Integer.parseInt(check.getUserId().substring(0, 3), 16)); + sParam.put("memberId", check.getUserId().substring(3, check.getUserId().length())); + String memberId =check.getUserId().substring(3, check.getUserId().length()); + + HashMap siteApiInfo = siteService.getSiteApiInfo(sParam); + + AuthParam param = new AuthParam(); + param.setBalance(0); + param.setUserId(memberId); + param.setNickName(check.getUserId()); + + CommonParam commonParam = new CommonParam(); + commonParam.setSiteIdx(Integer.parseInt(siteApiInfo.get("siteIdx").toString())); + commonParam.setAuthParam(param); + + System.out.print("CHECK " + check.toString()); + + Member member = siteService.getMember(commonParam); + + if(member == null) { + siteService.insertMember(commonParam); + member = siteService.getMember(commonParam); + } + + String sid = makeApiKey(""); + member.setLastSid(sid); + siteService.updateSid(member); + evoResponse.setSid(sid); + evoResponse.setUuid(check.getUuid()); + evoResponse.success(); + + } catch (Exception e) { + log.info(e.toString()); + e.printStackTrace(); + evoResponse.fail(); + } + + return evoResponse; + } + + @ResponseBody + @RequestMapping(value={"/check"}) + public EvoResponse check(HttpServletRequest request, @RequestBody CheckVo check) throws Exception { + EvoResponse evoResponse = new EvoResponse(); + try { + System.out.print("check CHECK " + check.toString()); + + evoResponse.setSid(check.getSid()); + evoResponse.setUuid(check.getUuid()); + + + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx",Integer.parseInt(check.getUserId().substring(0, 3), 16)); + sParam.put("memberId", check.getUserId().substring(3, check.getUserId().length())); + String memberId =check.getUserId().substring(3, check.getUserId().length()); + + + HashMap siteApiInfo = siteService.getSiteApiInfo(sParam); + + AuthParam param = new AuthParam(); + param.setBalance(0); + param.setUserId(memberId); + param.setNickName(check.getUserId()); + + CommonParam commonParam = new CommonParam(); + commonParam.setSiteIdx(Integer.parseInt(siteApiInfo.get("siteIdx").toString())); + commonParam.setAuthParam(param); + + System.out.print("CHECK " + check.toString()); + + Member member = siteService.getMember(commonParam); + + // 회원 없을경우 가입시키기 + + if(member == null) { + + System.out.print("CHECK INVALID_PARAMETER"); + + evoResponse.fail("INVALID_PARAMETER"); + return evoResponse; + } + + /* + if(!check.getSid().equals(member.getLastSid())) { + evoResponse.fail("INVALID_SID"); + return evoResponse; + } + */ + + evoResponse.success(); + + + } catch (Exception e) { + log.info(e.toString()); + e.printStackTrace(); + evoResponse.fail(); + } + + return evoResponse; + } + + + @ResponseBody + @RequestMapping(value="/balance") + public EvoResponse balance(HttpServletRequest request, @RequestBody EvolutionVo evo) throws Exception { + EvoResponse evoResponse = new EvoResponse(); + try { + log.debug(evo.toString()); + + //사이트정보 + HashMap sParam = new HashMap(); + + sParam.put("siteIdx",Integer.parseInt(evo.getUserId().substring(0, 3), 16)); + sParam.put("memberId", evo.getUserId().substring(3, evo.getUserId().length())); + String memberId =evo.getUserId().substring(3, evo.getUserId().length()); + /* + AuthParam param = new AuthParam(); + param.setBalance(0); + param.setUserId("moka_"+evo.getUserId()); + param.setNickName(evo.getUserId()); + + CommonParam commonParam = new CommonParam(); + commonParam.setSiteIdx(1); + commonParam.setAuthParam(param); + + Member memberS = siteService.getMember(commonParam); + if(!evo.getSid().equals(memberS.getLastSid())) { + evoResponse.fail("INVALID_SID"); + return evoResponse; + } + + */ + HashMap siteApiInfo = siteService.getSiteApiInfo(sParam); + + if(siteApiInfo==null) { + + evoResponse.setBalance(null); + evoResponse.fail(); + return evoResponse; + } + + JSONObject member = new JSONObject(); + member.put("userId", memberId); + + log.info("# site.getSiteCbUrl() : " + siteApiInfo.get("siteCbUrl")+"/balance"); + log.info("# site.getSiteCbUrl() : " + member.toString()); + + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/json"); + header.add("Accept", "application/json"); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + + ResponseEntity responseEntity = null; + try { + responseEntity = webClient.post() + .uri(siteApiInfo.get("siteCbUrl")+"/balance") + .headers(h -> h.addAll(header)) + .bodyValue(member.toString()) + .retrieve() + .toEntity(String.class) + .block(); + } catch(WebClientResponseException e) { + log.error("balance::HttpClientErrorException : " + e.getMessage()); + log.error("balance::status code : " + e.getStatusCode().value()); + log.error("balance::response body : " + e.getResponseBodyAsString()); + evoResponse.setBalance(null); + evoResponse.fail(); + return evoResponse; + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) { + log.error("balance::ConnectTimeoutException::" + rae.getMessage()); + } + if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error("balance::SocketTimeoutException::" + rae.getMessage()); + } + if(rae.getCause() instanceof InterruptedException) { + log.error("balance::InterruptedException::" + rae.getMessage()); + } + log.error("balance::WebClientRequestException : " + rae.getMessage()); + evoResponse.setBalance(null); + evoResponse.fail(); + return evoResponse; + } + + if(responseEntity != null && responseEntity.getStatusCode() == HttpStatus.OK) { + log.info("status code : {}", responseEntity.getStatusCode()); + log.info("body: {}", responseEntity.getBody()); + + JSONObject resData = new JSONObject(responseEntity.getBody()); + + if(resData.getInt("result_code") == 0) { + evoResponse.setUuid(evo.getUuid()); + evoResponse.setBalance( resData.getDouble("balance")); + evoResponse.setBonus(0.0); + evoResponse.success(); + }else { + evoResponse.setBalance( resData.getDouble("balance")); + evoResponse.fail(); + } + } else { + log.error("balance::Unexpected response status code"); + evoResponse.setBalance(null); + evoResponse.fail(); + } + + } catch (Exception e) { + log.info(e.toString()); + e.printStackTrace(); + evoResponse.fail(); + } + + return evoResponse; + } + + + @ResponseBody + @RequestMapping(value="/debit") + public EvoResponse debit (HttpServletRequest request, @RequestBody EvolutionVo evo) throws Exception { + EvoResponse evoResponse = new EvoResponse(); + + try { + log.debug(evo.toString()); + //사이트정보 + //사이트정보 + HashMap sParam = new HashMap(); + + sParam.put("siteIdx",Integer.parseInt(evo.getUserId().substring(0, 3), 16)); + sParam.put("memberId", evo.getUserId().substring(3, evo.getUserId().length())); + String memberId =evo.getUserId().substring(3, evo.getUserId().length()); + + + /* + AuthParam param = new AuthParam(); + param.setBalance(0); + param.setUserId("moka_"+evo.getUserId()); + param.setNickName(evo.getUserId()); + + CommonParam commonParam = new CommonParam(); + commonParam.setSiteIdx(1); + commonParam.setAuthParam(param); + + Member memberS = siteService.getMember(commonParam); + if(!evo.getSid().equals(memberS.getLastSid())) { + evoResponse.fail("INVALID_SID"); + return evoResponse; + } + */ + + HashMap siteApiInfo = siteService.getSiteApiInfo(sParam); + String siteId = siteApiInfo.get("siteId").toString(); + + if(siteApiInfo==null) { + + evoResponse.setBalance(null); + evoResponse.fail(); + return evoResponse; + } + + // 사이트에 크레딧이 없을경우 에러 보냄 베팅막음 + long targetSiteCredit = siteService.getSiteCredit(siteApiInfo.get("siteId").toString()); + if(targetSiteCredit < evo.getTransaction().getAmount() ) { + System.out.println("no siteCredit"); + evoResponse.setBalance(null); + evoResponse.fail("INSUFFICIENT_FUNDS2"); + return evoResponse; + } + + +//최대베팅액 (userMaxBet 우선 적용) + sParam.put("vendorIdx", 1); + long maxBet = siteService.getSiteMaxBet(sParam); + + // userMaxBet 조회 + long userMaxBet = 0; + Long userMaxBetObj = siteService.getUserMaxBet(sParam); + if(userMaxBetObj != null) { + userMaxBet = userMaxBetObj; + } + + // 최종 maxBet 결정: userMaxBet이 0이면 siteMaxBet 사용, 0이 아니면 userMaxBet 사용 + long finalMaxBet = (userMaxBet > 0) ? userMaxBet : maxBet; + System.out.println("MaxBet Info - siteMaxBet: " + maxBet + ", userMaxBet: " + userMaxBet + ", finalMaxBet: " + finalMaxBet); + + if(evo.getTransaction().getAmount() > finalMaxBet) { + System.out.println("Over bet money - finalMaxBet: " + finalMaxBet); + evoResponse.setBalance(null); + evoResponse.fail("INSUFFICIENT_FUNDS3"); + return evoResponse; + } + + + int fatErrCnt = siteService.getFinalErr(evo.getTransaction().getRefId()); + + if(fatErrCnt > 0) { + JSONObject member = new JSONObject(); + member.put("userId", memberId); + + HttpHeaders headerb = new HttpHeaders(); + headerb.add("Content-Type", "application/json"); + headerb.add("Accept", "application/json"); + + ResponseEntity responseEntityb = null; + try { + responseEntityb = webClient.post() + .uri(siteApiInfo.get("siteCbUrl")+"/balance") + .headers(h -> h.addAll(headerb)) + .bodyValue(member.toString()) + .retrieve() + .toEntity(String.class) + .block(); + } catch(WebClientResponseException e) { + log.error("debit(fatErrCnt)::HttpClientErrorException : " + e.getMessage()); + log.error("debit(fatErrCnt)::status code : " + e.getStatusCode().value()); + log.error("debit(fatErrCnt)::response body : " + e.getResponseBodyAsString()); + evoResponse.fail(); + return evoResponse; + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) { + log.error("debit(fatErrCnt)::ConnectTimeoutException::" + rae.getMessage()); + } + if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error("debit(fatErrCnt)::SocketTimeoutException::" + rae.getMessage()); + } + if(rae.getCause() instanceof InterruptedException) { + log.error("debit(fatErrCnt)::InterruptedException::" + rae.getMessage()); + } + log.error("debit(fatErrCnt)::WebClientRequestException : " + rae.getMessage()); + evoResponse.fail(); + return evoResponse; + } + + if(responseEntityb != null && responseEntityb.getStatusCode() == HttpStatus.OK) { + log.info("status code : {}", responseEntityb.getStatusCode()); + log.info("body: {}", responseEntityb.getBody()); + + JSONObject resDatab = new JSONObject(responseEntityb.getBody()); + + evoResponse.setBalance(resDatab.getDouble("balance")); + evoResponse.fail("FINAL_ERROR_ACTION_FAILED"); + return evoResponse; + } + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", siteId+evo.getTransaction().getId()); + tranParam.put("refId", siteId+evo.getTransaction().getRefId()); + tranParam.put("siteIdx", siteApiInfo.get("siteIdx")); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", siteApiInfo.get("memberIdx")); + tranParam.put("memberId", memberId); + tranParam.put("vendorIdx", 1); + tranParam.put("vendorCode", "evolution"); + tranParam.put("vendorTranKey", evo.getTransaction().getId()); + tranParam.put("gameIdx", evo.getGame().getType()); + tranParam.put("tranType", "debit"); + tranParam.put("depositAmt", evo.getTransaction().getAmount()); + tranParam.put("creditAmt", "0"); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("completed", false); + + try { + CommonParam commonParam = new CommonParam(); + commonParam.setSiteIdx(Integer.parseInt(siteApiInfo.get("siteIdx").toString())); + PlayParam param = new PlayParam(); + param.setVendorKey("C01"); + commonParam.setPlayParam(param); + HashMap venderInfo = siteService.getVenderApiInfo(commonParam); + tranParam.put("vendorApiId", venderInfo.get("vendorApiId").toString()); + }catch(Exception e) {System.out.println("VI ERR:" + e.toString());} + siteService.commonBetinsert(tranParam); + + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/json"); + header.add("Accept", "application/json"); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + JSONObject debit = new JSONObject(); + + debit.put("betId", siteId+evo.getTransaction().getRefId()); + debit.put("tranId", siteId+evo.getTransaction().getId()); + debit.put("userId", memberId); + debit.put("vendorIdx", 1); + debit.put("vendorKey","C01"); + debit.put("vendor", "evolution"); + debit.put("gameIdx", 1); + debit.put("gameKey",evo.getGame().getType()); + debit.put("tranType", "debit"); + debit.put("debit", evo.getTransaction().getAmount()); + debit.put("credit", 0); + debit.put("isCancel", 0); + debit.put("isBonus",0); + + log.info("send code : {}", debit.toString()); + + ResponseEntity responseEntity = null; + try { + responseEntity = webClient.post() + .uri(siteApiInfo.get("siteCbUrl")+"/changebalance") + .headers(h -> h.addAll(header)) + .bodyValue(debit.toString()) + .retrieve() + .toEntity(String.class) + .block(); + } catch(WebClientResponseException e) { + log.error("debit::HttpClientErrorException : " + e.getMessage()); + log.error("debit::status code : " + e.getStatusCode().value()); + log.error("debit::response body : " + e.getResponseBodyAsString()); + evoResponse.fail(); + return evoResponse; + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) { + log.error("debit::ConnectTimeoutException::" + rae.getMessage()); + } + if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error("debit::SocketTimeoutException::" + rae.getMessage()); + } + if(rae.getCause() instanceof InterruptedException) { + log.error("debit::InterruptedException::" + rae.getMessage()); + } + log.error("debit::WebClientRequestException : " + rae.getMessage()); + evoResponse.fail(); + return evoResponse; + } + + if(responseEntity != null && responseEntity.getStatusCode() == HttpStatus.OK) { + log.info("status code : {}", responseEntity.getStatusCode()); + log.info("bodyD: {}", responseEntity.getBody()); + + JSONObject resData = new JSONObject(responseEntity.getBody()); + log.info("result_Dcode: {}", resData.getInt("result_code")); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getDouble("balance")); + int res = siteService.updateCbApi(tranParam); + log.info("result_Dcode: {}2"); + evoResponse.setUuid(evo.getUuid()); + evoResponse.setBalance( resData.getDouble("balance")); + evoResponse.setBonus(0.0); + + evoResponse.success(); + }else if(resData.getLong("result_code") == 80) { + evoResponse.setBalance( resData.getDouble("balance")); + evoResponse.fail("INSUFFICIENT_FUNDS"); + + }else if(resData.getLong("result_code") == 98) { + log.info("result_Dcode 98: {}1"); + evoResponse.fail("BET_ALREADY_EXIST"); + evoResponse.setBalance( resData.getDouble("balance")); + }else { + evoResponse.fail(); + } + } else { + log.error("debit::Unexpected response status code"); + evoResponse.fail(); + } + + } catch (Exception e) { + log.info(e.toString()); + e.printStackTrace(); + evoResponse.fail(); + } + + return evoResponse; + } + + + @ResponseBody + @RequestMapping(value={"/credit","/cancel"}) + public EvoResponse credit (HttpServletRequest request, @RequestBody EvolutionVo evo) throws Exception { + EvoResponse evoResponse = new EvoResponse(); + + try { + log.debug(evo.toString()); + //사이트정보 + HashMap sParam = new HashMap(); + + sParam.put("siteIdx",Integer.parseInt(evo.getUserId().substring(0, 3), 16)); + sParam.put("memberId", evo.getUserId().substring(3, evo.getUserId().length())); + String memberId =evo.getUserId().substring(3, evo.getUserId().length()); + + HashMap siteApiInfo = siteService.getSiteApiInfo(sParam); + String siteId = siteApiInfo.get("siteId").toString(); + + HashMap tranParam = new HashMap(); + tranParam.put("tranId",siteId+evo.getTransaction().getId()); + tranParam.put("refId", siteId+evo.getTransaction().getRefId()); + tranParam.put("siteIdx", siteApiInfo.get("siteIdx")); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", siteApiInfo.get("memberIdx")); + tranParam.put("memberId", memberId); + tranParam.put("vendorIdx", 1); + tranParam.put("vendorCode", "evolution"); + tranParam.put("vendorTranKey", evo.getTransaction().getId()); + tranParam.put("gameIdx", evo.getGame().getType()); + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", 0); + tranParam.put("creditAmt", evo.getTransaction().getAmount()); + + tranParam.put("completed", true); + + tranParam.put("isCancel", "N"); + + if(request.getRequestURI().indexOf("cancel") > 0 ) { + tranParam.put("isCancel", "Y"); + } + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + + + try { + CommonParam commonParam = new CommonParam(); + commonParam.setSiteIdx(Integer.parseInt(siteApiInfo.get("siteIdx").toString())); + PlayParam param = new PlayParam(); + param.setVendorKey("C01"); + commonParam.setPlayParam(param); + HashMap venderInfo = siteService.getVenderApiInfo(commonParam); + tranParam.put("vendorApiId", venderInfo.get("vendorApiId").toString()); + }catch(Exception e) {System.out.println("VI ERR:" + e.toString());} + siteService.commonBetinsert(tranParam); + + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/json"); + header.add("Accept", "application/json"); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + JSONObject debit = new JSONObject(); + + debit.put("betId", siteId+evo.getTransaction().getRefId()); + debit.put("tranId", siteId+evo.getTransaction().getId()); + debit.put("userId", memberId); + debit.put("vendorIdx", 1); + debit.put("vendorKey","C01"); + debit.put("vendor", "evolution"); + debit.put("gameIdx", 1); + debit.put("gameKey",evo.getGame().getType()); + debit.put("tranType", "credit"); + debit.put("debit", 0); + debit.put("credit", evo.getTransaction().getAmount()); + debit.put("isCancel",0); + debit.put("isBonus",0); + + if(request.getRequestURI().indexOf("cancel") > 0 ) { + debit.put("isCancel",1); + } + + log.info("send code : {}", debit.toString()); + + ResponseEntity responseEntity = null; + try { + responseEntity = webClient.post() + .uri(siteApiInfo.get("siteCbUrl")+"/changebalance") + .headers(h -> h.addAll(header)) + .bodyValue(debit.toString()) + .retrieve() + .toEntity(String.class) + .block(); + } catch(WebClientResponseException e) { + log.error("credit::HttpClientErrorException : " + e.getMessage()); + log.error("credit::status code : " + e.getStatusCode().value()); + log.error("credit::response body : " + e.getResponseBodyAsString()); + evoResponse.fail(); + return evoResponse; + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) { + log.error("credit::ConnectTimeoutException::" + rae.getMessage()); + } + if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error("credit::SocketTimeoutException::" + rae.getMessage()); + } + if(rae.getCause() instanceof InterruptedException) { + log.error("credit::InterruptedException::" + rae.getMessage()); + } + log.error("credit::WebClientRequestException : " + rae.getMessage()); + evoResponse.fail(); + return evoResponse; + } + + if(responseEntity != null && responseEntity.getStatusCode() == HttpStatus.OK) { + log.info("status code : {}", responseEntity.getStatusCode()); + log.info("bodyC: {}", responseEntity.getBody()); + + JSONObject resData = new JSONObject(responseEntity.getBody()); + log.info("result_DCcode: {}", resData.getInt("result_code")); + if(resData.getLong("result_code") == 0) { + log.info("siteService.updateCbApi(tranParam)"); + tranParam.put("balance", resData.getDouble("balance")); + int res = siteService.updateCbApi(tranParam); + + evoResponse.setUuid(evo.getUuid()); + evoResponse.setBalance( resData.getDouble("balance")); + evoResponse.setBonus(0.0); + evoResponse.success(); + }else if(resData.getLong("result_code") == 99) { + + if(request.getRequestURI().indexOf("cancel") > 0 ) { + + HashMap eParam = new HashMap(); + eParam.put("betId", evo.getTransaction().getRefId()); + eParam.put("errorType", "FATAL_ERROR"); + + siteService.insertError(eParam); + } + + evoResponse.fail("BET_DOES_NOT_EXIST"); + evoResponse.setBalance( resData.getDouble("balance")); + + }else if(resData.getLong("result_code") == 98) { + evoResponse.fail("BET_ALREADY_SETTLED"); + evoResponse.setBalance( resData.getDouble("balance")); + }else { + evoResponse.fail(); + } + } else { + log.error("credit::Unexpected response status code"); + evoResponse.fail(); + } + + } catch (Exception e) { + log.info(e.toString()); + e.printStackTrace(); + evoResponse.fail(); + } + + return evoResponse; + } + + + + @ResponseBody + @RequestMapping(value={"/promo_payout"}) + public EvoResponse promo_payout (HttpServletRequest request, @RequestBody EvolutionVo evo) throws Exception { + EvoResponse evoResponse = new EvoResponse(); + + try { + log.debug(evo.toString()); + //사이트정보 + HashMap sParam = new HashMap(); + String[] usrinfo = evo.getUserId().split("_"); + + sParam.put("siteIdx",Integer.parseInt(evo.getUserId().substring(0, 3), 16)); + sParam.put("memberId", evo.getUserId().substring(3, evo.getUserId().length())); + String memberId =evo.getUserId().substring(3, evo.getUserId().length()); + + HashMap siteApiInfo = siteService.getSiteApiInfo(sParam); + String siteId = siteApiInfo.get("siteId").toString(); + + HashMap tranParam = new HashMap(); + tranParam.put("tranId",siteId+evo.getPromoTransaction().getId()); + tranParam.put("refId", siteId+evo.getPromoTransaction().getId()); + tranParam.put("siteIdx", siteApiInfo.get("siteIdx")); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", siteApiInfo.get("memberIdx")); + tranParam.put("memberId", memberId); + tranParam.put("vendorIdx", 1); + tranParam.put("vendorCode", "evolution"); + tranParam.put("vendorTranKey", evo.getPromoTransaction().getId()); + tranParam.put("gameIdx", evo.getPromoTransaction().getType()); + tranParam.put("tranType", "promo"); + tranParam.put("depositAmt", 0); + tranParam.put("creditAmt", evo.getPromoTransaction().getAmount()); + + tranParam.put("isCancel", "N"); + + if(request.getRequestURI().indexOf("cancel") > 0 ) { + tranParam.put("isCancel", "Y"); + } + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + + tranParam.put("completed", true); + try { + CommonParam commonParam = new CommonParam(); + commonParam.setSiteIdx(Integer.parseInt(siteApiInfo.get("siteIdx").toString())); + PlayParam param = new PlayParam(); + param.setVendorKey("C01"); + commonParam.setPlayParam(param); + HashMap venderInfo = siteService.getVenderApiInfo(commonParam); + tranParam.put("vendorApiId", venderInfo.get("vendorApiId").toString()); + }catch(Exception e) {System.out.println("VI ERR:" + e.toString());} + siteService.commonBetinsert(tranParam); + + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/json"); + header.add("Accept", "application/json"); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + JSONObject debit = new JSONObject(); + + debit.put("betId", siteId+evo.getPromoTransaction().getId()); + debit.put("tranId", siteId+evo.getPromoTransaction().getId()); + debit.put("userId", memberId); + debit.put("vendorIdx", 1); + debit.put("vendorKey","C01"); + debit.put("vendor","evolution"); + debit.put("gameIdx", 1); + debit.put("gameKey",evo.getPromoTransaction().getType()); + debit.put("tranType", "credit"); + debit.put("debit", 0); + debit.put("credit", evo.getPromoTransaction().getAmount()); + debit.put("isCancel",0); + debit.put("isBonus",1); + + log.info("send code : {}", debit.toString()); + + ResponseEntity responseEntity = null; + try { + responseEntity = webClient.post() + .uri(siteApiInfo.get("siteCbUrl")+"/changebalance") + .headers(h -> h.addAll(header)) + .bodyValue(debit.toString()) + .retrieve() + .toEntity(String.class) + .block(); + } catch(WebClientResponseException e) { + log.error("promo_payout::HttpClientErrorException : " + e.getMessage()); + log.error("promo_payout::status code : " + e.getStatusCode().value()); + log.error("promo_payout::response body : " + e.getResponseBodyAsString()); + evoResponse.fail(); + return evoResponse; + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) { + log.error("promo_payout::ConnectTimeoutException::" + rae.getMessage()); + } + if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error("promo_payout::SocketTimeoutException::" + rae.getMessage()); + } + if(rae.getCause() instanceof InterruptedException) { + log.error("promo_payout::InterruptedException::" + rae.getMessage()); + } + log.error("promo_payout::WebClientRequestException : " + rae.getMessage()); + evoResponse.fail(); + return evoResponse; + } + + if(responseEntity != null && responseEntity.getStatusCode() == HttpStatus.OK) { + log.info("status code : {}", responseEntity.getStatusCode()); + log.info("bodyC: {}", responseEntity.getBody()); + + JSONObject resData = new JSONObject(responseEntity.getBody()); + log.info("result_DCcode: {}", resData.getInt("result_code")); + if(resData.getLong("result_code") == 0) { + log.info("siteService.updateCbApi(tranParam)"); + tranParam.put("balance", resData.getDouble("balance")); + int res = siteService.updateCbApi(tranParam); + + evoResponse.setUuid(evo.getUuid()); + evoResponse.setBalance( resData.getDouble("balance")); + evoResponse.setBonus(0.0); + evoResponse.success(); + }else if(resData.getLong("result_code") == 99) { + evoResponse.fail("BET_DOES_NOT_EXIST"); + evoResponse.setBalance( resData.getDouble("balance")); + + }else if(resData.getLong("result_code") == 98) { + evoResponse.fail("BET_ALREADY_SETTLED"); + evoResponse.setBalance( resData.getDouble("balance")); + + }else if(resData.getLong("result_code") == 70) { + evoResponse.fail("BET_ALREADY_SETTLED"); + evoResponse.setBalance( resData.getDouble("balance")); + + }else { + evoResponse.fail(); + } + } else { + log.error("promo_payout::Unexpected response status code"); + evoResponse.fail(); + } + + } catch (Exception e) { + log.info(e.toString()); + e.printStackTrace(); + evoResponse.fail(); + } + + return evoResponse; + } + + + + private String makeApiKey(String param) { + + int n = 20; // n자리 쿠폰 + char[] chs = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' ,'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; + + + Random rd = new Random(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < n; i++) { + char ch = chs[rd.nextInt(chs.length)]; + sb.append(ch); + } + return param + sb.toString(); + + + } + +} + diff --git a/src/main/java/com/bb/front/CallBackBombController.java b/src/main/java/com/bb/front/CallBackBombController.java new file mode 100644 index 0000000..a9af7ad --- /dev/null +++ b/src/main/java/com/bb/front/CallBackBombController.java @@ -0,0 +1,559 @@ +package com.bb.front; + +import java.text.SimpleDateFormat; +import java.util.HashMap; + +import jakarta.servlet.http.HttpServletRequest; + +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +import com.bb.jwt.JwtManager; +import com.bb.model.BombAuthVO; +import com.bb.model.BombReponseVo; +import com.bb.model.CommonParam; +import com.bb.model.Member; +import com.bb.model.PlayParam; +import com.bb.service.CallBackService; +import com.bb.service.SiteService; +import com.bb.util.AesUtil; +import com.google.gson.Gson; + +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@RestController +@Slf4j +@RequestMapping("/api/cb/pbomb") +@RequiredArgsConstructor +@SecurityRequirement(name = "Authorization") +public class CallBackBombController { + + // https://oprvender.com/api/cb/live + + @Autowired + private final JwtManager jwtManager; + + @Autowired + SiteService siteService; + + @Autowired + CallBackService callBackService; + + @ResponseBody + @RequestMapping(value = "/loginAuth", method = RequestMethod.POST) + public BombReponseVo minegameLoginAuth(@RequestBody BombAuthVO bombAuthVO, HttpServletRequest request) + throws Exception { + BombReponseVo bombReponseVo = new BombReponseVo(); + log.info("#bomb::loginAuth::" + "bombAuthVO" + bombAuthVO.toString()); + Gson gson = new Gson(); + bombAuthVO = gson.fromJson(AesUtil.getAES128_Decode(bombAuthVO.getEp()), BombAuthVO.class); + log.info("#bomb::loginAuth::" + "dec bombAuthVO" + bombAuthVO.toString()); + + HashMap memParam = new HashMap(); + memParam.put("bombAccId", bombAuthVO.getLoginToken()); + + Member member = siteService.getMemByBombAccId(memParam); + + try { + String accID = bombAuthVO.getAccID(); + String token = bombAuthVO.getLoginToken(); + + log.info("#bomb::loginAuth::" + accID); + log.info("#bomb::loginAuth::" + token); + log.info("#bomb::loginAuth::" + member); + + if (member.getBombAccId().equals(token)) { + + log.info("#bomb::loginAuth::" + 1111111); + + bombReponseVo.setAccId(accID); + bombReponseVo.setNickName(member.getMemberNick()); + bombReponseVo.setCode(0); + bombReponseVo.setDemo(false); + + // 밸런스 가져오기 + + HashMap sParam = new HashMap(); + // String[] usrinfo = accID.split("_"); + + // String memberId =""; + // String siteId =""; + sParam.put("siteIdx", Integer.parseInt(accID.substring(0, 3), 16)); + sParam.put("memberId", accID.substring(3, accID.length())); + String memberId = accID.substring(3, accID.length()); + + HashMap siteApiInfo = siteService.getSiteApiInfo(sParam); + + JSONObject parammember = new JSONObject(); + parammember.put("userId", member.getMemberId()); + + // 밸런스가져오기 + JSONObject resData = callBackService.getBalance(siteApiInfo, parammember); + if(resData == null) { + log.info("#bomb::debit::" + "balance callback error"); + bombReponseVo.setCode(-1); + return bombReponseVo; + } + + // JSONObject resData = new JSONObject(responseEntity.getBody()); + + if (resData.getInt("result_code") == 0) { + + if ("Y".equals(siteApiInfo.getOrDefault("bombDecYn", "").toString())) { + bombReponseVo.setBalance("" + (resData.getDouble("balance") * 0.01)); + } else { + bombReponseVo.setBalance("" + resData.getDouble("balance")); + } + } else { + bombReponseVo.fail(); + } + + } else { + bombReponseVo.fail(); + } + } catch (Exception e) { + bombReponseVo.fail(); + } + + log.info("#bomb::loginAuth::" + "BOMB AUTH RESbody: {}", bombReponseVo); + return bombReponseVo; + } + + @ResponseBody + @RequestMapping(value = "/bet", method = RequestMethod.POST) + public BombReponseVo minegameEncBet(@RequestBody BombAuthVO bombAuthVO, HttpServletRequest request) + throws Exception { + BombReponseVo bombReponseVo = new BombReponseVo(); + + Gson gson = new Gson(); + bombAuthVO = gson.fromJson(AesUtil.getAES128_Decode(bombAuthVO.getEp()), BombAuthVO.class); + + JSONObject obj = new JSONObject(); + + HashMap memParam = new HashMap(); + memParam.put("bombAccId", bombAuthVO.getLoginToken()); + Member member = siteService.getMemByBombAccId(memParam); + + try { + String accID = bombAuthVO.getAccID(); + String userID = bombAuthVO.getUserID(); + String token = bombAuthVO.getLoginToken(); + String transferId = bombAuthVO.getTransferId(); + Integer roomNo = bombAuthVO.getRoomNo(); + double betAmount = (double) bombAuthVO.getAmount(); + + log.info("#bomb::debit::" + "bombgame bet accID : " + accID); + log.info("#bomb::debit::" + "bombgame bet userID : " + userID); + log.info("#bomb::debit::" + "bombgame bet token : " + token); + log.info("#bomb::debit::" + "bombgame bet roomNo : " + roomNo); + log.info("#bomb::debit::" + "bombgame bet transferId : " + transferId); + log.info("#bomb::debit::" + "bombgame bet betAmount : " + betAmount); + + // 밸런스 가져오기 + + HashMap sParam = new HashMap(); + + sParam.put("siteIdx", Integer.parseInt(accID.substring(0, 3), 16)); + sParam.put("memberId", accID.substring(3, accID.length())); + String memberId = accID.substring(3, accID.length()); + + HashMap siteApiInfo = siteService.getSiteApiInfo(sParam); + String siteId = siteApiInfo.get("siteId").toString(); + + // 사이트에 크레딧이 없을경우 에러 보냄 베팅막음 + long targetSiteCredit = siteService.getSiteCredit(siteId); + if (targetSiteCredit < betAmount) { + log.info("#bomb::debit::" + "no siteCredit"); + bombReponseVo.setCode(-1); + return bombReponseVo; + } + + // 최대베팅액 (userMaxBet 우선 적용) + sParam.put("vendorIdx", 5); + long maxBet = siteService.getSiteMaxBet(sParam); + + // userMaxBet 조회 + long userMaxBet = 0; + Long userMaxBetObj = siteService.getUserMaxBet(sParam); + if(userMaxBetObj != null) { + userMaxBet = userMaxBetObj; + } + + // 최종 maxBet 결정: userMaxBet이 0이면 siteMaxBet 사용, 0이 아니면 userMaxBet 사용 + long finalMaxBet = (userMaxBet > 0) ? userMaxBet : maxBet; + log.info("#bomb::debit::MaxBet Info - siteMaxBet: " + maxBet + ", userMaxBet: " + userMaxBet + ", finalMaxBet: " + finalMaxBet); + + if (betAmount > finalMaxBet) { + log.info("#bomb::debit::" + "Over bet money - finalMaxBet: " + finalMaxBet); + bombReponseVo.setCode(-1); + return bombReponseVo; + } + + JSONObject parammember = new JSONObject(); + parammember.put("userId", member.getMemberId()); + + log.info("#bomb::debit::" + siteApiInfo); + JSONObject resData2 = callBackService.getBalance(siteApiInfo, parammember); + if(resData2 == null) { + log.info("#bomb::debit::" + "balance callback error"); + bombReponseVo.setCode(-1); + return bombReponseVo; + } + + if (resData2.getInt("result_code") == 0) { + + if ("Y".equals(siteApiInfo.getOrDefault("bombDecYn", "").toString())) { + bombReponseVo.setBalance("" + (resData2.getDouble("balance") * 0.01)); + } else { + bombReponseVo.setBalance("" + resData2.getDouble("balance")); + } + + } else { + bombReponseVo.fail(); + } + + if (betAmount < 0) { + + bombReponseVo.setCode(-99); + + } else { + if (member.getBombAccId().equals(token)) { + double curCashAmount = resData2.getDouble("balance"); + + if (curCashAmount >= betAmount) { + + // betAmount 만큼 cashAmt 차감 + // memberService.updateMineMemCashAmt(bombAuthVO); + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", siteId + "D" + bombAuthVO.getTransferId()); + tranParam.put("refId", siteId + bombAuthVO.getTransferId()); + tranParam.put("siteIdx", siteApiInfo.get("siteIdx")); + + tranParam.put("siteId", siteId); + + tranParam.put("memberIdx", siteApiInfo.get("memberIdx")); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", "MINIGAME"); + tranParam.put("vendorIdx", 5); + tranParam.put("vendorCode", "tpabomb"); + tranParam.put("vendorTranKey", bombAuthVO.getTransferId()); + tranParam.put("gameType", ""); + tranParam.put("gameId", ""); + tranParam.put("gameIdx", ""+roomNo); + tranParam.put("tranType", "debit"); + tranParam.put("depositAmt", betAmount); + tranParam.put("creditAmt", "0"); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("completed", false); + + try { + CommonParam commonParam = new CommonParam(); + commonParam.setSiteIdx(Integer.parseInt(siteApiInfo.get("siteIdx").toString())); + PlayParam param = new PlayParam(); + param.setVendorKey("M01"); + commonParam.setPlayParam(param); + HashMap venderInfo = siteService.getVenderApiInfo(commonParam); + tranParam.put("vendorApiId", venderInfo.get("vendorApiId").toString()); + } catch (Exception e) { + log.info("#bomb::debit::" + "VI ERR:" + e.toString()); + } + siteService.commonBetinsert(tranParam); + + + JSONObject debit = new JSONObject(); + debit.put("betId", siteId + bombAuthVO.getTransferId()); + debit.put("tranId", siteId + "D" + bombAuthVO.getTransferId()); + debit.put("userId", memberId); + debit.put("vendorIdx", 5); + debit.put("vendorKey", "M01"); + debit.put("vendor", "tpabomb"); + debit.put("gameIdx", 1); + debit.put("gameKey", ""+roomNo); + debit.put("gameId", ""); + debit.put("gameType", ""); + debit.put("tranType", "debit"); + + if ("Y".equals(siteApiInfo.getOrDefault("bombDecYn", "").toString())) { + Double betAmountD = betAmount * 100; + debit.put("debit", betAmountD.longValue()); + } else { + debit.put("debit", betAmount); + } + + debit.put("credit", 0); + debit.put("isCancel", 0); + debit.put("isBonus", 0); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + long nDate = System.currentTimeMillis(); + String betDateTimeStr = sdf.format(nDate); + debit.put("requestAt", betDateTimeStr); + + JSONObject resData = callBackService.changeBalance("#bomb::", siteApiInfo, debit); + + log.info("#bomb::debit::" + "result_Dcode: {}", resData.getInt("result_code")); + + if (resData.getLong("result_code") == 0) { + bombReponseVo.setCode(0); + bombReponseVo.setBalance("" + resData.getDouble("balance")); + + if ("Y".equals(siteApiInfo.getOrDefault("bombDecYn", "").toString())) { + bombReponseVo.setBalance("" + (resData.getDouble("balance") * 0.01)); + } else { + bombReponseVo.setBalance("" + resData.getDouble("balance")); + } + + tranParam.put("balance", bombReponseVo.getBalance()); + int res = siteService.updateCbApi(tranParam); + log.info("#bomb::debit::" + "result_Dcode: {}2"); + + } else if (resData.getLong("result_code") == 80) { + bombReponseVo.setCode(-1); + + } else if (resData.getLong("result_code") == 98) { + log.info("#bomb::debit::" + "result_Dcode 98: {}1"); + bombReponseVo.setCode(-1); + } else { + bombReponseVo.setCode(-1); + } + + } else { + bombReponseVo.setCode(-1); + obj.put("code", -1); + log.info("#bomb::debit::" + "bombgame info curr cash : " + curCashAmount + ", reqest : " + + betAmount); + } + + } else { + bombReponseVo.setCode(-99); + log.info("#bomb::debit::" + "bombgame info token : " + member.getBombAccId() + ", reqest : " + + token); + } + } + + } catch (Exception e) { + bombReponseVo.setCode(-1); + log.info("#bomb::debit::" + e); + } + + return bombReponseVo; + } + + @ResponseBody + @RequestMapping(value = { "/payout", "/end" }, method = RequestMethod.POST) + public BombReponseVo minegameEncCredit(@RequestBody BombAuthVO bombAuthVO, HttpServletRequest request) + throws Exception { + BombReponseVo bombReponseVo = new BombReponseVo(); + log.info("#bomb::credit::" + "bombAuthVO" + bombAuthVO.toString()); + Gson gson = new Gson(); + bombAuthVO = gson.fromJson(AesUtil.getAES128_Decode(bombAuthVO.getEp()), BombAuthVO.class); + + JSONObject obj = new JSONObject(); + + HashMap memParam = new HashMap(); + memParam.put("bombAccId", bombAuthVO.getLoginToken()); + Member member = siteService.getMemByBombAccId(memParam); + + try { + String accID = bombAuthVO.getAccID(); + String userID = bombAuthVO.getUserID(); + String token = bombAuthVO.getLoginToken(); + String transferId = bombAuthVO.getTransferId(); + Integer roomNo = bombAuthVO.getRoomNo(); + double betAmount = (double) bombAuthVO.getAmount(); + + String bombs = bombAuthVO.getBombs(); + String play = bombAuthVO.getPlay(); + String endDate = bombAuthVO.getEndDate(); + + log.info("#bomb::credit::" + "bombgame bet accID : " + accID); + log.info("#bomb::credit::" + "bombgame bet userID : " + userID); + log.info("#bomb::credit::" + "bombgame bet token : " + token); + log.info("#bomb::credit::" + "bombgame bet roomNo : " + roomNo); + log.info("#bomb::credit::" + "bombgame bet transferId : " + transferId); + log.info("#bomb::credit::" + "bombgame bet betAmount : " + betAmount); + + log.info("#bomb::credit::" + "bombgame bet bombs : " + bombs); + log.info("#bomb::credit::" + "bombgame bet play : " + play); + + // 밸런스 가져오기 + + HashMap sParam = new HashMap(); + sParam.put("siteIdx", Integer.parseInt(accID.substring(0, 3), 16)); + sParam.put("memberId", accID.substring(3, accID.length())); + String memberId = accID.substring(3, accID.length()); + + HashMap siteApiInfo = siteService.getSiteApiInfo(sParam); + String siteId = siteApiInfo.get("siteId").toString(); + + JSONObject parammember = new JSONObject(); + parammember.put("userId", member.getMemberId()); + + JSONObject resData2 = callBackService.getBalance(siteApiInfo, parammember); + if(resData2 == null) { + log.info("#bomb::credit::" + "balance callback error"); + bombReponseVo.setCode(-1); + return bombReponseVo; + } + + if (resData2.getInt("result_code") == 0) { + + if ("Y".equals(siteApiInfo.getOrDefault("bombDecYn", "").toString())) { + bombReponseVo.setBalance("" + (resData2.getDouble("balance") * 0.01)); + } else { + bombReponseVo.setBalance("" + resData2.getDouble("balance")); + } + + } else { + bombReponseVo.fail(); + } + + if (betAmount < 0) { + + bombReponseVo.setCode(-99); + + } else { + if (member.getBombAccId().equals(token)) { + double curCashAmount = resData2.getDouble("balance"); + + if (betAmount >= 0) { + + // betAmount 만큼 cashAmt 차감 + // memberService.updateMineMemCashAmt(bombAuthVO); + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", siteId + "C" + bombAuthVO.getTransferId()); + tranParam.put("refId", siteId + bombAuthVO.getTransferId()); + tranParam.put("siteIdx", siteApiInfo.get("siteIdx")); + + tranParam.put("siteId", siteId); + + tranParam.put("memberIdx", siteApiInfo.get("memberIdx")); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", "MINIGAME"); + tranParam.put("vendorIdx", 5); + tranParam.put("vendorCode", "tpabomb"); + tranParam.put("vendorTranKey", bombAuthVO.getTransferId()); + tranParam.put("gameType", ""); + tranParam.put("gameId", ""); + tranParam.put("gameIdx", ""+roomNo); + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", 0); + tranParam.put("creditAmt", betAmount); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + + tranParam.put("completed", true); + + // 게임별로 상세내역 넣어주기 있을 경우에만 + JSONObject detail = new JSONObject(); + + detail.put("roomNo ", roomNo); + detail.put("play", play); + detail.put("bombs", bombs); + tranParam.put("detail", detail.toString()); + + try { + CommonParam commonParam = new CommonParam(); + commonParam.setSiteIdx(Integer.parseInt(siteApiInfo.get("siteIdx").toString())); + PlayParam param = new PlayParam(); + param.setVendorKey("M01"); + commonParam.setPlayParam(param); + HashMap venderInfo = siteService.getVenderApiInfo(commonParam); + tranParam.put("vendorApiId", venderInfo.get("vendorApiId").toString()); + } catch (Exception e) { + log.info("#bomb::credit::" + "VI ERR:" + e.toString()); + } + siteService.commonBetinsert(tranParam); + JSONObject debit = new JSONObject(); + + debit.put("betId", siteId + bombAuthVO.getTransferId()); + debit.put("tranId", siteId + "C" + bombAuthVO.getTransferId()); + debit.put("userId", memberId); + debit.put("vendorIdx", 5); + debit.put("vendorKey", "M01"); + debit.put("vendor", "tpabomb"); + debit.put("gameIdx", 1); + debit.put("gameKey", roomNo); + debit.put("gameId", ""); + debit.put("gameType", ""); + debit.put("tranType", "credit"); + debit.put("debit", 0); + + if ("Y".equals(siteApiInfo.getOrDefault("bombDecYn", "").toString())) { + Double betAmountD = betAmount * 100; + debit.put("credit", betAmountD.longValue()); + } else { + + debit.put("credit", betAmount); + } + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + long nDate = System.currentTimeMillis(); + String betDateTimeStr = sdf.format(nDate); + debit.put("requestAt", betDateTimeStr); + debit.put("isCancel", 0); + debit.put("isBonus", 0); + debit.put("detail", detail); + + + + JSONObject resData = callBackService.changeBalance("#bomb::", siteApiInfo, debit); + log.info("#bomb::credit::" + "result_Dcode: {}", resData.getInt("result_code")); + + if (resData.getLong("result_code") == 0) { + + bombReponseVo.setCode(0); + + if ("Y".equals(siteApiInfo.getOrDefault("bombDecYn", "").toString())) { + bombReponseVo.setBalance("" + (resData.getDouble("balance") * 0.01)); + } else { + bombReponseVo.setBalance("" + resData.getDouble("balance")); + } + + tranParam.put("balance", bombReponseVo.getBalance()); + int res = siteService.updateCbApi(tranParam); + log.info("#bomb::debit::" + "result_Dcode: {}2"); + + } else if (resData.getLong("result_code") == 80) { + bombReponseVo.setCode(-1); + + } else if (resData.getLong("result_code") == 98) { + log.info("#bomb::credit::" + "result_Dcode 98: {}1"); + bombReponseVo.setCode(-1); + } else { + bombReponseVo.setCode(-1); + } + + } else { + bombReponseVo.setCode(-1); + obj.put("code", -1); + log.info("#bomb::credit::" + "bombgame info curr cash : " + curCashAmount + ", reqest : " + + betAmount); + } + + } else { + bombReponseVo.setCode(-99); + log.info("#bomb::credit::" + "bombgame info token : " + member.getBombAccId() + ", reqest : " + + token); + } + } + + } catch (Exception e) { + bombReponseVo.setCode(-1); + log.info("#bomb::credit::" + e); + } + + return bombReponseVo; + } + +} diff --git a/src/main/java/com/bb/front/CallBackBombDemoController.java b/src/main/java/com/bb/front/CallBackBombDemoController.java new file mode 100644 index 0000000..31bc0a0 --- /dev/null +++ b/src/main/java/com/bb/front/CallBackBombDemoController.java @@ -0,0 +1,159 @@ +package com.bb.front; + +import java.util.HashMap; + +import jakarta.servlet.http.HttpServletRequest; + +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +import com.bb.jwt.JwtManager; +import com.bb.model.BombAuthVO; +import com.bb.model.BombReponseVo; +import com.bb.service.SiteService; +import com.bb.util.AesUtil; +import com.google.gson.Gson; + +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@RestController +@Slf4j +@RequestMapping("/api/cb/demopbomb") +@RequiredArgsConstructor +@SecurityRequirement(name = "Authorization") +public class CallBackBombDemoController { + + // https://oprvender.com/api/cb/live + + @Autowired + private final JwtManager jwtManager; + + @Autowired + SiteService siteService; + + + + + @ResponseBody + @RequestMapping(value="/loginAuth", method=RequestMethod.POST) + public BombReponseVo minegameLoginAuth(@RequestBody BombAuthVO bombAuthVO, HttpServletRequest request) throws Exception { + BombReponseVo bombReponseVo = new BombReponseVo(); + System.out.println("bombAuthVO" + bombAuthVO.toString()); + Gson gson = new Gson(); + bombAuthVO = gson.fromJson(AesUtil.getAES128_Decode(bombAuthVO.getEp()), BombAuthVO.class); + System.out.println("dec bombAuthVO" + bombAuthVO.toString()); + + + HashMap memParam = new HashMap(); + memParam.put("bombAccId", bombAuthVO.getLoginToken()); + HashMap demomember = siteService.getDemoByBombAccId(memParam); + + try { + String accID = bombAuthVO.getAccID(); + String token= bombAuthVO.getLoginToken(); + + + + if(demomember.get("bombAccId").toString().equals(token)) { + + + System.out.println(1111111); + + + bombReponseVo.setAccId(accID); + bombReponseVo.setNickName( demomember.get("bombAccId").toString()); + bombReponseVo.setCode(0); + bombReponseVo.setBalance(""+(Double.parseDouble(demomember.get("creditAmt").toString()))); + bombReponseVo.setDemo(true); + + + + } else { + bombReponseVo.fail(); + } + }catch(Exception e) { + bombReponseVo.fail(); + } + + log.info("BOMB AUTH RESbody: {}", bombReponseVo); + return bombReponseVo; + } + + + + + @ResponseBody + @RequestMapping(value="/bet", method=RequestMethod.POST) + public BombReponseVo minegameEncBet(@RequestBody BombAuthVO bombAuthVO, HttpServletRequest request) throws Exception { + BombReponseVo bombReponseVo = new BombReponseVo(); + + Gson gson = new Gson(); + bombAuthVO = gson.fromJson(AesUtil.getAES128_Decode(bombAuthVO.getEp()), BombAuthVO.class); + + JSONObject obj = new JSONObject(); + + + + + HashMap memParam = new HashMap(); + memParam.put("bombAccId", bombAuthVO.getLoginToken()); + HashMap demomember = siteService.getDemoByBombAccId(memParam); + double balance = Double.parseDouble(demomember.get("creditAmt").toString()); + double betAmount = (double)bombAuthVO.getAmount(); + log.warn("DEMO BALANCE memINFO {} {} ", demomember.toString(), betAmount); + if(balance < balance - betAmount) { + + bombReponseVo.setCode(-99); + return bombReponseVo; + } else { + bombReponseVo.setBalance("" +( balance - betAmount)); + memParam.put("creditAmt", "" +( balance - betAmount)); + siteService.updateDemoUSer(memParam); + } + log.warn("DEMO BALANCE memParam {}", memParam.toString()); + + return bombReponseVo; + } + + + @ResponseBody + @RequestMapping(value={"/payout", "/end"}, method=RequestMethod.POST) + public BombReponseVo minegameEncCredit(@RequestBody BombAuthVO bombAuthVO, HttpServletRequest request) throws Exception { + BombReponseVo bombReponseVo = new BombReponseVo(); + + Gson gson = new Gson(); + bombAuthVO = gson.fromJson(AesUtil.getAES128_Decode(bombAuthVO.getEp()), BombAuthVO.class); + + JSONObject obj = new JSONObject(); + + + + + HashMap memParam = new HashMap(); + memParam.put("bombAccId", bombAuthVO.getLoginToken()); + HashMap demomember = siteService.getDemoByBombAccId(memParam); + + double balance = Double.parseDouble(demomember.get("creditAmt").toString()); + double betAmount = (double)bombAuthVO.getAmount(); + log.warn("DEMO BALANCE memINFO {} {} ", demomember.toString(), betAmount); + bombReponseVo.setBalance("" +( balance + betAmount)); + memParam.put("creditAmt", "" +( balance + betAmount)); + siteService.updateDemoUSer(memParam); + log.warn("DEMO BALANCE memParam {}", memParam.toString()); + return bombReponseVo; + + + + } + + + + +} diff --git a/src/main/java/com/bb/front/CallBackBtiController.java b/src/main/java/com/bb/front/CallBackBtiController.java new file mode 100644 index 0000000..da6f0e9 --- /dev/null +++ b/src/main/java/com/bb/front/CallBackBtiController.java @@ -0,0 +1,1682 @@ +package com.bb.front; + +import java.math.BigDecimal; +import java.net.URLDecoder; +import java.text.DecimalFormat; +import java.util.Date; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +import org.json.XML; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.WebClientRequestException; +import org.springframework.web.reactive.function.client.WebClientResponseException; + +import com.bb.jwt.JwtManager; +import com.bb.model.Member; +import com.bb.service.SiteService; +import com.bb.service.SplusService; +import com.bb.util.StringUtils.StringBuilderPlus; +import com.google.gson.Gson; + +import io.jsonwebtoken.ExpiredJwtException; +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import net.sf.json.JSONObject; + +@Slf4j +@Controller +@RequestMapping("/api/cb/bti") +@RequiredArgsConstructor +public class CallBackBtiController { + + @Autowired + private final JwtManager jwtManager; + + @Autowired + SiteService siteService; + + @Autowired + SplusService splusService; + + @Autowired + WebClient webClient; + + @CrossOrigin(origins = "*") + @GetMapping(value = "/js/refresh") + public @ResponseBody JSONObject refreshToken(HttpServletRequest request, ModelMap model) throws Exception { + log.info("#-bti::refreshToken::___________________Request____________________________"); + Enumeration params = request.getParameterNames(); + while (params.hasMoreElements()) { + String name = (String) params.nextElement(); + String value = request.getParameter(name); + log.info("#-bti::refreshToken::" + name + "=" + value); + } + log.info("#-bti::refreshToken::___________________Request____________________________"); + + StringBuilderPlus sp = new StringBuilderPlus(); + JSONObject resData = new JSONObject(); + + try { + String base64Token = URLDecoder.decode(request.getParameter("token"), "UTF-8"); + Map authParam = new HashMap(); + + if ("F0IjoxNTE2MjM5MDIyfQ".equals(base64Token)) { + authParam.put("memberId", "007maker1"); + authParam.put("siteId", "peanuts9"); + } else if ("F0IjoxNTE1MjM3MDIyfQ".equals(base64Token)) { + authParam.put("memberId", "00Dmat02"); + authParam.put("siteId", "aplus1"); + } else { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfo(base64Token); + authParam.put("memberId", tokenInfo.getMid()); + authParam.put("siteId", tokenInfo.getSid()); + } + + // 회사정보 + HashMap siteApiInfo = siteService.getSiteApiInfoByToken(authParam); + log.info("#-bti::refreshToken::::siteApiInfo {}", siteApiInfo); + + if ("F0IjoxNTE2MjM5MDIyfQ".equals(base64Token)) { + authParam.put("siteIdx", 87); + } else if ("F0IjoxNTE1MjM3MDIyfQ".equals(base64Token)) { + authParam.put("siteIdx", 12); + } else { + authParam.put("siteIdx", siteApiInfo.get("siteIdx")); + } + + // 회원정보 + Member member = siteService.getMemberByToken(authParam); + + int res = siteService.getSplusToken(base64Token); + + DecimalFormat formatter = new DecimalFormat("0.00"); + double balance = getBalnce("#-bti::refreshToken::", siteApiInfo.get("siteCbUrl").toString(), + authParam.get("memberId").toString()); + + resData.put("status", "success"); + resData.put("balance", "" + formatter.format(new BigDecimal(balance))); + + siteService.insertToken(base64Token); + + } catch (Exception e) { + log.error("#-bti::refreshToken::::Exception :" + e.getMessage()); + resData.put("status", "failure"); + resData.put("balance", "0.00"); + } + + return resData; + } + + @GetMapping(value = "/ValidateToken", produces = MediaType.TEXT_PLAIN_VALUE) + public @ResponseBody String validateToken(HttpServletRequest request, ModelMap model) throws Exception { + log.info("#-bti::validateToken::___________________Request____________________________"); + Enumeration params = request.getParameterNames(); + while (params.hasMoreElements()) { + String name = (String) params.nextElement(); + String value = request.getParameter(name); + log.info("#-bti::validateToken::" + name + "=" + value); + } + log.info("#-bti::validateToken::___________________Request____________________________"); + + StringBuilderPlus sp = new StringBuilderPlus(); + String base64Token = URLDecoder.decode(request.getParameter("auth_token"), "UTF-8"); + // JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfo(base64Token); + + DecimalFormat formatter = new DecimalFormat("0.00"); + String logUsername = ""; + Map authParam = new HashMap(); + JwtManager.TokenInfo tokenInfo = null; + try { + tokenInfo = jwtManager.getTokenInfo(base64Token); + authParam.put("memberId", tokenInfo.getMid()); + authParam.put("siteId", tokenInfo.getSid()); + logUsername = tokenInfo.getMid(); + } catch (ExpiredJwtException ee) { + log.error("#-bti::validateToken::ExpiredJwtException::" + base64Token); + sp.appendLine("error_code=-3"); + sp.append("error_message=TokenNotValid"); + return sp.toString(); + } + + final String LOG_PREFIX = "#-bti::validateToken::" + logUsername + ":::"; + + // 회사정보 + HashMap siteApiInfo = siteService.getSiteApiInfoByToken(authParam); + if(siteApiInfo == null) { + log.error(LOG_PREFIX + "Not found site..."); + sp.appendLine("error_code=-2"); + sp.append("error_message=CustomerNotFound"); + return sp.toString(); + } + log.info(LOG_PREFIX + "siteApiInfo {}", siteApiInfo); + authParam.put("siteIdx", siteApiInfo.get("siteIdx")); + + // 회원정보 + Member member = siteService.getMemberByToken(authParam); + + if (member == null) { + log.error(LOG_PREFIX + "Not found member..."); + sp.appendLine("error_code=-2"); + sp.append("error_message=CustomerNotFound"); + return sp.toString(); + } else { + log.info(LOG_PREFIX + "Callback Url : " + siteApiInfo.get("siteCbUrl") + "/balance/sportsD"); + JSONObject members = new JSONObject(); + members.put("userId", authParam.get("memberId").toString()); + + // 회원 머니 + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/json"); + header.add("Accept", "application/json"); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + + ResponseEntity responseEntity = null; + try { + responseEntity = webClient.post() + .uri(siteApiInfo.get("siteCbUrl") + "/balance/sportsD") + .header("Content-Type", "application/json") + .header("Accept", "application/json") + .header("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36") + .bodyValue(members.toString()) + .retrieve() + .toEntity(String.class) + .block(); + + if (responseEntity != null) { + log.info(LOG_PREFIX + "status code : {}", responseEntity.getStatusCode()); + log.info(LOG_PREFIX + "body: {}", responseEntity.getBody()); + } + + org.codehaus.jettison.json.JSONObject resData = new org.codehaus.jettison.json.JSONObject(responseEntity.getBody()); + sp.appendLine("error_code=0"); + sp.appendLine("error_message=OK"); + // sp.appendLine("balance="+formatter.format(new BigDecimal(resData.getDouble("balance")*0.01))); + sp.appendLine("balance=" + formatter.format(new BigDecimal(resData.getDouble("balance")))); + sp.appendLine("cust_id=" + siteApiInfo.get("siteIdxHex").toString() + member.getMemberId()); + sp.appendLine("cust_login=" + member.getMemberNick()); + sp.appendLine("city=EN"); + sp.appendLine("country=EN"); + sp.append("currency_code=MNT"); + } catch (WebClientResponseException e) { + log.error(LOG_PREFIX + "WebClientResponseException::" + e.getStatusCode().value()); + log.error(LOG_PREFIX + "WebClientResponseException Body::" + e.getResponseBodyAsString()); + sp.appendLine("error_code=-99"); + sp.appendLine("error_message=error"); + sp.appendLine("balance=0.00"); + return sp.toString(); + } catch (WebClientRequestException e) { + Throwable cause = e.getCause(); + if (cause instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX + "ConnectTimeoutException::" + e.getMessage()); + } else if (cause instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX + "SocketTimeoutException::" + e.getMessage()); + } else if (cause instanceof InterruptedException) { + log.error(LOG_PREFIX + "InterruptedException::" + e.getMessage()); + } else { + log.error(LOG_PREFIX + "WebClientRequestException::" + e.getMessage()); + } + sp.appendLine("error_code=-99"); + sp.appendLine("error_message=error"); + sp.appendLine("balance=0.00"); + return sp.toString(); + } catch (Exception e) { + log.error(LOG_PREFIX + "Exception::" + e.getMessage()); + sp.appendLine("error_code=-99"); + sp.appendLine("error_message=error"); + sp.appendLine("balance=0.00"); + return sp.toString(); + } + } + siteService.insertToken(base64Token); + // model.put("resultStr", returnString); + + log.info(LOG_PREFIX + "Response: " + sp.toString()); + return sp.toString(); + // 활용한 응답 생성; + } + + // 베팅 예약 크레딧 차람 + @RequestMapping(value = "/reserve", produces = MediaType.TEXT_PLAIN_VALUE) + public @ResponseBody String reserve(HttpServletRequest request, @RequestBody(required = false) String parambody) + throws Exception { + log.info("#-bti::reserve::___________________Request____________________________"); + Enumeration params = request.getParameterNames(); + while (params.hasMoreElements()) { + String name = (String) params.nextElement(); + String value = request.getParameter(name); + log.info("#-bti::reserve::" + name + "=" + value); + } + log.info("#-bti::reserve::___________________Request____________________________"); + + HashMap splusParam = new HashMap(); + + StringBuilderPlus sp = new StringBuilderPlus(); + String cust_id = URLDecoder.decode(request.getParameter("cust_id"), "UTF-8"); + String reserve_id = URLDecoder.decode(request.getParameter("reserve_id"), "UTF-8"); + String amountStr = URLDecoder.decode(request.getParameter("amount"), "UTF-8"); + String agent_id = URLDecoder.decode(request.getParameter("agent_id"), "UTF-8"); + String customer_id = URLDecoder.decode(request.getParameter("customer_id"), "UTF-8"); + String memberId = cust_id.substring(3, cust_id.length()); + String purchase_id = "null"; + String req_id = "null"; + final String LOG_PREFIX = "#-bti::reserve::" + memberId + "::" + reserve_id + "::" + purchase_id+ "::" + req_id + ":::"; + + DecimalFormat formatter = new DecimalFormat("0.00"); + Map trxParam = new HashMap(); + trxParam.put("tranType", "reserve"); + trxParam.put("cust_id", cust_id); + trxParam.put("reserve_id", reserve_id); + trxParam.put("amount", amountStr); + trxParam.put("agent_id", agent_id); + trxParam.put("customer_id", cust_id); + + org.json.JSONObject paramjson = new org.json.JSONObject(); + + try { + log.info(LOG_PREFIX+ "BF::parambody : "+ parambody); + log.info(LOG_PREFIX+ "BF::parambody {}", parambody); + paramjson = XML.toJSONObject(parambody); + log.info(LOG_PREFIX+ "MF::parambody {}", paramjson.toString()); + trxParam.put("data", paramjson.toString()); + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::002"); + log.error(LOG_PREFIX+ "error {}", e.getMessage()); + } + + log.info(LOG_PREFIX+ "AF::parambody {}", paramjson.toString()); + + // 사이트정보 + HashMap ssParam = new HashMap(); + ssParam.put("siteIdx", Integer.parseInt(cust_id.substring(0, 3), 16)); + ssParam.put("memberId", cust_id.substring(3, cust_id.length())); + HashMap siteApiInfo = siteService.getSiteApiInfo(ssParam); + + if (siteApiInfo == null) { + sp.appendLine("error_code=-2"); + sp.append("error_message=CustomerNotFound"); + return sp.toString(); + } + + String siteId = siteApiInfo.get("siteId").toString(); + + Map authParam = new HashMap(); + authParam.put("memberId", memberId); + authParam.put("siteId", siteId); + + // 회사정보 + log.info(LOG_PREFIX+ "siteApiInfo {}", siteApiInfo); + authParam.put("siteIdx", siteApiInfo.get("siteIdx")); + + // 회원정보 + Member member = siteService.getMemberByToken(authParam); + if (member == null) { + log.error(LOG_PREFIX+ "Exception::Not found user"); + sp.appendLine("error_code=-2"); + sp.append("error_message=CustomerNotFound"); + return sp.toString(); + } + + int siteIdx = Integer.parseInt(siteApiInfo.get("siteIdx").toString()); + String refId = siteId + reserve_id; + Date dt = new Date(); + String trxId = "" + siteIdx + dt.getTime() + "0"; + trxParam.put("refId", refId); + trxParam.put("trx_id", trxId); + + int resCnt = splusService.getReserveCnt(trxParam); + + if(resCnt == 0) { + try { + log.info(LOG_PREFIX+ "trxParam : "+trxParam.toString()); + siteService.insertSplusTran(trxParam); + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::003"); + log.error(LOG_PREFIX+ "ERROR {}", e.getMessage()); + } + } + + double balance = getBalnce(LOG_PREFIX, siteApiInfo.get("siteCbUrl").toString(), memberId); + + if(resCnt > 0) { + log.error(LOG_PREFIX+ "reserve::중복"); + sp.appendLine("error_code=0"); + sp.appendLine("error_message=No Error"); + // sp.appendLine("balance="+formatter.format(new BigDecimal(resData.getDouble("balance") * 0.01))); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.append("trx_id=" + trxId); + return sp.toString(); + } + + long targetSiteCredit = siteService.getSiteCredit(siteApiInfo.get("siteId").toString()); + double amount = Double.parseDouble(amountStr); + + log.info(LOG_PREFIX+ "targetSiteCredit < amount {}, {}", targetSiteCredit, amount); + if (targetSiteCredit < amount && amount > 0) { + log.error(LOG_PREFIX+ "Exception::크레딧 부족"); + sp.appendLine("error_code=-4"); + sp.append("error_message=InsufficientFunds"); + return sp.toString(); + } + + if (balance < amount && amount > 0) { + log.error(LOG_PREFIX+ "Exception::유저잔액 부족"); + sp.appendLine("error_code=-4"); + sp.appendLine("error_message=InsufficientFunds"); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.append("trx_id=" + trxId); + return sp.toString(); + } + + // 최대베팅액 (userMaxBet 우선 적용) + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", member.getMemberId()); + sParam.put("vendorIdx", 84); + long maxBet = siteService.getSiteMaxBet(sParam); + + // userMaxBet 조회 + long userMaxBet = 0; + Long userMaxBetObj = siteService.getUserMaxBet(sParam); + if(userMaxBetObj != null) { + userMaxBet = userMaxBetObj; + } + + // 최종 maxBet 결정: userMaxBet이 0이면 siteMaxBet 사용, 0이 아니면 userMaxBet 사용 + long finalMaxBet = (userMaxBet > 0) ? userMaxBet : maxBet; + log.info(LOG_PREFIX+ "MaxBet Info - siteMaxBet: " + maxBet + ", userMaxBet: " + userMaxBet + ", finalMaxBet: " + finalMaxBet); + + double maxBetD = finalMaxBet; + if (amount > maxBetD) { + log.error(LOG_PREFIX+ "Exception::최대 베팅금 초과 - finalMaxBet: " + finalMaxBet); + sp.appendLine("error_code=-10"); + sp.append("error_message= max bet limit - overBet"); + return sp.toString(); + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", refId + "#R"); + tranParam.put("refId", refId); + tranParam.put("siteIdx", siteApiInfo.get("siteIdx")); + tranParam.put("siteId", siteId); + tranParam.put("completed", true); + tranParam.put("memberIdx", member.getMemberIdx()); + tranParam.put("memberId", member.getMemberId()); + tranParam.put("vendorCetegory", "SPORT"); + tranParam.put("vendorIdx", 84); + tranParam.put("vendorCode", "bti_zeno"); + tranParam.put("vendorTranKey", reserve_id + "#R"); + tranParam.put("gameType", ""); + tranParam.put("gameId", ""); + tranParam.put("gameIdx", ""); + tranParam.put("tranType", "debit"); + tranParam.put("depositAmt", amount); + tranParam.put("creditAmt", "0"); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", ""); + siteService.commonBetinsert(tranParam); + + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/json"); + header.add("Accept", "application/json"); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + JSONObject debit = new JSONObject(); + double fakeAmount = amount;// *100; + debit.put("betId", refId); + debit.put("tranId", refId + "#R"); + + debit.put("userId", member.getMemberId()); + debit.put("vendorIdx", 84); + debit.put("vendorKey", "SP3"); + debit.put("vendor", "bti_zeno"); + debit.put("gameIdx", 1); + debit.put("gameKey", ""); + debit.put("gameId", ""); + debit.put("gameType", ""); + debit.put("tranType", "debit"); + debit.put("debit", fakeAmount); + debit.put("credit", 0); + debit.put("isCancel", 0); + debit.put("isBonus", 0); + debit.put("decYn", "Y"); + + HashMap detailMap = new Gson().fromJson(paramjson.toString(), HashMap.class); + debit.put("status", "bet"); + debit.put("detail", detailMap); + + log.info(LOG_PREFIX+ "Callback Request: "+debit.toString()); + ResponseEntity responseEntity = null; + try { + responseEntity = webClient.post() + .uri(siteApiInfo.get("siteCbUrl") + "/changebalance/sportsD") + .header("Content-Type", "application/json") + .header("Accept", "application/json") + .header("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36") + .bodyValue(debit.toString()) + .retrieve() + .toEntity(String.class) + .block(); + + org.codehaus.jettison.json.JSONObject resData = new org.codehaus.jettison.json.JSONObject( + responseEntity.getBody()); + + log.info(LOG_PREFIX+ "Callback Response: "+resData.toString()); + + if (resData.getLong("result_code") == 0) { + trxParam.put("tranId", tranParam.get("tranId").toString()); + trxParam.put("resData", resData.toString()); + trxParam.put("cbResultCode", resData.get("result_code").toString()); + siteService.updateSplusTran(trxParam); + + sp.appendLine("error_code=0"); + sp.appendLine("error_message=No Error"); + // sp.appendLine("balance="+formatter.format(new BigDecimal(resData.getDouble("balance") * 0.01))); + sp.appendLine("balance=" + formatter.format(new BigDecimal(resData.getDouble("balance")))); + sp.append("trx_id=" + trxId); + tranParam.put("balance", resData.getDouble("balance")); + int res = siteService.updateCbApi(tranParam); + + splusService.insertSplus(tranParam, paramjson); + + } else { + log.info(LOG_PREFIX+ "Callback Error: "+resData.toString()); + sp.appendLine("error_code=-99"); + sp.appendLine("error_message=error"); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.append("trx_id=" + trxId); + } + } catch (WebClientResponseException e) { + log.error(LOG_PREFIX + "WebClientResponseException::" + e.getStatusCode().value()); + log.error(LOG_PREFIX + "WebClientResponseException Body::" + e.getResponseBodyAsString()); + sp.appendLine("error_code=-99"); + sp.appendLine("error_message=error"); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.append("trx_id=" + trxId); + } catch (WebClientRequestException e) { + Throwable cause = e.getCause(); + if (cause instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX + "ConnectTimeoutException::" + e.getMessage()); + } else if (cause instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX + "SocketTimeoutException::" + e.getMessage()); + } else if (cause instanceof InterruptedException) { + log.error(LOG_PREFIX + "InterruptedException::" + e.getMessage()); + } else { + log.error(LOG_PREFIX + "WebClientRequestException::" + e.getMessage()); + } + sp.appendLine("error_code=-99"); + sp.appendLine("error_message=error"); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.append("trx_id=" + trxId); + } catch (Exception e) { + log.error(LOG_PREFIX + "Exception::" + e.getMessage()); + sp.appendLine("error_code=-99"); + sp.appendLine("error_message=error"); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.append("trx_id=" + trxId); + } + + log.info(LOG_PREFIX + "Response: " + sp.toString()); + return sp.toString(); // 활용한 응답 생성; + } + + // 베팅 예약 취소 크레딧 복구 + @GetMapping(value = "/cancelreserve", produces = MediaType.TEXT_PLAIN_VALUE) + public @ResponseBody String cancelReserve(HttpServletRequest request) throws Exception { + log.info("#-bti::cancelReserve::___________________Request____________________________"); + Enumeration params = request.getParameterNames(); + while (params.hasMoreElements()) { + String name = (String) params.nextElement(); + String value = request.getParameter(name); + log.info("#-bti::cancelReserve::" + name + "=" + value); + } + log.info("#-bti::cancelReserve::___________________Request____________________________"); + + DecimalFormat formatter = new DecimalFormat("0.00"); + StringBuilderPlus sp = new StringBuilderPlus(); + String cust_id = URLDecoder.decode(request.getParameter("cust_id"), "UTF-8"); + String reserve_id = URLDecoder.decode(request.getParameter("reserve_id"), "UTF-8"); + String agent_id = URLDecoder.decode(request.getParameter("agent_id"), "UTF-8"); + String customer_id = URLDecoder.decode(request.getParameter("customer_id"), "UTF-8"); + String memberId = cust_id.substring(3, cust_id.length()); + String purchase_id = "null"; + String req_id = "null"; + final String LOG_PREFIX = "#-bti::cancelReserve::" + memberId + "::" + reserve_id + "::" + purchase_id+ "::" + req_id + ":::"; + + Map trxParam = new HashMap(); + trxParam.put("tranType", "cancelReserve"); + trxParam.put("cust_id", cust_id); + trxParam.put("reserve_id", reserve_id); + trxParam.put("agent_id", agent_id); + trxParam.put("customer_id", customer_id); + + // 사이트정보 + HashMap ssParam = new HashMap(); + ssParam.put("siteIdx", Integer.parseInt(cust_id.substring(0, 3), 16)); + ssParam.put("memberId", cust_id.substring(3, cust_id.length())); + + HashMap siteApiInfo = siteService.getSiteApiInfo(ssParam); + if (siteApiInfo == null) { + log.error(LOG_PREFIX+ "Error:: siteApiInfo null"); + sp.appendLine("error_code=-2"); + sp.append("error_message=CustomerNotFound"); + return sp.toString(); + } + + String siteId = siteApiInfo.get("siteId").toString(); + Map authParam = new HashMap(); + authParam.put("memberId", memberId); + authParam.put("siteId", siteId); + + // 회사정보 + log.info(LOG_PREFIX+ "siteApiInfo {}", siteApiInfo); + authParam.put("siteIdx", siteApiInfo.get("siteIdx")); + + // 회원정보 + Member member = siteService.getMemberByToken(authParam); + if (member == null) { + log.error(LOG_PREFIX+ "Error:: Member null"); + sp.appendLine("error_code=-2"); + sp.append("error_message=CustomerNotFound"); + return sp.toString(); + } + int siteIdx = Integer.parseInt(siteApiInfo.get("siteIdx").toString()); + String refId = siteId + reserve_id; + Date dt = new Date(); + String trxId = "" + siteIdx + dt.getTime() + "9"; + trxParam.put("refId", refId); + trxParam.put("trx_id", trxId); + + double balance = getBalnce(LOG_PREFIX, siteApiInfo.get("siteCbUrl").toString(), memberId); + long targetSiteCredit = siteService.getSiteCredit(siteApiInfo.get("siteId").toString()); + + log.info(LOG_PREFIX+ "refId : "+refId + "#R"); + double amount = siteService.getBetDepositAmt(refId + "#R"); + log.info(LOG_PREFIX+ "amount :" + amount); + trxParam.put("amount", amount); + + int resCnt = splusService.getReserveCnt(trxParam); + + if(resCnt == 0) { + try { + log.info(LOG_PREFIX+ "trxParam : "+trxParam.toString()); + siteService.insertSplusTran(trxParam); + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::003"); + log.error(LOG_PREFIX+ "ERROR {}", e.getMessage()); + } + } + + if(resCnt > 0) { + log.error(LOG_PREFIX+ "cancelReserve::중복"); + sp.appendLine("error_code=0"); + sp.appendLine("error_message=No Error"); + // sp.appendLine("balance="+formatter.format(new BigDecimal(resData.getDouble("balance") * 0.01))); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.append("trx_id=" + trxId); + return sp.toString(); + } + + if (amount == 0.0) { + log.error(LOG_PREFIX+ "Error:: amount 0"); + sp.appendLine("error_code=0"); + sp.appendLine("error_message=ReserveID not exists"); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + return sp.toString(); + } + + log.info(LOG_PREFIX+ "amount:{}, balance:{}", amount, balance); + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", refId + "#C"); + tranParam.put("refId", refId); + tranParam.put("siteIdx", siteApiInfo.get("siteIdx")); + tranParam.put("siteId", siteId); + tranParam.put("completed", true); + tranParam.put("memberIdx", member.getMemberIdx()); + tranParam.put("memberId", member.getMemberId()); + tranParam.put("vendorCetegory", "SPORT"); + tranParam.put("vendorIdx", 84); + tranParam.put("vendorCode", "bti_zeno"); + tranParam.put("vendorTranKey", reserve_id + "#C"); + tranParam.put("gameType", ""); + tranParam.put("gameId", ""); + tranParam.put("gameIdx", ""); + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + tranParam.put("isCancel", "Y"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", ""); + siteService.commonBetinsert(tranParam); + + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/json"); + header.add("Accept", "application/json"); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + JSONObject debit = new JSONObject(); + double fakeAmount = amount;// *100; + debit.put("betId", refId); + debit.put("tranId", refId + "#C"); + debit.put("userId", member.getMemberId()); + debit.put("vendorIdx", 84); + debit.put("vendorKey", "SP3"); + debit.put("vendor", "bti_zeno"); + debit.put("gameIdx", 1); + debit.put("gameKey", ""); + debit.put("gameType", ""); + debit.put("gameId", ""); + debit.put("tranType", "credit"); + debit.put("debit", 0); + debit.put("credit", fakeAmount); + debit.put("isCancel", 1); + debit.put("isBonus", 0); + debit.put("status", "betCancel"); + debit.put("decYn", "Y"); + + log.info(LOG_PREFIX+ "Callback Request: "+debit.toString()); + ResponseEntity responseEntity = null; + org.codehaus.jettison.json.JSONObject resData = null; + try { + responseEntity = webClient.post() + .uri(siteApiInfo.get("siteCbUrl") + "/changebalance/sportsD") + .header("Content-Type", "application/json") + .header("Accept", "application/json") + .header("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36") + .bodyValue(debit.toString()) + .retrieve() + .toEntity(String.class) + .block(); + + resData = new org.codehaus.jettison.json.JSONObject( + responseEntity.getBody()); + log.info(LOG_PREFIX+ "Callback Response: "+resData.toString()); + + if (resData.getLong("result_code") == 0) { + sp.appendLine("error_code=0"); + sp.appendLine("error_message=No Error "); + // sp.appendLine("balance="+formatter.format(new BigDecimal(resData.getDouble("balance") * 0.01))); + sp.appendLine("balance=" + formatter.format(new BigDecimal(resData.getDouble("balance")))); + sp.appendLine("trx_id=" + trxId); + + tranParam.put("balance", resData.getDouble("balance")); + int res = siteService.updateCbApi(tranParam); + } else { + log.error(LOG_PREFIX+ "Callback Error::" + resData.toString()); + sp.appendLine("error_code=0"); + sp.appendLine("error_message=error"); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.appendLine("trx_id=" + trxId); + } + + trxParam.put("tranId", tranParam.get("tranId").toString()); + trxParam.put("resData", resData.toString()); + + siteService.updateSplusTran(trxParam); + splusService.cancelSplus(tranParam); + } catch (WebClientResponseException e) { + log.error(LOG_PREFIX + "WebClientResponseException::" + e.getStatusCode().value()); + log.error(LOG_PREFIX + "WebClientResponseException Body::" + e.getResponseBodyAsString()); + log.error(LOG_PREFIX + "Callback Error::" + e.toString()); + sp.appendLine("error_code=0"); + sp.appendLine("error_message=error"); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.appendLine("trx_id=" + trxId); + } catch (WebClientRequestException e) { + Throwable cause = e.getCause(); + if (cause instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX + "ConnectTimeoutException::" + e.getMessage()); + } else if (cause instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX + "SocketTimeoutException::" + e.getMessage()); + } else if (cause instanceof InterruptedException) { + log.error(LOG_PREFIX + "InterruptedException::" + e.getMessage()); + } else { + log.error(LOG_PREFIX + "WebClientRequestException::" + e.getMessage()); + } + sp.appendLine("error_code=0"); + sp.appendLine("error_message=error"); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.appendLine("trx_id=" + trxId); + } catch (Exception e) { + log.error(LOG_PREFIX + "Exception::" + e.getMessage()); + sp.appendLine("error_code=0"); + sp.appendLine("error_message=error"); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.appendLine("trx_id=" + trxId); + } + + log.info(LOG_PREFIX + "Response: " + sp.toString()); + return sp.toString(); // 활용한 응답 생성; + } + + + // 뭔지 잘 모르겠슴 + @GetMapping(value = "/commitreserve", produces = MediaType.TEXT_PLAIN_VALUE) + public @ResponseBody String commitReserve(HttpServletRequest request) throws Exception { + log.info("#-bti::commitReserve::___________________Request____________________________"); + Enumeration params = request.getParameterNames(); + while (params.hasMoreElements()) { + String name = (String) params.nextElement(); + String value = request.getParameter(name); + log.info("#-bti::commitReserve::" + name + "=" + value); + } + log.info("#-bti::commitReserve::___________________Request____________________________"); + + DecimalFormat formatter = new DecimalFormat("0.00"); + StringBuilderPlus sp = new StringBuilderPlus(); + String cust_id = URLDecoder.decode(request.getParameter("cust_id"), "UTF-8"); + String reserve_id = URLDecoder.decode(request.getParameter("reserve_id"), "UTF-8"); + String agent_id = URLDecoder.decode(request.getParameter("agent_id"), "UTF-8"); + String customer_id = URLDecoder.decode(request.getParameter("customer_id"), "UTF-8"); + String purchase_id = URLDecoder.decode(request.getParameter("purchase_id"), "UTF-8"); + String memberId = cust_id.substring(3, cust_id.length()); + String req_id = "null"; + final String LOG_PREFIX = "#-bti::commitReserve::" + memberId + "::" + reserve_id + "::" + purchase_id+ "::" + req_id + ":::"; + + Map trxParam = new HashMap(); + trxParam.put("tranType", "commitReserve"); + trxParam.put("cust_id", cust_id); + trxParam.put("reserve_id", reserve_id); + trxParam.put("agent_id", agent_id); + trxParam.put("customer_id", customer_id); + trxParam.put("purchase_id", purchase_id); + + // 사이트정보 + HashMap ssParam = new HashMap(); + ssParam.put("siteIdx", Integer.parseInt(cust_id.substring(0, 3), 16)); + ssParam.put("memberId", cust_id.substring(3, cust_id.length())); + + HashMap siteApiInfo = siteService.getSiteApiInfo(ssParam); + if (siteApiInfo == null) { + log.error(LOG_PREFIX+ "Error:: siteApiInfo null"); + sp.appendLine("error_code=-1"); + sp.append("error_message=CustomerNotFound"); + return sp.toString(); + } + + String siteId = siteApiInfo.get("siteId").toString(); + Map authParam = new HashMap(); + authParam.put("memberId", memberId); + authParam.put("siteId", siteId); + + // 회사정보 + log.info(LOG_PREFIX + "siteApiInfo {}", siteApiInfo); + authParam.put("siteIdx", siteApiInfo.get("siteIdx")); + + // 회원정보 + Member member = siteService.getMemberByToken(authParam); + if (member == null) { + log.error(LOG_PREFIX+ "Error:: member null"); + sp.appendLine("error_code=-1"); + sp.append("error_message=CustomerNotFound"); + return sp.toString(); + } + + int siteIdx = Integer.parseInt(siteApiInfo.get("siteIdx").toString()); + String refId = siteId + reserve_id; + Date dt = new Date(); + String trxId = "" + siteIdx + dt.getTime() + "1"; + trxParam.put("refId", refId); + trxParam.put("trx_id", trxId); + + double amount = siteService.getBetDepositAmt(refId + "#R"); + double gap = siteService.getBetGapAmt(purchase_id); + double balance = getBalnce(LOG_PREFIX, siteApiInfo.get("siteCbUrl").toString(), memberId); + + int cmtCnt = splusService.getCommitCnt(trxParam); + if(cmtCnt > 0) { + log.error(LOG_PREFIX+ "commitReserve::중복"); + sp.appendLine("error_code=0"); + sp.appendLine("error_message=No Error"); + // sp.appendLine("balance="+formatter.format(new BigDecimal(resData.getDouble("balance") * 0.01))); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.append("trx_id=" + trxId); + return sp.toString(); + } + +// if (amount == 0.0) { +// log.error(LOG_PREFIX+ "Error:: amount 0"); +// sp.appendLine("error_code=-20"); +// sp.appendLine("error_message=ReserveNotFound"); +// sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); +// return sp.toString(); +// } + + if (gap > 0 && gap < amount) { + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", refId + "#CR"); + tranParam.put("refId", refId); + tranParam.put("siteIdx", siteApiInfo.get("siteIdx")); + tranParam.put("siteId", siteId); + tranParam.put("completed", true); + tranParam.put("memberIdx", member.getMemberIdx()); + tranParam.put("memberId", member.getMemberId()); + tranParam.put("vendorCetegory", "SPORT"); + tranParam.put("vendorIdx", 84); + tranParam.put("vendorCode", "bti_zeno"); + tranParam.put("vendorTranKey", purchase_id + "#CR"); + tranParam.put("gameType", ""); + tranParam.put("gameId", ""); + tranParam.put("gameIdx", ""); + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", gap); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", ""); + siteService.commonBetinsert(tranParam); + + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/json"); + header.add("Accept", "application/json"); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + JSONObject debit = new JSONObject(); + double fakeAmount = gap;// *100; + debit.put("betId", refId); + debit.put("tranId", refId + "#CR"); + debit.put("userId", member.getMemberId()); + debit.put("vendorIdx", 84); + debit.put("vendorKey", "SP3"); + debit.put("vendor", "bti_zeno"); + debit.put("gameIdx", 1); + debit.put("gameKey", ""); + debit.put("gameType", ""); + debit.put("gameId", ""); + debit.put("tranType", "credit"); + debit.put("debit", 0); + debit.put("credit", fakeAmount); + debit.put("isCancel", 0); + debit.put("isBonus", 0); + debit.put("decYn", "Y"); + debit.put("status", "commitReserve"); + + log.info(LOG_PREFIX+ "Callback Request: "+debit.toString()); + ResponseEntity responseEntity = null; + try { + responseEntity = webClient.post() + .uri(siteApiInfo.get("siteCbUrl") + "/changebalance/sportsD") + .header("Content-Type", "application/json") + .header("Accept", "application/json") + .header("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36") + .bodyValue(debit.toString()) + .retrieve() + .toEntity(String.class) + .block(); + + org.codehaus.jettison.json.JSONObject resData = new org.codehaus.jettison.json.JSONObject( + responseEntity.getBody()); + log.info(LOG_PREFIX+ "Callback Response: "+resData.toString()); + + balance = resData.getDouble("balance");// *0.01; + + tranParam.put("balance", resData.getDouble("balance")); + int res = siteService.updateCbApi(tranParam); + } catch (WebClientResponseException e) { + log.error(LOG_PREFIX + "WebClientResponseException::" + e.getStatusCode().value()); + log.error(LOG_PREFIX + "WebClientResponseException Body::" + e.getResponseBodyAsString()); + } catch (WebClientRequestException e) { + Throwable cause = e.getCause(); + if (cause instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX + "ConnectTimeoutException::" + e.getMessage()); + } else if (cause instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX + "SocketTimeoutException::" + e.getMessage()); + } else if (cause instanceof InterruptedException) { + log.error(LOG_PREFIX + "InterruptedException::" + e.getMessage()); + } else { + log.error(LOG_PREFIX + "WebClientRequestException::" + e.getMessage()); + } + } catch (Exception e) { + log.error(LOG_PREFIX + "Exception::" + e.getMessage()); + } + + } + + trxParam.put("amount", gap); + try { + log.info(LOG_PREFIX+ "trxParam : "+trxParam.toString()); + siteService.insertSplusTran(trxParam); + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::003"); + log.error(LOG_PREFIX+ "ERROR {}", e.getMessage()); + } + + sp.appendLine("error_code=0"); + sp.appendLine("error_message=No Error "); + // sp.appendLine("balance="+formatter.format(new BigDecimal(resData.getDouble("balance") * 0.01))); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.appendLine("trx_id=" + trxId); + + log.info(LOG_PREFIX + "Response: " + sp.toString()); + return sp.toString(); // 활용한 응답 생성; + } + + // 뭔지 잘 모르겠슴 + @RequestMapping(value = "/debitreserve", produces = MediaType.TEXT_PLAIN_VALUE) + public @ResponseBody String debitReserve(HttpServletRequest request, + @RequestBody(required = false) String parambody) throws Exception { + log.info("#-bti::debitReserve::___________________Request____________________________"); + Enumeration params = request.getParameterNames(); + while (params.hasMoreElements()) { + String name = (String) params.nextElement(); + String value = request.getParameter(name); + log.info("#-bti::debitReserve::" + name + "=" + value); + } + log.info("#-bti::debitReserve::___________________Request____________________________"); + + DecimalFormat formatter = new DecimalFormat("0.00"); + StringBuilderPlus sp = new StringBuilderPlus(); + String cust_id = URLDecoder.decode(request.getParameter("cust_id"), "UTF-8"); + String reserve_id = URLDecoder.decode(request.getParameter("reserve_id"), "UTF-8"); + String req_id = URLDecoder.decode(request.getParameter("req_id"), "UTF-8"); + String amountStr = URLDecoder.decode(request.getParameter("amount"), "UTF-8"); + String agent_id = URLDecoder.decode(request.getParameter("agent_id"), "UTF-8"); + String customer_id = URLDecoder.decode(request.getParameter("customer_id"), "UTF-8"); + String purchase_id = URLDecoder.decode(request.getParameter("purchase_id"), "UTF-8"); + String memberId = cust_id.substring(3, cust_id.length()); + final String LOG_PREFIX = "#-bti::debitReserve::" + memberId + "::" + reserve_id + "::" + purchase_id+ "::" + req_id + ":::"; + + Map trxParam = new HashMap(); + trxParam.put("tranType", "debitReserve"); + trxParam.put("cust_id", cust_id); + trxParam.put("req_id", req_id); + trxParam.put("reserve_id", reserve_id); + trxParam.put("amount", amountStr); + trxParam.put("agent_id", agent_id); + trxParam.put("customer_id", customer_id); + trxParam.put("purchase_id", purchase_id); + try { + log.info(LOG_PREFIX+ "BF::parambody : "+ parambody); + log.info(LOG_PREFIX+ "BF::parambody {}", parambody); + org.json.JSONObject paramjson = XML.toJSONObject(parambody); + log.info(LOG_PREFIX+ "AF::parambody {}", paramjson.toString()); + trxParam.put("data", paramjson.toString()); + } catch (Exception e) { + log.info(LOG_PREFIX+ "error {}", e.getMessage()); + } + + // 사이트정보 + HashMap ssParam = new HashMap(); + ssParam.put("siteIdx", Integer.parseInt(cust_id.substring(0, 3), 16)); + ssParam.put("memberId", cust_id.substring(3, cust_id.length())); + HashMap siteApiInfo = siteService.getSiteApiInfo(ssParam); + if (siteApiInfo == null) { + sp.appendLine("error_code=0"); + sp.append("error_message=CustomerNotFound"); + return sp.toString(); + } + + String siteId = siteApiInfo.get("siteId").toString(); + Map authParam = new HashMap(); + authParam.put("memberId", memberId); + authParam.put("siteId", siteId); + + // 회사정보 + log.info(LOG_PREFIX+ "siteApiInfo {}", siteApiInfo); + authParam.put("siteIdx", siteApiInfo.get("siteIdx")); + + // 회원정보 + Member member = siteService.getMemberByToken(authParam); + if (member == null) { + sp.appendLine("error_code=0"); + sp.append("error_message=CustomerNotFound"); + return sp.toString(); + } + + int siteIdx = Integer.parseInt(siteApiInfo.get("siteIdx").toString()); + String refId = siteId + reserve_id; + Date dt = new Date(); + String trxId = "" + siteIdx + dt.getTime() + "1"; + trxParam.put("refId", refId); + trxParam.put("trx_id", trxId); + + double balance = 0.0; + try { + String cbData = siteService.getCbData(reserve_id); + org.codehaus.jettison.json.JSONObject cbDataJson = new org.codehaus.jettison.json.JSONObject(cbData); + balance = cbDataJson.getDouble("balance");// *0.01; + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::001"); + log.error(LOG_PREFIX+ "Exception::" + e.getMessage()); + balance = getBalnce(LOG_PREFIX, siteApiInfo.get("siteCbUrl").toString(), memberId); + } + + int deReverseCnt = splusService.getDeReverseCnt(trxParam); + if(deReverseCnt > 0) { + log.error(LOG_PREFIX+ "debitReserve::중복"); + sp.appendLine("error_code=0"); + sp.appendLine("error_message=No Error"); + // sp.appendLine("balance="+formatter.format(new BigDecimal(resData.getDouble("balance") * 0.01))); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.append("trx_id=" + trxId); + return sp.toString(); + } + + try { + log.info(LOG_PREFIX+ "trxParam : "+trxParam.toString()); + siteService.insertSplusTran(trxParam); + siteService.updatesPurchaseId(trxParam); + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::003"); + log.error(LOG_PREFIX+ "ERROR {}", e.getMessage()); + } + + // 구매아이디 보내주기 + try { + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/json"); + header.add("Accept", "application/json"); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + JSONObject debit = new JSONObject(); + + debit.put("betId", refId); + debit.put("purchaseId", purchase_id); + + log.info(LOG_PREFIX+ "Callback Request: "+debit.toString()); + try { + ResponseEntity responseEntity = webClient.post() + .uri(siteApiInfo.get("siteCbUrl") + "/purchaseId") + .header("Content-Type", "application/json") + .header("Accept", "application/json") + .header("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36") + .bodyValue(debit.toString()) + .retrieve() + .toEntity(String.class) + .block(); + + org.codehaus.jettison.json.JSONObject resData = new org.codehaus.jettison.json.JSONObject( + responseEntity.getBody()); + log.info(LOG_PREFIX+ "Callback Response: "+resData.toString()); + } catch (WebClientResponseException e) { + log.error(LOG_PREFIX + "WebClientResponseException::" + e.getStatusCode().value()); + log.error(LOG_PREFIX + "WebClientResponseException Body::" + e.getResponseBodyAsString()); + } catch (WebClientRequestException e) { + Throwable cause = e.getCause(); + if (cause instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX + "ConnectTimeoutException::" + e.getMessage()); + } else if (cause instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX + "SocketTimeoutException::" + e.getMessage()); + } else if (cause instanceof InterruptedException) { + log.error(LOG_PREFIX + "InterruptedException::" + e.getMessage()); + } else { + log.error(LOG_PREFIX + "WebClientRequestException::" + e.getMessage()); + } + } + + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::002"); + log.error(LOG_PREFIX+ "Exception::" + e.getMessage()); + } + + sp.appendLine("error_code=0"); + sp.appendLine("error_message=No Error "); + // sp.appendLine("balance="+formatter.format(new BigDecimal(resData.getDouble("balance") * 0.01))); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.appendLine("trx_id=" + trxId); + + log.info(LOG_PREFIX + "Response: " + sp.toString()); + return sp.toString(); // 활용한 응답 생성; + } + + + // 베팅 예약 크레딧 차람 + @RequestMapping(value = "/debitcustomer", produces = MediaType.TEXT_PLAIN_VALUE) + public @ResponseBody String debitCustomer(HttpServletRequest request, + @RequestBody(required = false) String parambody) throws Exception { + log.info("#-bti::debitCustomer::___________________Request____________________________"); + Enumeration params = request.getParameterNames(); + while (params.hasMoreElements()) { + String name = (String) params.nextElement(); + String value = request.getParameter(name); + log.info("#-bti::debitCustomer::" + name + "=" + value); + } + log.info("#-bti::debitCustomer::___________________Request____________________________"); + + DecimalFormat formatter = new DecimalFormat("0.00"); + StringBuilderPlus sp = new StringBuilderPlus(); + String cust_id = URLDecoder.decode(request.getParameter("cust_id"), "UTF-8"); + String req_id = URLDecoder.decode(request.getParameter("req_id"), "UTF-8"); + String purchase_id = URLDecoder.decode(request.getParameter("purchase_id"), "UTF-8"); + String amountStr = URLDecoder.decode(request.getParameter("amount"), "UTF-8"); + String agent_id = URLDecoder.decode(request.getParameter("agent_id"), "UTF-8"); + String customer_id = URLDecoder.decode(request.getParameter("customer_id"), "UTF-8"); + String memberId = cust_id.substring(3, cust_id.length()); + String reserveId = siteService.getRefIdByPurchaseId(purchase_id); + final String LOG_PREFIX = "#-bti::debitCustomer::" + memberId + "::" + reserveId + "::" + purchase_id+ "::" + req_id + ":::"; + + Map trxParam = new HashMap(); + trxParam.put("tranType", "debitCustomer"); + trxParam.put("cust_id", cust_id); + trxParam.put("reserve_id", reserveId); + trxParam.put("req_id", req_id); + trxParam.put("purchase_id", purchase_id); + trxParam.put("amount", amountStr); + trxParam.put("agent_id", agent_id); + trxParam.put("customer_id", cust_id); + + org.json.JSONObject paramjson = new org.json.JSONObject(); + try { + log.info(LOG_PREFIX+ "BF::parambody : "+ parambody); + log.info(LOG_PREFIX+ "BF::parambody {}", parambody); + paramjson = XML.toJSONObject(parambody); + log.info(LOG_PREFIX+ "MF::parambody {}", paramjson.toString()); + + trxParam.put("data", paramjson.toString()); + log.info(LOG_PREFIX+ "AF::parambody {}", paramjson.toString()); + } catch (Exception e) { + log.info(LOG_PREFIX+ "error {}", e.getMessage()); + } + + // 사이트정보 + HashMap ssParam = new HashMap(); + ssParam.put("siteIdx", Integer.parseInt(cust_id.substring(0, 3), 16)); + ssParam.put("memberId", cust_id.substring(3, cust_id.length())); + HashMap siteApiInfo = siteService.getSiteApiInfo(ssParam); + if (siteApiInfo == null) { + sp.appendLine("error_code=0"); + sp.append("error_message=CustomerNotFound"); + return sp.toString(); + } + + String siteId = siteApiInfo.get("siteId").toString(); + Map authParam = new HashMap(); + authParam.put("memberId", memberId); + authParam.put("siteId", siteId); + + // 회사정보 + log.info(LOG_PREFIX+ "siteApiInfo {}", siteApiInfo); + authParam.put("siteIdx", siteApiInfo.get("siteIdx")); + + // 회원정보 + Member member = siteService.getMemberByToken(authParam); + if (member == null) { + sp.appendLine("error_code=0"); + sp.append("error_message=CustomerNotFound"); + return sp.toString(); + } + + int siteIdx = Integer.parseInt(siteApiInfo.get("siteIdx").toString()); + String refId = siteId + reserveId; + Date dt = new Date(); + String trxId = "" + siteIdx + dt.getTime() + "3"; + trxParam.put("trxId", trxId); + trxParam.put("refId", refId + "#DC"); + + double balance = getBalnce(LOG_PREFIX, siteApiInfo.get("siteCbUrl").toString(), memberId); + long targetSiteCredit = siteService.getSiteCredit(siteApiInfo.get("siteId").toString()); + double amount = Double.parseDouble(amountStr); + + int custCnt = splusService.getCustomerCnt(trxParam); + if(custCnt > 0) { + log.error(LOG_PREFIX+ "debitCustomer::중복"); + sp.appendLine("error_code=0"); + sp.appendLine("error_message=No Error"); + // sp.appendLine("balance="+formatter.format(new BigDecimal(resData.getDouble("balance") * 0.01))); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.append("trx_id=" + trxId); + return sp.toString(); + } + + try { + log.info(LOG_PREFIX+ "trxParam : "+trxParam.toString()); + siteService.insertSplusTran(trxParam); + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::003"); + log.error(LOG_PREFIX+ "ERROR {}", e.getMessage()); + } + + if (member == null) { + sp.appendLine("error_code=-2"); + sp.append("error_message=not validateToken"); + + return sp.toString(); + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", refId + "#DC"); + tranParam.put("refId", refId + "#DC"); + tranParam.put("siteIdx", siteApiInfo.get("siteIdx")); + tranParam.put("siteId", siteId); + tranParam.put("completed", true); + tranParam.put("memberIdx", member.getMemberIdx()); + tranParam.put("memberId", member.getMemberId()); + tranParam.put("vendorCetegory", "SPORT"); + tranParam.put("vendorIdx", 84); + tranParam.put("vendorCode", "bti_zeno"); + tranParam.put("vendorTranKey", purchase_id + "#DC"); + tranParam.put("gameType", ""); + tranParam.put("gameId", ""); + tranParam.put("gameIdx", ""); + tranParam.put("tranType", "debit"); + tranParam.put("depositAmt", amount); + tranParam.put("creditAmt", "0"); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", ""); + siteService.commonBetinsert(tranParam); + + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/json"); + header.add("Accept", "application/json"); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + JSONObject debit = new JSONObject(); + double fakeAmount = amount;// *100; + debit.put("betId", refId + "#DC"); + debit.put("tranId", refId + "#DC"); + debit.put("userId", member.getMemberId()); + debit.put("vendorIdx", 84); + debit.put("vendorKey", "SP3"); + debit.put("vendor", "bti_zeno"); + debit.put("gameIdx", 1); + debit.put("gameKey", ""); + debit.put("gameType", ""); + debit.put("gameId", ""); + debit.put("tranType", "debit"); + debit.put("debit", fakeAmount); + debit.put("credit", 0); + debit.put("isCancel", 0); + debit.put("isBonus", 0); + debit.put("minusBalanceYn", "Y"); + HashMap detailMap = new Gson().fromJson(paramjson.toString(), HashMap.class); + debit.put("status", "debitCustomer"); + debit.put("detail", detailMap); + + log.info(LOG_PREFIX+ "Callback Request: "+debit.toString()); + ResponseEntity responseEntity = null; + try { + responseEntity = webClient.post() + .uri(siteApiInfo.get("siteCbUrl") + "/changebalance/sportsD") + .header("Content-Type", "application/json") + .header("Accept", "application/json") + .header("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36") + .bodyValue(debit.toString()) + .retrieve() + .toEntity(String.class) + .block(); + org.codehaus.jettison.json.JSONObject resData = new org.codehaus.jettison.json.JSONObject( + responseEntity.getBody()); + log.info(LOG_PREFIX+ "Callback Response: "+resData.toString()); + + if (resData.getLong("result_code") == 0) { + sp.appendLine("error_code=0"); + sp.appendLine("error_message=No Error "); + // sp.appendLine("balance="+formatter.format(new BigDecimal(resData.getDouble("balance") * 0.01))); + sp.appendLine("balance=" + formatter.format(new BigDecimal(resData.getDouble("balance")))); + sp.appendLine("trx_id=" + trxId); + + tranParam.put("balance", resData.getDouble("balance")); + int res = siteService.updateCbApi(tranParam); + } else { + sp.appendLine("error_code=0"); + sp.appendLine("error_message=error"); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.appendLine("trx_id=" + trxId); + } + + trxParam.put("tranId", tranParam.get("tranId").toString()); + trxParam.put("resData", resData.toString()); + siteService.updateSplusTran(trxParam); + } catch (WebClientResponseException e) { + log.error(LOG_PREFIX + "WebClientResponseException::" + e.getStatusCode().value()); + log.error(LOG_PREFIX + "WebClientResponseException Body::" + e.getResponseBodyAsString()); + sp.appendLine("error_code=0"); + sp.appendLine("error_message=error"); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.appendLine("trx_id=" + trxId); + } catch (WebClientRequestException e) { + Throwable cause = e.getCause(); + if (cause instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX + "ConnectTimeoutException::" + e.getMessage()); + } else if (cause instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX + "SocketTimeoutException::" + e.getMessage()); + } else if (cause instanceof InterruptedException) { + log.error(LOG_PREFIX + "InterruptedException::" + e.getMessage()); + } else { + log.error(LOG_PREFIX + "WebClientRequestException::" + e.getMessage()); + } + sp.appendLine("error_code=0"); + sp.appendLine("error_message=error"); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.appendLine("trx_id=" + trxId); + } catch (Exception e) { + log.error(LOG_PREFIX + "Exception::" + e.getMessage()); + sp.appendLine("error_code=0"); + sp.appendLine("error_message=error"); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.appendLine("trx_id=" + trxId); + } + + log.info(LOG_PREFIX + "Response: " + sp.toString()); + return sp.toString(); // 활용한 응답 생성; + } + + private double getBalnce(String LOG_PREFIX, String cbUrl, String memId) { + LOG_PREFIX = LOG_PREFIX + "==> getBalnce::"; + double balance = 0L; + + try { + log.info(LOG_PREFIX + "Callback Url :" + cbUrl + "/balance/sportsD"); + JSONObject members = new JSONObject(); + members.put("userId", memId); + members.put("decYn", "Y"); + + // 회원 머니 + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/json"); + header.add("Accept", "application/json"); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + try { + ResponseEntity responseEntity = webClient.post() + .uri(cbUrl + "/balance/sportsD") + .header("Content-Type", "application/json") + .header("Accept", "application/json") + .header("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36") + .bodyValue(members.toString()) + .retrieve() + .toEntity(String.class) + .block(); + log.info(LOG_PREFIX + "status code : {}", responseEntity.getStatusCode()); + log.info(LOG_PREFIX + "body: {}", responseEntity.getBody()); + org.codehaus.jettison.json.JSONObject resData = new org.codehaus.jettison.json.JSONObject( + responseEntity.getBody()); + balance = resData.getDouble("balance");// * 0.01; + } catch (WebClientResponseException e) { + log.error(LOG_PREFIX + "WebClientResponseException::" + e.getStatusCode().value()); + log.error(LOG_PREFIX + "WebClientResponseException Body::" + e.getResponseBodyAsString()); + } catch (WebClientRequestException e) { + Throwable cause = e.getCause(); + if (cause instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX + "ConnectTimeoutException::" + e.getMessage()); + } else if (cause instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX + "SocketTimeoutException::" + e.getMessage()); + } else if (cause instanceof InterruptedException) { + log.error(LOG_PREFIX + "InterruptedException::" + e.getMessage()); + } else { + log.error(LOG_PREFIX + "WebClientRequestException::" + e.getMessage()); + } + } + + } catch (Exception e) { + log.error(LOG_PREFIX + "Exception :" + e.getMessage()); + } + + return balance; + } + + // 베팅 예약 크레딧 차람 + @RequestMapping(value = "/creditcustomer", produces = MediaType.TEXT_PLAIN_VALUE) + public @ResponseBody String creditCustomer(HttpServletRequest request, + @RequestBody(required = false) String parambody) throws Exception { + log.info("#-bti::creditCustomer::___________________Request____________________________"); + Enumeration params = request.getParameterNames(); + while (params.hasMoreElements()) { + String name = (String) params.nextElement(); + String value = request.getParameter(name); + log.info("#-bti::creditCustomer::" + name + "=" + value); + } + log.info("#-bti::creditCustomer::___________________Request____________________________"); + + DecimalFormat formatter = new DecimalFormat("0.00"); + StringBuilderPlus sp = new StringBuilderPlus(); + String cust_id = URLDecoder.decode(request.getParameter("cust_id"), "UTF-8"); + String purchase_id = URLDecoder.decode(request.getParameter("purchase_id"), "UTF-8"); + String req_id = URLDecoder.decode(request.getParameter("req_id"), "UTF-8"); + String amountStr = URLDecoder.decode(request.getParameter("amount"), "UTF-8"); + String agent_id = URLDecoder.decode(request.getParameter("agent_id"), "UTF-8"); + String customer_id = URLDecoder.decode(request.getParameter("customer_id"), "UTF-8"); + String memberId = cust_id.substring(3, cust_id.length()); + String reserveId = siteService.getRefIdByPurchaseId(purchase_id); + final String LOG_PREFIX = "#-bti::creditCustomer::" + memberId + "::" + reserveId + "::" + purchase_id+ "::" + req_id + ":::"; + + Map trxParam = new HashMap(); + trxParam.put("tranType", "creditCustomer"); + trxParam.put("cust_id", cust_id); + trxParam.put("reserve_id", reserveId); + trxParam.put("req_id", req_id); + trxParam.put("purchase_id", purchase_id); + trxParam.put("amount", amountStr); + trxParam.put("agent_id", agent_id); + trxParam.put("customer_id", cust_id); + + org.json.JSONObject paramjson = new org.json.JSONObject(); + try { + log.info(LOG_PREFIX+ "BF::parambody : "+ parambody); + log.info(LOG_PREFIX+ "BF::parambody {}", parambody); + paramjson = XML.toJSONObject(parambody); + log.info(LOG_PREFIX+ "MF::parambody {}", paramjson.toString()); + + trxParam.put("data", paramjson.toString()); + log.info(LOG_PREFIX+ "AF::parambody {}", paramjson.toString()); + } catch (Exception e) { + log.info(LOG_PREFIX+ "error {}", e.getMessage()); + } + + // 사이트정보 + HashMap ssParam = new HashMap(); + ssParam.put("siteIdx", Integer.parseInt(cust_id.substring(0, 3), 16)); + ssParam.put("memberId", cust_id.substring(3, cust_id.length())); + HashMap siteApiInfo = siteService.getSiteApiInfo(ssParam); + if (siteApiInfo == null) { + sp.appendLine("error_code=0"); + sp.append("error_message=CustomerNotFound"); + return sp.toString(); + } + + String siteId = siteApiInfo.get("siteId").toString(); + Map authParam = new HashMap(); + authParam.put("memberId", memberId); + authParam.put("siteId", siteId); + + // 회사정보 + log.info(LOG_PREFIX+ "siteApiInfo {}", siteApiInfo); + authParam.put("siteIdx", siteApiInfo.get("siteIdx")); + + // 회원정보 + Member member = siteService.getMemberByToken(authParam); + if (member == null) { + sp.appendLine("error_code=0"); + sp.append("error_message=CustomerNotFound"); + return sp.toString(); + } + + int siteIdx = Integer.parseInt(siteApiInfo.get("siteIdx").toString()); + String refId = siteId + reserveId; + Date dt = new Date(); + String trxId = "" + dt.getTime() + "4"; + trxParam.put("trxId", trxId); + trxParam.put("refId", refId); + + double balance = getBalnce(LOG_PREFIX, siteApiInfo.get("siteCbUrl").toString(), memberId); + long targetSiteCredit = siteService.getSiteCredit(siteApiInfo.get("siteId").toString()); + double amount = Double.parseDouble(amountStr); + + int custCnt = splusService.getCustomerCnt(trxParam); + if(custCnt > 0) { + log.error(LOG_PREFIX+ "creditCustomer::중복"); + sp.appendLine("error_code=0"); + sp.appendLine("error_message=No Error"); + // sp.appendLine("balance="+formatter.format(new BigDecimal(resData.getDouble("balance") * 0.01))); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.append("trx_id=" + trxId); + return sp.toString(); + } + + try { + log.info(LOG_PREFIX+ "trxParam : "+trxParam.toString()); + siteService.insertSplusTran(trxParam); + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::003"); + log.error(LOG_PREFIX+ "ERROR {}", e.getMessage()); + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", req_id + "#CC"); + tranParam.put("refId", refId); + tranParam.put("siteIdx", siteApiInfo.get("siteIdx")); + tranParam.put("siteId", siteId); + tranParam.put("completed", true); + tranParam.put("memberIdx", member.getMemberIdx()); + tranParam.put("memberId", member.getMemberId()); + tranParam.put("vendorCetegory", "SPORT"); + tranParam.put("vendorIdx", 84); + tranParam.put("vendorCode", "bti_zeno"); + tranParam.put("vendorTranKey", purchase_id + "#CC"); + tranParam.put("gameType", ""); + tranParam.put("gameId", ""); + tranParam.put("gameIdx", ""); + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", ""); + siteService.commonBetinsert(tranParam); + + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/json"); + header.add("Accept", "application/json"); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + JSONObject debit = new JSONObject(); + double fakeAmount = amount;// *100; + debit.put("betId", refId); + debit.put("tranId", req_id + "#CC"); + debit.put("userId", member.getMemberId()); + debit.put("vendorIdx", 84); + debit.put("vendorKey", "SP3"); + debit.put("vendor", "bti_zeno"); + debit.put("gameIdx", 1); + debit.put("gameKey", ""); + debit.put("gameType", ""); + debit.put("gameId", ""); + debit.put("tranType", "credit"); + debit.put("debit", 0); + debit.put("credit", fakeAmount); + debit.put("isCancel", 0); + debit.put("isBonus", 0); + debit.put("decYn", "Y"); + HashMap detailMap = new Gson().fromJson(paramjson.toString(), HashMap.class); + debit.put("status", "end"); + debit.put("detail", detailMap); + + log.info(LOG_PREFIX+ "Callback Request: "+debit.toString()); + org.codehaus.jettison.json.JSONObject resData = null; + + try { + ResponseEntity responseEntity = webClient.post() + .uri(siteApiInfo.get("siteCbUrl") + "/changebalance/sportsD") + .header("Content-Type", "application/json") + .header("Accept", "application/json") + .header("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36") + .bodyValue(debit.toString()) + .retrieve() + .toEntity(String.class) + .block(); + + resData = new org.codehaus.jettison.json.JSONObject( + responseEntity.getBody()); + log.info(LOG_PREFIX+ "Callback Response: "+resData.toString()); + + log.info(LOG_PREFIX+ "status code : {}", responseEntity.getStatusCode()); + log.info(LOG_PREFIX+ "body: {}", responseEntity.getBody()); + + if (resData.getLong("result_code") == 0) { + sp.appendLine("error_code=0"); + sp.appendLine("error_message=No Error "); + // sp.appendLine("balance="+formatter.format(new BigDecimal(resData.getDouble("balance") * 0.01))); + sp.appendLine("balance=" + formatter.format(new BigDecimal(resData.getDouble("balance")))); + sp.appendLine("trx_id=" + trxId); + + tranParam.put("balance", resData.getDouble("balance")); + int res = siteService.updateCbApi(tranParam); + } else { + sp.appendLine("error_code=0"); + sp.appendLine("error_message=error"); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.appendLine("trx_id=" + trxId); + } + } catch (WebClientResponseException e) { + log.error(LOG_PREFIX + "WebClientResponseException::" + e.getStatusCode().value()); + log.error(LOG_PREFIX + "WebClientResponseException Body::" + e.getResponseBodyAsString()); + sp.appendLine("error_code=0"); + sp.appendLine("error_message=error"); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.appendLine("trx_id=" + trxId); + } catch (WebClientRequestException e) { + Throwable cause = e.getCause(); + if (cause instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX + "ConnectTimeoutException::" + e.getMessage()); + } else if (cause instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX + "SocketTimeoutException::" + e.getMessage()); + } else if (cause instanceof InterruptedException) { + log.error(LOG_PREFIX + "InterruptedException::" + e.getMessage()); + } else { + log.error(LOG_PREFIX + "WebClientRequestException::" + e.getMessage()); + } + sp.appendLine("error_code=0"); + sp.appendLine("error_message=error"); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.appendLine("trx_id=" + trxId); + } catch (Exception e) { + log.error(LOG_PREFIX + "Exception::" + e.getMessage()); + sp.appendLine("error_code=0"); + sp.appendLine("error_message=error"); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.appendLine("trx_id=" + trxId); + } + + trxParam.put("tranId", tranParam.get("tranId").toString()); + trxParam.put("resData", resData.toString()); + siteService.updateSplusTran(trxParam); + + splusService.updateSplus(tranParam, paramjson); + + log.info(LOG_PREFIX+ "Response: "+sp.toString()); + return sp.toString(); // 활용한 응답 생성; + } + + private String makeApiKey(String param) { + + int n = 20; // n자리 쿠폰 + char[] chs = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', + 'J', 'K', 'L', 'M', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'N', 'O', 'P', 'Q', + 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', + 'z' }; + + Random rd = new Random(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < n; i++) { + char ch = chs[rd.nextInt(chs.length)]; + sb.append(ch); + } + return param + sb.toString(); + + } + +} diff --git a/src/main/java/com/bb/front/CallBackDpcoreController.java b/src/main/java/com/bb/front/CallBackDpcoreController.java new file mode 100644 index 0000000..22afb1c --- /dev/null +++ b/src/main/java/com/bb/front/CallBackDpcoreController.java @@ -0,0 +1,1286 @@ +package com.bb.front; + +import java.net.SocketTimeoutException; +import java.text.SimpleDateFormat; +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; + +import org.apache.http.conn.ConnectTimeoutException; +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.ResourceAccessException; + +import com.bb.model.NexusResponse; +import com.bb.model.PrimeResponse; +import com.bb.service.AsyncSiteService; +import com.bb.service.CallBackService; +import com.bb.service.SiteService; + +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@RequestMapping("/api/callback/dpcore") +@RequiredArgsConstructor +@SecurityRequirement(name = "Authorization") +@EnableScheduling +@RestController +public class CallBackDpcoreController { + + @Autowired + SiteService siteService; + + @Autowired + CallBackService callBackService; + + @Autowired + AsyncSiteService asyncCallBackService; + + + @ResponseBody + @RequestMapping(path = "/balance") + public ResponseEntity balance(HttpServletRequest request, @RequestParam("username") String primeUsername) throws Exception { + PrimeResponse response = null; + + long siteIdx = 0L; + try { + siteIdx = Long.parseLong(primeUsername.substring(0, 3), 16); + } catch (NumberFormatException e) { + log.error("#-CB::DPCORE::balance::Invalid username format (hex expected): {}", primeUsername); + log.error("#-CB::DPCORE::balance::Error Msg: NOT_FOUND_USER"); + response = new PrimeResponse(); + response.setBalance(0); + return new ResponseEntity(response, HttpStatus.BAD_REQUEST); + } + String memberId = primeUsername.substring(3, primeUsername.length()); + final String LOG_PREFIX = "#-CB::DPCORE::balance::"+memberId+":::"; + log.info(LOG_PREFIX+ "Request::" + primeUsername); + + try { + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + log.info(LOG_PREFIX + "SITE_API_INFO_PARAM::"+sParam.toString()); + HashMap siteApiInfo = siteService.getSiteApiInfo(sParam); + if(siteApiInfo == null) { + log.error(LOG_PREFIX+ "Error Msg: NOT_FOUND_SITE_INFO"); + response = new PrimeResponse(); + response.setBalance(0); + return new ResponseEntity(response, HttpStatus.BAD_REQUEST); + } + + if(siteApiInfo.get("memberIdx") == null) { + log.error(LOG_PREFIX+ "존재하지 않는 회원"); + response = new PrimeResponse(); + response.setBalance(0); + return new ResponseEntity(response, HttpStatus.BAD_REQUEST); + } + + // ##--isTransfer 처리-## + int balance = 0; + if("N".equals(siteApiInfo.get("isTransfer").toString())) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + JSONObject member = new JSONObject(); + member.put("userId", memberId); + log.info(LOG_PREFIX+ "balance Req ::"+ member.toString()); + JSONObject resData = callBackService.getBalance(siteApiInfo, member); + if(resData == null) { + log.error(LOG_PREFIX+ "Error Msg: BALANCE_CALLBACK_ERROR"); + response = new PrimeResponse(); + response.setBalance(0); + return new ResponseEntity(response, HttpStatus.BAD_REQUEST); + } + log.info(LOG_PREFIX+ "balance Res ::"+ resData.toString()); + balance = resData.getInt("balance"); + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + balance = siteService.getUserBalance(balanceMap); + + if(siteApiInfo.get("siteCbUrl") != null && !"".equals(siteApiInfo.get("siteCbUrl").toString())) { + JSONObject member = new JSONObject(); + member.put("userId", memberId); + member.put("balance", balance); + asyncCallBackService.asyncBalance(LOG_PREFIX, siteApiInfo, member); + } + } + + response = new PrimeResponse(); + response.setBalance(balance); + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + response = new PrimeResponse(); + response.setBalance(0); + return new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + response = new PrimeResponse(); + response.setBalance(0); + return new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + ResponseEntity res = new ResponseEntity(response, HttpStatus.OK); + log.info(LOG_PREFIX+ "Response::" + response.toString()); + + return res; + } + + + @ResponseBody + @RequestMapping(path = "/changeBalance") + public ResponseEntity changeBalance(HttpServletRequest request, @RequestBody net.sf.json.JSONObject requestBody) throws Exception { + ResponseEntity resEntity = null; + + String primeUsername = requestBody.getString("username"); + long siteIdx = 0L; + try { + siteIdx = Long.parseLong(primeUsername.substring(0, 3), 16); + } catch (NumberFormatException e) { + log.error("#-CB::DPCORE::balance::Invalid username format (hex expected): {}", primeUsername); + log.error("#-CB::DPCORE::balance::Error Msg: NOT_FOUND_USER"); + PrimeResponse response = new PrimeResponse(); + resEntity = new ResponseEntity(response, HttpStatus.BAD_REQUEST); + return resEntity; + } + String memberId = primeUsername.substring(3, primeUsername.length()); + net.sf.json.JSONObject transaction = requestBody.getJSONObject("transaction"); + net.sf.json.JSONObject game = transaction.getJSONObject("details").getJSONObject("game"); + String transactionId = transaction.getString("id"); + String transactionType = transaction.getString("type"); + + final String LOG_PREFIX = "#-CB::DPCORE::changeBalance::"+memberId+"::"+transactionId+"::"+transactionType+":::"; + log.info(LOG_PREFIX+ "Request::" + requestBody.toString()); + + try { + // "processed_at":"2025-01-16T09:25:23.000000Z" + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS"); + String betDateTimeStr = transaction.getString("processed_at"); + log.info(LOG_PREFIX+ "========== BF_betDateTimeStr::" + betDateTimeStr); + betDateTimeStr = betDateTimeStr.substring(0, 19); + betDateTimeStr = betDateTimeStr.replace("T", " "); + log.info(LOG_PREFIX+ "========== MF_betDateTimeStr::" + betDateTimeStr); + betDateTimeStr = makeEdate(LOG_PREFIX, betDateTimeStr, 32400000); + log.info(LOG_PREFIX+ "========== AF_betDateTimeStr::" + betDateTimeStr); + + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "dpcore"); + sParam.put("vendorGameCode", game.getString("vendor_code")); + log.info(LOG_PREFIX + "getSiteVendorInfo::"+sParam.toString()); + HashMap siteVendorInfo = siteService.getSiteVendorInfo(sParam); + if(siteVendorInfo == null) { + log.error(LOG_PREFIX+ "존재하지 않는 회원입니다"); + PrimeResponse response = new PrimeResponse(); + resEntity = new ResponseEntity(response, HttpStatus.BAD_REQUEST); + return resEntity; + } + + if(transactionType.equals("bet")) { + int amount = Math.abs(requestBody.getInt("amount")); + resEntity = callBet(LOG_PREFIX, siteIdx, memberId, transaction, betDateTimeStr, siteVendorInfo, amount); + + } else if(transactionType.equals("win")) { + int amount = Math.abs(requestBody.getInt("amount")); + resEntity = callWin(LOG_PREFIX, siteIdx, memberId, transaction, betDateTimeStr, siteVendorInfo, amount, requestBody); + + } else if(transactionType.equals("cancel")) { + int amount = Math.abs(requestBody.getInt("amount")); + resEntity = callCancel(LOG_PREFIX, siteIdx, memberId, transaction, betDateTimeStr, siteVendorInfo, amount); + + } else if(transactionType.equals("adjust")) { + int amount = requestBody.getInt("amount"); + //resEntity = callAdjust(LOG_PREFIX, siteIdx, memberId, transaction, betDateTimeStr, siteVendorInfo, amount); + + } else if(transactionType.equals("promo_win")) { + int amount = Math.abs(requestBody.getInt("amount")); + //resEntity = callPromoWin(LOG_PREFIX, siteIdx, memberId, transaction, betDateTimeStr, siteVendorInfo, amount); + + } else { + log.error(LOG_PREFIX+ "unknown_transaction_type"); + PrimeResponse response = new PrimeResponse(); + resEntity = new ResponseEntity(response, HttpStatus.BAD_REQUEST); + return resEntity; + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + PrimeResponse response = new PrimeResponse(); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + return resEntity; + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + PrimeResponse response = new PrimeResponse(); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + return resEntity; + } + + log.info(LOG_PREFIX+ "Response::" + resEntity.toString()); + + return resEntity; + } + + private ResponseEntity callBet(String LOG_PREFIX, long siteIdx, String memberId, + net.sf.json.JSONObject transaction, String betDateTimeStr, HashMap siteVendorInfo, int amount) { + + LOG_PREFIX = LOG_PREFIX + "callBet:::"; + ResponseEntity resEntity = null; + PrimeResponse response = new PrimeResponse(); + + // ##--isTransfer 처리-## + final String IS_TRANSFER = siteVendorInfo.get("isTransfer").toString(); + + try { + net.sf.json.JSONObject details = transaction.getJSONObject("details"); + net.sf.json.JSONObject game = details.getJSONObject("game"); + + String gameType = ""; + if(game.has("gameType")) { + gameType = game.getString("gameType").replaceAll(" ", "").toLowerCase(); + } else { + gameType = game.getString("type").replaceAll(" ", "").toLowerCase(); + } + + // gameType 변환 (하부로 전달 시 blackjack으로 통일) + if ("classicbetstackerbj".equals(gameType) || "freebet".equals(gameType) + || "funfun21scalablebj".equals(gameType) || "easybj".equals(gameType) + || "lightningscalablebj".equals(gameType) || "classicfreebet".equals(gameType) + || gameType.contains("blackjack")) { + gameType = "blackjack"; + } + + String betKey = game.getString("id")+"#"+transaction.getString("referer_id"); + String roundId = betKey; + String gameName = game.getString("title"); + + String tableId = game.getString("game_code"); + String targetTableId = tableId.replaceAll(" ", "").toLowerCase(); + + String banGameType = siteVendorInfo.get("banGameType").toString().replaceAll(" ", "").toLowerCase(); + String banGameId = siteVendorInfo.get("banGameId").toString().replaceAll(" ", "").toLowerCase(); + + if(!"".equals(gameType) && !"".equals(banGameType) && banGameType.contains(gameType+"|")) { + log.error(LOG_PREFIX+ "Ban Game Type : " + gameType); + resEntity = new ResponseEntity(response, HttpStatus.BAD_REQUEST); // 501 + return resEntity; + } + + if(!"".equals(targetTableId) && !"".equals(banGameId) && banGameId.contains(targetTableId+"|")) { + log.error(LOG_PREFIX+ "Ban Game Id : " + banGameId); + resEntity = new ResponseEntity(response, HttpStatus.BAD_REQUEST); // 502 + return resEntity; + } + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + String tranId = transaction.getString("id"); + String betId = transaction.getString("referer_id"); + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + + /* + int cnt1 = siteService.getTranIdCheck(tranId); + if(cnt1 != 0) { + // 중복베팅 + log.error(LOG_PREFIX+ "중복베팅"); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + return resEntity; + } + */ + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("Y")) { + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(tranId); + if(cntTr > 0) { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + response.setBalance(balance); + log.error(LOG_PREFIX+ "중복요청::Response::" + response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + } + + if(siteVendorInfo.get("lastInVendorIdx")==null || "0".equals(siteVendorInfo.get("lastInVendorIdx").toString())) { + HashMap memParam = new HashMap<>(); + memParam.put("siteIdx", siteIdx); + memParam.put("memberIdx", memberIdx); + memParam.put("lastInVendorIdx", Integer.parseInt(siteVendorInfo.get("vendorIdx").toString())); + int updResult = siteService.updMemLastVendorIdx(memParam); + } else { + int lastInVendorIdx = Integer.parseInt(siteVendorInfo.get("lastInVendorIdx").toString()); + if(lastInVendorIdx != vendorIdx) { + log.error(LOG_PREFIX+ "VendorIdx doesn't match"); + resEntity = new ResponseEntity(response, HttpStatus.BAD_REQUEST); + return resEntity; + } + } + + long siteCredit = Long.parseLong(siteVendorInfo.get("credit").toString()); + // ##--isTransfer 처리-## + if(siteCredit < amount && IS_TRANSFER.equals("N")) { + log.error(LOG_PREFIX+ "NO_SITE_CREDIT"); + resEntity = new ResponseEntity(response, HttpStatus.BAD_REQUEST); + return resEntity; + } + + // 최대 베팅 금액 처리 (userMaxBet 우선 적용) + long siteMaxBet = Long.parseLong(siteVendorInfo.get("siteMaxBet").toString()); + long userMaxBet = 0; + if(siteVendorInfo.get("userMaxBet") != null && !siteVendorInfo.get("userMaxBet").toString().isEmpty()) { + try { + userMaxBet = Long.parseLong(siteVendorInfo.get("userMaxBet").toString()); + } catch (NumberFormatException e) { + userMaxBet = 0; + } + } + + // 최종 maxBet 결정: userMaxBet이 0이면 siteMaxBet 사용, 0이 아니면 userMaxBet 사용 + long finalMaxBet = (userMaxBet > 0) ? userMaxBet : siteMaxBet; + log.info(LOG_PREFIX+ "MaxBet Info - siteMaxBet: " + siteMaxBet + ", userMaxBet: " + userMaxBet + ", finalMaxBet: " + finalMaxBet); + + if(finalMaxBet < amount) { + log.error(LOG_PREFIX+ "MAX_BET_AMOUNT_OVER"); + log.error(LOG_PREFIX+ "finalMaxBet : " + finalMaxBet +", amount : " + amount); + resEntity = new ResponseEntity(response, HttpStatus.BAD_REQUEST); + return resEntity; + } + + boolean isParsing = false; + log.info(LOG_PREFIX + "BF_isParsing::"+isParsing); + Boolean genuine = false; + if(transaction.has("genuine")) { + log.info(LOG_PREFIX + "transaction.has(\"genuine\") is true"); + genuine = transaction.getBoolean("genuine"); + log.info(LOG_PREFIX + "transaction.genuine::"+genuine.booleanValue()); + // genuine = true : 정품 + // genuine = null or false : 하이브리드(파싱) + if(genuine != null && genuine.booleanValue() == true) { + isParsing = false; + if(game.has("id")) { + roundId = game.getString("id"); + } + } else { + isParsing = true; + } + } else { + log.info(LOG_PREFIX + "transaction.has(\"genuine\") is false"); + isParsing = true; + } + log.info(LOG_PREFIX + "AF_isParsing::"+isParsing); + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "dpcore"); + tranParam.put("vendorTranKey", roundId); + tranParam.put("gameType", gameType); + tranParam.put("gameId", tableId); + tranParam.put("gameIdx", gameName); + tranParam.put("tranType", "debit"); + tranParam.put("depositAmt", amount); + tranParam.put("creditAmt", "0"); + tranParam.put("isCancel", "N"); + if(isParsing) { + tranParam.put("isTie", "P"); + } else { + tranParam.put("isTie", "N"); + } + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("betKey", roundId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "dpcore"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", gameName); + callBackObj.put("gameId", tableId); + callBackObj.put("gameType", game.getString("type")); + callBackObj.put("tranType", "debit"); + callBackObj.put("debit", amount); + callBackObj.put("credit", 0); + callBackObj.put("isCancel", 0); + callBackObj.put("isBonus", 0); + if(isParsing) { + callBackObj.put("isData", "Y"); + } else { + callBackObj.put("isData", "N"); + } + callBackObj.put("requestAt", betDateTimeStr); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("N")) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + log.info(LOG_PREFIX + "-----INSERT_BET_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_BET_END-----"); + + log.info(LOG_PREFIX + "SEND_BET request body: " + callBackObj.toString()); + JSONObject resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + log.info(LOG_PREFIX + "SEND_BET status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_BET response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + response.setBalance(balance); + response.setBeforeBalance(balance+amount); + resEntity = new ResponseEntity(response, HttpStatus.OK); + } else if(resData.getLong("result_code") == 98) { + int balance = resData.getInt("balance"); + response.setBalance(balance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + } else if(resData.getLong("result_code") == 80) { + int balance = resData.getInt("balance"); + response.setBalance(balance); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } else { + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + log.error(LOG_PREFIX+ msg); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + int afBalance = balance - amount; + + if(balance < amount) { + response.setBalance(balance); + log.error(LOG_PREFIX+ "Response::금액을 확인하여 주세요::" + response.toString()); + return new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + log.info(LOG_PREFIX + "-----INSERT_BET_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_BET_END-----"); + + tranParam.put("balance", afBalance); + tranParam.put("preBalance", balance); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + response.setBalance(afBalance); + response.setBeforeBalance(balance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + + if(siteVendorInfo.get("siteCbUrl") != null && !"".equals(siteVendorInfo.get("siteCbUrl").toString())) { + callBackObj.put("balance", afBalance); + asyncCallBackService.asyncChangeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + return resEntity; + } + + + private ResponseEntity callWin(String LOG_PREFIX, long siteIdx, String memberId, net.sf.json.JSONObject transaction, + String betDateTimeStr, HashMap siteVendorInfo, int amount, net.sf.json.JSONObject requestBody) { + + LOG_PREFIX = LOG_PREFIX + "callWin:::"; + ResponseEntity resEntity = null; + PrimeResponse response = new PrimeResponse(); + + // ##--isTransfer 처리-## + final String IS_TRANSFER = siteVendorInfo.get("isTransfer").toString(); + + try { + net.sf.json.JSONObject details = transaction.getJSONObject("details"); + net.sf.json.JSONObject game = details.getJSONObject("game"); + + String gameType = ""; + if(game.has("gameType")) { + gameType = game.getString("gameType").replaceAll(" ", "").toLowerCase(); + } else { + gameType = game.getString("type").replaceAll(" ", "").toLowerCase(); + } + + // gameType 변환 (하부로 전달 시 blackjack으로 통일) + if ("classicbetstackerbj".equals(gameType) || "freebet".equals(gameType) + || "funfun21scalablebj".equals(gameType) || "easybj".equals(gameType) + || "lightningscalablebj".equals(gameType) || "classicfreebet".equals(gameType) + || gameType.contains("blackjack")) { + gameType = "blackjack"; + } + + String tableId = game.getString("game_code"); + String betKey = game.getString("id")+"#"+transaction.getString("referer_id"); + String roundId = betKey; + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + String tranId = transaction.getString("id"); + String betId = transaction.getString("referer_id"); + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + + /* + int cnt1 = siteService.getTranIdCheck(tranId); + if(cnt1 != 0) { + // 중복베팅 + log.error(LOG_PREFIX+ "중복베팅"); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + return resEntity; + } + */ + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("Y")) { + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(tranId); + if(cntTr > 0) { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + response.setBalance(balance); + log.error(LOG_PREFIX+ "중복요청::Response::" + response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + + // 베팅 체크 + int cntBet = siteService.getBetIdCheck2(betId); + if(cntBet == 0) { + // 처리한 베팅 존재X + log.error(LOG_PREFIX+ "처리한 베팅 존재X"); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + return resEntity; + } + } else { + int cnt2 = siteService.getBetIdCheck(betId); + if(cnt2 == 0) { + // 처리한 베팅 존재X + log.error(LOG_PREFIX+ "처리한 베팅 존재X"); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + return resEntity; + } + } + + boolean isParsing = false; + log.info(LOG_PREFIX + "BF_isParsing::"+isParsing); + Boolean genuine = false; + if(transaction.has("genuine")) { + log.info(LOG_PREFIX + "transaction.has(\"genuine\") is true"); + genuine = transaction.getBoolean("genuine"); + log.info(LOG_PREFIX + "transaction.genuine::"+genuine.booleanValue()); + // genuine = true : 정품 + // genuine = null or false : 하이브리드(파싱) + if(genuine != null && genuine.booleanValue() == true) { + isParsing = false; + if(game.has("id")) { + roundId = game.getString("id"); + } + } else { + isParsing = true; + } + } else { + log.info(LOG_PREFIX + "transaction.has(\"genuine\") is false"); + isParsing = true; + } + log.info(LOG_PREFIX + "AF_isParsing::"+isParsing); + + String isDebitParse = siteService.getDebitIsParse(betId); + log.info(LOG_PREFIX + "isDebitParse::"+isDebitParse); + if(isDebitParse == null) { + log.error(LOG_PREFIX+ "처리한 베팅 존재X"); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + return resEntity; + } else { + if("P".equals(isDebitParse)) { + isParsing = true; + } + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "dpcore"); + tranParam.put("vendorTranKey", roundId); + tranParam.put("gameType", gameType); + tranParam.put("gameId", tableId); + tranParam.put("gameIdx", game.getString("title")); + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + tranParam.put("isCancel", "N"); + if(isParsing) { + tranParam.put("isTie", "P"); + } else { + tranParam.put("isTie", "N"); + } + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("betKey", roundId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "dpcore"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", game.getString("title")); + callBackObj.put("gameId", tableId); + callBackObj.put("gameType", gameType); + callBackObj.put("tranType", "credit"); + callBackObj.put("debit", 0); + callBackObj.put("credit", amount); + callBackObj.put("isCancel", 0); + callBackObj.put("isBonus", 0); + if(isParsing) { + callBackObj.put("isData", "Y"); + } else { + callBackObj.put("isData", "N"); + } + callBackObj.put("requestAt", betDateTimeStr); + + /** + * issueFlag : flag=Y 유저 이면 결과 강제취소처리 + */ + String issueFlag = siteVendorInfo.get("issueFlag").toString(); + if("Y".equals(issueFlag)) { + // ##-- issueFlag 전처리 + if(amount <= 0) { // 여러가지 경우를 테스트함 + int betAmount = Integer.parseInt(siteService.getBetAmountByTranParam(tranParam)); + tranParam.put("creditAmt", betAmount); + tranParam.put("isCancel", "Y"); + + callBackObj.put("credit", betAmount); + callBackObj.put("isCancel", 1); + } + } + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("N")) { + log.info(LOG_PREFIX + "-----INSERT_RESULT_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_RESULT_END-----"); + + log.info(LOG_PREFIX + "SEND_RESULT request body: " + callBackObj.toString()); + JSONObject resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + log.info(LOG_PREFIX + "SEND_RESULT status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_RESULT response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + response.setBalance(balance); + response.setBeforeBalance(balance-amount); + resEntity = new ResponseEntity(response, HttpStatus.OK); + + } else if(resData.getLong("result_code") == 98) { + int balance = resData.getInt("balance"); + response.setBalance(balance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + + } else { + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + log.error(LOG_PREFIX+ msg); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + int afBalance = balance + amount; + + log.info(LOG_PREFIX + "-----INSERT_RESULT_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_RESULT_END-----"); + + tranParam.put("balance", afBalance); + tranParam.put("preBalance", balance); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + response.setBalance(afBalance); + response.setBeforeBalance(balance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + + if(siteVendorInfo.get("siteCbUrl") != null && !"".equals(siteVendorInfo.get("siteCbUrl").toString())) { + callBackObj.put("balance", afBalance); + asyncCallBackService.asyncChangeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } + } + + /** + * issueFlag : flag=Y 유저 이면 결과 강제취소처리 + */ + if("Y".equals(issueFlag)) { + // ##-- issueFlag 후처리 + log.error(LOG_PREFIX+ "issueFlag=Y, 결과 강제취소처리"); + + asyncCallBackService.asyncIssueLogSave(LOG_PREFIX, requestBody, tranParam); + + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + return resEntity; + } + + + private ResponseEntity callCancel(String LOG_PREFIX, long siteIdx, String memberId, + net.sf.json.JSONObject transaction, String betDateTimeStr, HashMap siteVendorInfo, int amount) { + + ResponseEntity resEntity = null; + PrimeResponse response = new PrimeResponse(); + + // ##--isTransfer 처리-## + final String IS_TRANSFER = siteVendorInfo.get("isTransfer").toString(); + + try { + net.sf.json.JSONObject details = transaction.getJSONObject("details"); + net.sf.json.JSONObject game = details.getJSONObject("game"); + + String gameType = ""; + if(game.has("gameType")) { + gameType = game.getString("gameType").replaceAll(" ", "").toLowerCase(); + } else { + gameType = game.getString("type").replaceAll(" ", "").toLowerCase(); + } + + // gameType 변환 (하부로 전달 시 blackjack으로 통일) + if ("classicbetstackerbj".equals(gameType) || "freebet".equals(gameType) + || "funfun21scalablebj".equals(gameType) || "easybj".equals(gameType) + || "lightningscalablebj".equals(gameType) || "classicfreebet".equals(gameType) + || gameType.contains("blackjack")) { + gameType = "blackjack"; + } + + String tableId = game.getString("game_code"); + String betKey = game.getString("id")+"#"+transaction.getString("referer_id"); + String roundId = betKey; + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + String tranId = transaction.getString("id"); + String betId = transaction.getString("referer_id"); + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + + /* + int cnt1 = siteService.getTranIdCheck(tranId); + if(cnt1 != 0) { + // 중복베팅 + log.error(LOG_PREFIX+ "중복베팅"); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + return resEntity; + } + */ + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("Y")) { + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(tranId); + if(cntTr > 0) { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + response.setBalance(balance); + log.error(LOG_PREFIX+ "중복요청::Response::" + response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + + // 베팅 체크 + int cntBet = siteService.getBetIdCheck2(betId); + if(cntBet == 0) { + // 처리한 베팅 존재X + log.error(LOG_PREFIX+ "처리한 베팅 존재X"); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + return resEntity; + } + } else { + int cnt2 = siteService.getBetIdCheck(betId); + if(cnt2 == 0) { + // 처리한 베팅 존재X + log.error(LOG_PREFIX+ "처리한 베팅 존재X"); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + return resEntity; + } + } + + boolean isParsing = false; + log.info(LOG_PREFIX + "BF_isParsing::"+isParsing); + Boolean genuine = false; + if(transaction.has("genuine")) { + log.info(LOG_PREFIX + "transaction.has(\"genuine\") is true"); + genuine = transaction.getBoolean("genuine"); + log.info(LOG_PREFIX + "transaction.genuine::"+genuine.booleanValue()); + // genuine = true : 정품 + // genuine = null or false : 하이브리드(파싱) + if(genuine != null && genuine.booleanValue() == true) { + isParsing = false; + if(game.has("id")) { + roundId = game.getString("id"); + } + } else { + isParsing = true; + } + } else { + log.info(LOG_PREFIX + "transaction.has(\"genuine\") is false"); + isParsing = true; + } + log.info(LOG_PREFIX + "AF_isParsing::"+isParsing); + + String isDebitParse = siteService.getDebitIsParse(betId); + log.info(LOG_PREFIX + "isDebitParse::"+isDebitParse); + if(isDebitParse == null) { + log.error(LOG_PREFIX+ "처리한 베팅 존재X"); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + return resEntity; + } else { + if("P".equals(isDebitParse)) { + isParsing = true; + } + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "dpcore"); + tranParam.put("vendorTranKey", roundId); + tranParam.put("gameType", gameType); + tranParam.put("gameId", tableId); + tranParam.put("gameIdx", game.getString("title")); + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + tranParam.put("isCancel", "Y"); + if(isParsing) { + tranParam.put("isTie", "P"); + } else { + tranParam.put("isTie", "N"); + } + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("betKey", roundId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "dpcore"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", game.getString("title")); + callBackObj.put("gameId", tableId); + callBackObj.put("gameType", gameType); + callBackObj.put("tranType", "credit"); + callBackObj.put("debit", 0); + callBackObj.put("credit", amount); + callBackObj.put("isCancel", 1); + callBackObj.put("isBonus", 0); + if(isParsing) { + callBackObj.put("isData", "Y"); + } else { + callBackObj.put("isData", "N"); + } + callBackObj.put("requestAt", betDateTimeStr); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("N")) { + log.info(LOG_PREFIX + "-----INSERT_CANCEL_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_CANCEL_END-----"); + + log.info(LOG_PREFIX + "SEND_CANCEL request body: " + callBackObj.toString()); + JSONObject resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + log.info(LOG_PREFIX + "SEND_CANCEL status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_CANCEL response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + response.setBalance(balance); + response.setBeforeBalance(balance-amount); + resEntity = new ResponseEntity(response, HttpStatus.OK); + + } else if(resData.getLong("result_code") == 98) { + int balance = resData.getInt("balance"); + response.setBalance(balance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + + } else { + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + log.error(LOG_PREFIX+ msg); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + int afBalance = balance + amount; + + log.info(LOG_PREFIX + "-----INSERT_CANCEL_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_CANCEL_END-----"); + + tranParam.put("balance", afBalance); + tranParam.put("preBalance", balance); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + response.setBalance(afBalance); + response.setBeforeBalance(balance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + + if(siteVendorInfo.get("siteCbUrl") != null && !"".equals(siteVendorInfo.get("siteCbUrl").toString())) { + callBackObj.put("balance", afBalance); + asyncCallBackService.asyncChangeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + return resEntity; + } + + + /** + * 에볼루션 상세 콜백 + * @param request + * @param requestBody + * @return + * @throws Exception + */ + @ResponseBody + @RequestMapping(path = "/callDetail") + public ResponseEntity callDetail(HttpServletRequest request, @RequestBody net.sf.json.JSONObject requestBody) throws Exception { + NexusResponse response = null; + HttpStatus httpStatus = null; + + String apiKey = requestBody.getString("apiKey"); + final String LOG_PREFIX = "#-CB::DPCORE::callDetail::ace::"+apiKey+":::"; + //log.info(LOG_PREFIX+ "Request::" + requestBody.toString()); + + try { + JSONObject bodyObj = new JSONObject(requestBody.toString()); + JSONArray params = bodyObj.getJSONArray("params"); + String prevVendorTranKey = ""; + for(int i=0; i(); + detailMap.put("refId", refId); + detailMap.put("orgDetail", orgDetail.toString()); + detailMap.put("parDetail", null); + try { + int result = siteService.insertEvoDetail(detailMap); + log.info(LOG_PREFIX2+ "insertEvoDetail result::" + result); + } catch(DataIntegrityViolationException de) { + log.error(LOG_PREFIX2+ "Duplicate refId"); + continue; + } + } + } + } else { + log.info(LOG_PREFIX+ "Not found json key _id"); + } + } + + response = new NexusResponse(); + response.setCode(0); + response.setMsg("SUCCESS"); + httpStatus = HttpStatus.OK; + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + response = new NexusResponse(); + response.setCode(-8); + response.setMsg("TIMEOUT_ERROR"); + httpStatus = HttpStatus.OK; + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + response = new NexusResponse(); + response.setCode(-9); + response.setMsg("DETAIL_SERVER_ERROR"); + httpStatus = HttpStatus.OK; + } + + ResponseEntity res = new ResponseEntity(response, httpStatus); + log.info(LOG_PREFIX+ "Response::" + response.toString()); + + return res; + } + + + /** + * UTC 시간을 한국 시간(KST)으로 변환 + * @param utcTimeStr UTC 시간 문자열 (예: 2026-02-06T04:39:05.243Z) + * @return 한국 시간 문자열 (예: 2026-02-06T13:39:05.243+09:00) + */ + private static String convertUtcToKstTime(String utcTimeStr) { + try { + if (utcTimeStr == null || !utcTimeStr.endsWith("Z")) { + return utcTimeStr; + } + + // UTC 시간 파싱 + Instant instant = Instant.parse(utcTimeStr); + // 한국 시간대로 변환 (UTC+9) + ZonedDateTime kstTime = instant.atZone(ZoneId.of("Asia/Seoul")); + // ISO 8601 형식으로 포맷 (타임존 포함) + return kstTime.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME); + } catch (Exception e) { + log.error("UTC to KST conversion error: " + e.getMessage()); + return utcTimeStr; // 변환 실패시 원본 반환 + } + } + + /** + * JSON 객체를 재귀적으로 순회하며 시간 필드를 UTC에서 KST로 변환 + * @param jsonObj 변환할 JSON 객체 + */ + private static void convertUtcToKst(JSONObject jsonObj) { + try { + // 변환할 시간 필드 목록 + String[] timeFields = {"startedAt", "settledAt", "placedOn", "recordedAt"}; + + Iterator keys = jsonObj.keys(); + while (keys.hasNext()) { + String key = keys.next(); + Object value = jsonObj.get(key); + + // 시간 필드인 경우 변환 + for (String timeField : timeFields) { + if (key.equals(timeField) && value instanceof String) { + String utcTime = (String) value; + String kstTime = convertUtcToKstTime(utcTime); + jsonObj.put(key, kstTime); + break; + } + } + + // 중첩된 JSONObject인 경우 재귀 호출 + if (value instanceof JSONObject) { + convertUtcToKst((JSONObject) value); + } + // 중첩된 JSONArray인 경우 각 요소 처리 + else if (value instanceof JSONArray) { + JSONArray jsonArray = (JSONArray) value; + for (int i = 0; i < jsonArray.length(); i++) { + Object arrayItem = jsonArray.get(i); + if (arrayItem instanceof JSONObject) { + convertUtcToKst((JSONObject) arrayItem); + } + } + } + } + } catch (Exception e) { + log.error("JSON time conversion error: " + e.getMessage()); + } + } + + private static String makeEdate(String LOG_PREFIX, String paramDate, int flag) { + // TODO Auto-generated method stub + String eDate = ""; + SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + try { + Date date = sdf1.parse(paramDate); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + calendar.add(Calendar.MILLISECOND, flag); + Date date2 = calendar.getTime(); + eDate = sdf2.format(date2); + } catch(Exception e) { + log.error(LOG_PREFIX+ "makeEdate::Exception::"+e.getMessage()); + } + return eDate; + } +} diff --git a/src/main/java/com/bb/front/CallBackNexusController.java b/src/main/java/com/bb/front/CallBackNexusController.java new file mode 100644 index 0000000..e7806de --- /dev/null +++ b/src/main/java/com/bb/front/CallBackNexusController.java @@ -0,0 +1,1684 @@ +package com.bb.front; + +import java.net.SocketTimeoutException; +import java.text.SimpleDateFormat; +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; + +import jakarta.servlet.http.HttpServletRequest; + +import org.apache.http.conn.ConnectTimeoutException; +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.ResourceAccessException; + +import com.bb.model.NexusBalanceData; +import com.bb.model.NexusResponse; +import com.bb.model.NexusSmlData; +import com.bb.model.NexusSmlRequest; +import com.bb.service.AsyncSiteService; +import com.bb.service.CallBackService; +import com.bb.service.SiteService; + +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@RequestMapping("/api/callback/nexus") +@RequiredArgsConstructor +@SecurityRequirement(name = "Authorization") +@EnableScheduling +@RestController +public class CallBackNexusController { + + @Autowired + SiteService siteService; + + @Autowired + CallBackService callBackService; + + @Autowired + AsyncSiteService asyncCallBackService; + + + @ResponseBody + @RequestMapping(path = "/callBalance") + public ResponseEntity callBalance(HttpServletRequest request, @RequestBody net.sf.json.JSONObject requestBody) throws Exception { + NexusResponse response = null; + HttpStatus httpStatus = null; + + String apiKey = requestBody.getString("apiKey"); + net.sf.json.JSONObject params = requestBody.getJSONObject("params"); + String siteUsername = params.getString("siteUsername"); + String requestedAt = params.getString("requestedAt"); + + if(siteUsername == null || siteUsername.equals("") || siteUsername.equals("invalid-user")) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("존재하지 않는 회원입니다"); + httpStatus = HttpStatus.OK; + return new ResponseEntity(response, httpStatus); + } + + long siteIdx = Long.parseLong(siteUsername.substring(0, 3), 16); + String memberId = siteUsername.substring(3, siteUsername.length()); + final String LOG_PREFIX = "#-CB::NEXUS::::callBalance::"+memberId+"::"+requestedAt+":::"; + log.info(LOG_PREFIX+ "Request::" + requestBody.toString()); + + try { + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "nexus"); + sParam.put("apiKey", apiKey); + log.info(LOG_PREFIX + "getSiteVendorInfo::"+sParam.toString()); + HashMap siteApiInfo = siteService.getSiteApiInfoByApiKey(sParam); + if(siteApiInfo == null) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("API키가 일치하지 않습니다"); + httpStatus = HttpStatus.OK; + return new ResponseEntity(response, httpStatus); + } + + if(siteApiInfo.get("memberIdx") == null) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("존재하지 않는 회원입니다"); + httpStatus = HttpStatus.OK; + return new ResponseEntity(response, httpStatus); + } + + // ##--isTransfer 처리-## + int balance = 0; + if("N".equals(siteApiInfo.get("isTransfer").toString())) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + JSONObject member = new JSONObject(); + member.put("userId", memberId); + long startTimestamp = System.currentTimeMillis(); + JSONObject resData = callBackService.getBalance(siteApiInfo, member); + if(resData == null) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("BALANCE_CALLBACK_ERROR"); + httpStatus = HttpStatus.OK; + return new ResponseEntity(response, httpStatus); + } + long endTimestamp = System.currentTimeMillis(); + double diffTime = (startTimestamp - endTimestamp)/1000.0; //두 시간에 차 계산 + if(diffTime < -1.5) { + log.error(LOG_PREFIX+ "잔액요청 응답시간("+diffTime+"초) 초과"); + } + log.info(LOG_PREFIX + "resData::"+resData.toString()); + balance = resData.getInt("balance"); + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + balance = siteService.getUserBalance(balanceMap); + + if(siteApiInfo.get("siteCbUrl") != null && !"".equals(siteApiInfo.get("siteCbUrl").toString())) { + JSONObject member = new JSONObject(); + member.put("userId", memberId); + member.put("balance", balance); + asyncCallBackService.asyncBalance(LOG_PREFIX, siteApiInfo, member); + } + } + + NexusBalanceData data = new NexusBalanceData(); + data.setBalance(balance); + data.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(data); + httpStatus = HttpStatus.OK; + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + response = new NexusResponse(); + response.setCode(-999); + response.setMsg("TIMEOUT_ERROR"); + httpStatus = HttpStatus.OK; + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + response = new NexusResponse(); + response.setCode(-999); + response.setMsg("BALANCE_SERVER_ERROR"); + httpStatus = HttpStatus.OK; + } + + ResponseEntity res = new ResponseEntity(response, httpStatus); + log.info(LOG_PREFIX+ "Response::" + response.toString()); + + return res; + } + + + @ResponseBody + @RequestMapping(path = "/callBet") + public ResponseEntity callBet(HttpServletRequest request, @RequestBody NexusSmlRequest requestBody) throws Exception { + NexusResponse response = null; + HttpStatus httpStatus = null; + + String apiKey = requestBody.getApiKey(); + NexusSmlData data = requestBody.getParams(); + String siteUsername = data.getSiteUsername(); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + String betDateTimeStr = data.getCreatedAt(); + if(betDateTimeStr == null || betDateTimeStr.equals("")) { + betDateTimeStr = sdf.format(System.currentTimeMillis()); + } else { + betDateTimeStr = betDateTimeStr.replace("T", " ").replace("Z", ""); + betDateTimeStr = makeEdate(betDateTimeStr, 32400000); + } + data.setBetDateTime(betDateTimeStr); + + if(siteUsername == null || siteUsername.equals("") || siteUsername.equals("invalid-user")) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("존재하지 않는 회원입니다"); + httpStatus = HttpStatus.OK; + return new ResponseEntity(response, httpStatus); + } + + long siteIdx = Long.parseLong(siteUsername.substring(0, 3), 16); + String memberId = siteUsername.substring(3, siteUsername.length()); + final String LOG_PREFIX = "#-CB::NEXUS::"+memberId+"::"+data.getTransactionKey()+"::callBet:::"; + log.info(LOG_PREFIX+ "Request::" + requestBody.toString()); + + try { + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "nexus"); + sParam.put("vendorGameCode", data.getVendorKey()); + log.info(LOG_PREFIX + "getSiteVendorInfo::"+sParam.toString()); + HashMap siteVendorInfo = siteService.getSiteVendorInfo(sParam); + if(siteVendorInfo == null) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("존재하지 않는 회원입니다"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "존재하지 않는 회원입니다::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + if(!apiKey.equals(siteVendorInfo.get("vendorApiKey").toString())) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("API키가 일치하지 않습니다"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "API키가 일치하지 않습니다::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + // ##--isTransfer 처리-## + final String IS_TRANSFER = siteVendorInfo.get("isTransfer").toString(); + + // vendors_info.useYn 게임막기 기능 + if("N".equals(siteVendorInfo.get("vendorAllUseYn").toString())) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("사용불가 벤더사"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "사용불가 벤더사::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + if(siteVendorInfo.get("lastInVendorIdx")==null || "0".equals(siteVendorInfo.get("lastInVendorIdx").toString())) { + HashMap memParam = new HashMap<>(); + memParam.put("siteIdx", siteIdx); + memParam.put("memberIdx", memberIdx); + memParam.put("lastInVendorIdx", Integer.parseInt(siteVendorInfo.get("vendorIdx").toString())); + int updResult = siteService.updMemLastVendorIdx(memParam); + } else { + Long lastInVendorIdx = Long.parseLong(siteVendorInfo.get("lastInVendorIdx").toString()); + Long vendorIdx = Long.parseLong(siteVendorInfo.get("vendorIdx").toString()); + if(lastInVendorIdx.longValue() != vendorIdx.longValue()) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("VendorIdx doesn't match"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "VendorIdx doesn't match::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + } + + Double amountD = Double.parseDouble(data.getAmount()); + int amount = Math.abs(amountD.intValue()); + long siteCredit = Long.parseLong(siteVendorInfo.get("credit").toString()); + // ##--isTransfer 처리-## + if(siteCredit < amount && IS_TRANSFER.equals("N")) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("NO_SITE_CREDIT"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "NO_SITE_CREDIT::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + if(amount < 0) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("금액이 올바르지 않습니다"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "금액이 올바르지 않습니다::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + // 최대 베팅 금액 처리 (userMaxBet 우선 적용) + long siteMaxBet = Long.parseLong(siteVendorInfo.get("siteMaxBet").toString()); + long userMaxBet = 0; + if(siteVendorInfo.get("userMaxBet") != null && !siteVendorInfo.get("userMaxBet").toString().isEmpty()) { + try { + userMaxBet = Long.parseLong(siteVendorInfo.get("userMaxBet").toString()); + } catch (NumberFormatException e) { + userMaxBet = 0; + } + } + + // 최종 maxBet 결정: userMaxBet이 0이면 siteMaxBet 사용, 0이 아니면 userMaxBet 사용 + long finalMaxBet = (userMaxBet > 0) ? userMaxBet : siteMaxBet; + log.info(LOG_PREFIX+ "MaxBet Info - siteMaxBet: " + siteMaxBet + ", userMaxBet: " + userMaxBet + ", finalMaxBet: " + finalMaxBet); + + if(finalMaxBet < amount) { + log.error(LOG_PREFIX+ "MAX_BET_AMOUNT_OVER"); + log.error(LOG_PREFIX+ "finalMaxBet : " + finalMaxBet +", amount : " + amount); + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("MAX_BET_AMOUNT_OVER"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "MAX_BET_AMOUNT_OVER::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + String vendorTranKey = data.getTransactionKey(); + String tranId = data.getTransactionKey(); + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("Y")) { + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(tranId); + if(cntTr > 0) { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(balance); + balanceData.setBeforeBalance(balance + amount); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "중복요청::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + } + + String betId = data.getParentTransactionKey(); + if(betId == null || betId.equals("")) { + betId = data.getTransactionKey(); + } + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + + String gameName = data.getGameName(); + String gameType = data.getGameType().replaceAll(" ", "").toLowerCase(); + if(data.getGameId() == null) data.setGameId(""); + String gameId = data.getGameId().replaceAll(" ", "").toLowerCase(); + String gameKey = null; + if(vendorIdx == 1) { + gameKey = siteService.getGameKeyByNexusGameId(data.getGameId()); + } + if(gameKey == null) gameKey = gameId; + String banGameType = siteVendorInfo.get("banGameType").toString().replaceAll(" ", "").toLowerCase(); + String banGameId = siteVendorInfo.get("banGameId").toString().replaceAll(" ", "").toLowerCase(); + + if(!"".equals(gameType) && !"".equals(banGameType) && banGameType.contains(gameType+"|")) { + // Ban Game Type Exception + HashMap logParam = new HashMap(); + logParam.put("siteIdx", siteIdx); + logParam.put("memberIdx", memberIdx); + logParam.put("vendorIdx", vendorIdx); + logParam.put("statusCode", 501L); + logParam.put("callBackType", "debit"); + logParam.put("tranId", tranId); + logParam.put("callBackReqBody", "gameType:"+gameType+"이 블락설정"); + logParam.put("callBackResBody", ""); + logParam.put("errorCode", "BLOCK_GAME_TYPE"); + logParam.put("errorMsg", "gameType:"+gameType+"이 블락설정"); + long startTimestamp = System.currentTimeMillis(); + logParam.put("regDate", startTimestamp); + logParam.put("updDate", startTimestamp); + callBackService.insertCallBackErrLog(logParam); + log.error(LOG_PREFIX+ "Ban Game Type : " + gameType); + + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("Ban Game Type : " + gameType); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "VendorIdx doesn't match::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + if(!"".equals(gameId) && !"".equals(banGameId) && banGameId.contains(gameId+"|")) { + // Ban Game Id Exception + HashMap logParam = new HashMap(); + logParam.put("siteIdx", siteIdx); + logParam.put("memberIdx", memberIdx); + logParam.put("vendorIdx", vendorIdx); + logParam.put("statusCode", 502L); + logParam.put("callBackType", "debit"); + logParam.put("tranId", tranId); + logParam.put("callBackReqBody", "gameId:"+gameId+"("+gameName+")이 블락설정"); + logParam.put("callBackResBody", ""); + logParam.put("errorCode", "BLOCK_GAME_ID"); + logParam.put("errorMsg", "gameId:"+gameId+"("+gameName+")이 블락설정"); + long startTimestamp = System.currentTimeMillis(); + logParam.put("regDate", startTimestamp); + logParam.put("updDate", startTimestamp); + callBackService.insertCallBackErrLog(logParam); + log.error(LOG_PREFIX+ "Ban Game Id : " + gameId); + + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("Ban Game Id : " + gameId); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "VendorIdx doesn't match::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "nexus"); + tranParam.put("vendorTranKey", vendorTranKey); + tranParam.put("gameType", data.getGameType()); + tranParam.put("gameId", data.getGameId()); + tranParam.put("gameIdx", data.getGameName()); + tranParam.put("tranType", "debit"); + tranParam.put("depositAmt", amount); + tranParam.put("creditAmt", "0"); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "nexus"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", data.getGameName()); + if(data.getGameId() == null) data.setGameId(""); + callBackObj.put("gameId", data.getGameId()); + callBackObj.put("gameType", data.getGameType()); + callBackObj.put("tranType", "debit"); + callBackObj.put("debit", amount); + callBackObj.put("credit", 0); + callBackObj.put("isCancel", 0); + if(data.getIsBonus().equals("true")) { + callBackObj.put("isBonus", 1); + } else { + callBackObj.put("isBonus", 0); + } + callBackObj.put("requestAt", betDateTimeStr); + log.info(LOG_PREFIX + "SEND_BET request body: " + callBackObj.toString()); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("N")) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + log.info(LOG_PREFIX + "-----INSERT_BET_START-----"); + long startTime = System.currentTimeMillis(); + siteService.commonBetinsert(tranParam); + long endTime = System.currentTimeMillis(); // 코드 실행 후에 시간 받아오기 + double diffTime = (startTime - endTime)/1000.0; //두 시간에 차 계산 + if(diffTime < -1.0) { + log.error(LOG_PREFIX + "commonBetinsert::배팅 쓰기지연::"+diffTime+"초 지연발생"); + response = new NexusResponse(); + response.setCode(-999); + response.setMsg("TIMEOUT_ERROR"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "TIMEOUT_ERROR::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + log.info(LOG_PREFIX + "-----INSERT_BET_END-----"); + + JSONObject resData = null; + if(data.getGameCategory().equals("casino")) { + resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } else { + resData = callBackService.changeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } + log.info(LOG_PREFIX + "SEND_BET status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_BET response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(balance); + balanceData.setBeforeBalance(balance + amount); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + } else if(resData.getLong("result_code") == 80) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("금액을 확인하여 주세요"); + httpStatus = HttpStatus.OK; + } else if(resData.getLong("result_code") == 98) { + int balance = resData.getInt("balance"); + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(balance); + balanceData.setBeforeBalance(balance + amount); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + } else { + response = new NexusResponse(); + response.setCode(-999); + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + response.setMsg(msg); + httpStatus = HttpStatus.OK; + } + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + int afBalance = balance - amount; + + if(balance < amount) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("금액을 확인하여 주세요"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "잔액부족::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + log.info(LOG_PREFIX + "-----INSERT_BET_START-----"); + long startTime = System.currentTimeMillis(); + siteService.commonBetinsert(tranParam); + long endTime = System.currentTimeMillis(); // 코드 실행 후에 시간 받아오기 + double diffTime = (startTime - endTime)/1000.0; //두 시간에 차 계산 + if(diffTime < -1.0) { + log.error(LOG_PREFIX + "commonBetinsert::배팅 쓰기지연::"+diffTime+"초 지연발생"); + response = new NexusResponse(); + response.setCode(-999); + response.setMsg("TIMEOUT_ERROR"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "TIMEOUT_ERROR::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + log.info(LOG_PREFIX + "-----INSERT_BET_END-----"); + + tranParam.put("balance", afBalance); + tranParam.put("preBalance", balance); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(afBalance); + balanceData.setBeforeBalance(balance); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + + if(siteVendorInfo.get("siteCbUrl") != null && !"".equals(siteVendorInfo.get("siteCbUrl").toString())) { + callBackObj.put("balance", afBalance); + if(data.getGameCategory().equals("casino")) { + asyncCallBackService.asyncChangeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } else { + asyncCallBackService.asyncChangeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } + } + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + response = new NexusResponse(); + response.setCode(-999); + response.setMsg("TIMEOUT_ERROR"); + httpStatus = HttpStatus.OK; + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + response = new NexusResponse(); + response.setCode(-999); + response.setMsg("BET_SERVER_ERROR"); + httpStatus = HttpStatus.OK; + } + + ResponseEntity res = new ResponseEntity(response, httpStatus); + log.info(LOG_PREFIX+ "Response::" + response.toString()); + + return res; + } + + + @ResponseBody + @RequestMapping(path = "/callResult") + public ResponseEntity callResult(HttpServletRequest request, @RequestBody NexusSmlRequest requestBody) throws Exception { + NexusResponse response = null; + HttpStatus httpStatus = null; + + String apiKey = requestBody.getApiKey(); + NexusSmlData data = requestBody.getParams(); + String siteUsername = data.getSiteUsername(); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + String betDateTimeStr = data.getCreatedAt(); + if(betDateTimeStr == null || betDateTimeStr.equals("")) { + betDateTimeStr = sdf.format(System.currentTimeMillis()); + } else { + betDateTimeStr = betDateTimeStr.replace("T", " ").replace("Z", ""); + betDateTimeStr = makeEdate(betDateTimeStr, 32400000); + } + data.setBetDateTime(betDateTimeStr); + + if(siteUsername == null || siteUsername.equals("") || siteUsername.equals("invalid-user")) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("존재하지 않는 회원입니다"); + httpStatus = HttpStatus.OK; + return new ResponseEntity(response, httpStatus); + } + + long siteIdx = Long.parseLong(siteUsername.substring(0, 3), 16); + String memberId = siteUsername.substring(3, siteUsername.length()); + final String LOG_PREFIX = "#-CB::NEXUS::"+memberId+"::"+data.getTransactionKey()+"::callResult:::"; + log.info(LOG_PREFIX+ "Request::" + requestBody.toString()); + + if(data.getType().equals("turn_promotion")) { + data.setVendorKey("pragmaticplay_casino"); + } + + try { + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "nexus"); + sParam.put("vendorGameCode", data.getVendorKey()); + log.info(LOG_PREFIX + "getSiteVendorInfo::"+sParam.toString()); + HashMap siteVendorInfo = siteService.getSiteVendorInfo(sParam); + if(siteVendorInfo == null) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("존재하지 않는 회원입니다"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "존재하지 않는 회원입니다::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + if(!apiKey.equals(siteVendorInfo.get("vendorApiKey").toString())) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("API키가 일치하지 않습니다"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "API키가 일치하지 않습니다::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + // ##--isTransfer 처리-## + final String IS_TRANSFER = siteVendorInfo.get("isTransfer").toString(); + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + Double amountD = Double.parseDouble(data.getAmount()); + int amount = Math.abs(amountD.intValue()); + if(amount < 0) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("금액이 올바르지 않습니다"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "금액이 올바르지 않습니다::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + String vendorTranKey = data.getTransactionKey(); + String tranId = data.getTransactionKey(); + String betId = data.getParentTransactionKey(); + if(betId == null || betId.equals("")) { + betId = data.getTransactionKey(); + } + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("Y")) { + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(tranId); + if(cntTr > 0) { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(balance); + balanceData.setBeforeBalance(balance + amount); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "중복요청::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + // 베팅 체크 + int cntBet = siteService.getBetIdCheck2(betId); + if(cntBet == 0) { + response = new NexusResponse(); + response.setCode(-999); + response.setMsg("NOT_FOUND_REF_DATA"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "NOT_FOUND_REF_DATA::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + } + + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + String gameName = data.getGameName(); + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "nexus"); + tranParam.put("vendorTranKey", vendorTranKey); + tranParam.put("gameType", data.getGameType()); + tranParam.put("gameId", data.getGameId()); + tranParam.put("gameIdx", gameName); + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "nexus"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", gameName); + if(data.getGameId() == null) data.setGameId(""); + callBackObj.put("gameId", data.getGameId()); + callBackObj.put("gameType", data.getGameType()); + callBackObj.put("tranType", "credit"); + callBackObj.put("debit", 0); + callBackObj.put("credit", amount); + callBackObj.put("isCancel", 0); + if(data.getIsBonus().equals("true") || data.getIsPromo().equals("true") || data.getType().equals("turn_promotion")) { + callBackObj.put("isBonus", 1); + } else { + callBackObj.put("isBonus", 0); + } + callBackObj.put("requestAt", betDateTimeStr); + log.info(LOG_PREFIX + "SEND_RESULT request body: " + callBackObj.toString()); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("N")) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + log.info(LOG_PREFIX + "-----INSERT_RESULT_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_RESULT_END-----"); + + JSONObject resData = null; + if(data.getGameCategory().equals("casino")) { + resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } else { + resData = callBackService.changeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } + log.info(LOG_PREFIX + "SEND_RESULT status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_RESULT response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(balance); + balanceData.setBeforeBalance(balance - amount); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + } else if(resData.getLong("result_code") == 98) { + int balance = resData.getInt("balance"); + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(balance); + balanceData.setBeforeBalance(balance - amount); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + } else { + response = new NexusResponse(); + response.setCode(-999); + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + response.setMsg(msg); + httpStatus = HttpStatus.OK; + } + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + int afBalance = balance + amount; + + log.info(LOG_PREFIX + "-----INSERT_RESULT_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_RESULT_END-----"); + + tranParam.put("balance", afBalance); + tranParam.put("preBalance", balance); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(afBalance); + balanceData.setBeforeBalance(balance); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + + if(siteVendorInfo.get("siteCbUrl") != null && !"".equals(siteVendorInfo.get("siteCbUrl").toString())) { + callBackObj.put("balance", afBalance); + if(data.getGameCategory().equals("casino")) { + asyncCallBackService.asyncChangeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } else { + asyncCallBackService.asyncChangeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } + } + } + + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + response = new NexusResponse(); + response.setCode(-999); + response.setMsg("TIMEOUT_ERROR"); + httpStatus = HttpStatus.OK; + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + response = new NexusResponse(); + response.setCode(-999); + response.setMsg("RESULT_SERVER_ERROR"); + httpStatus = HttpStatus.OK; + } + + ResponseEntity res = new ResponseEntity(response, httpStatus); + log.info(LOG_PREFIX+ "Response::" + response.toString()); + + return res; + } + + + @ResponseBody + @RequestMapping(path = "/callCancel") + public ResponseEntity callCancel(HttpServletRequest request, @RequestBody NexusSmlRequest requestBody) throws Exception { + NexusResponse response = null; + HttpStatus httpStatus = null; + + String apiKey = requestBody.getApiKey(); + NexusSmlData data = requestBody.getParams(); + String siteUsername = data.getSiteUsername(); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + String betDateTimeStr = data.getCreatedAt(); + if(betDateTimeStr == null || betDateTimeStr.equals("")) { + betDateTimeStr = sdf.format(System.currentTimeMillis()); + } else { + betDateTimeStr = betDateTimeStr.replace("T", " ").replace("Z", ""); + betDateTimeStr = makeEdate(betDateTimeStr, 32400000); + } + data.setBetDateTime(betDateTimeStr); + + if(siteUsername == null || siteUsername.equals("") || siteUsername.equals("invalid-user")) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("존재하지 않는 회원입니다"); + httpStatus = HttpStatus.OK; + return new ResponseEntity(response, httpStatus); + } + + long siteIdx = Long.parseLong(siteUsername.substring(0, 3), 16); + String memberId = siteUsername.substring(3, siteUsername.length()); + final String LOG_PREFIX = "#-CB::NEXUS::"+memberId+"::"+data.getTransactionKey()+"::callCancel:::"; + log.info(LOG_PREFIX+ "Request::" + requestBody.toString()); + + try { + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "nexus"); + sParam.put("vendorGameCode", data.getVendorKey()); + log.info(LOG_PREFIX + "getSiteVendorInfo::"+sParam.toString()); + HashMap siteVendorInfo = siteService.getSiteVendorInfo(sParam); + if(siteVendorInfo == null) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("존재하지 않는 회원입니다"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "존재하지 않는 회원입니다::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + if(!apiKey.equals(siteVendorInfo.get("vendorApiKey").toString())) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("API키가 일치하지 않습니다"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "API키가 일치하지 않습니다::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + // ##--isTransfer 처리-## + final String IS_TRANSFER = siteVendorInfo.get("isTransfer").toString(); + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + Double amountD = Double.parseDouble(data.getAmount()); + int amount = Math.abs(amountD.intValue()); + if(amount < 0) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("금액이 올바르지 않습니다"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "금액이 올바르지 않습니다::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + String vendorTranKey = data.getTransactionKey(); + String tranId = data.getTransactionKey(); + String betId = data.getParentTransactionKey(); + if(betId == null || betId.equals("")) { + betId = data.getTransactionKey(); + } + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("Y")) { + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(tranId); + if(cntTr > 0) { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(balance); + balanceData.setBeforeBalance(balance + amount); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "중복요청::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + // 베팅 체크 + int cntBet = siteService.getBetIdCheck2(betId); + if(cntBet == 0) { + response = new NexusResponse(); + response.setCode(-999); + response.setMsg("NOT_FOUND_REF_DATA"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "NOT_FOUND_REF_DATA::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + } + + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + String gameName = data.getGameName(); + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "nexus"); + tranParam.put("vendorTranKey", vendorTranKey); + tranParam.put("gameType", data.getGameType()); + tranParam.put("gameId", data.getGameId()); + tranParam.put("gameIdx", gameName); + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + tranParam.put("isCancel", "Y"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "nexus"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", gameName); + if(data.getGameId() == null) data.setGameId(""); + callBackObj.put("gameId", data.getGameId()); + callBackObj.put("gameType", data.getGameType()); + callBackObj.put("tranType", "credit"); + callBackObj.put("debit", 0); + callBackObj.put("credit", amount); + callBackObj.put("isCancel", 1); + callBackObj.put("isBonus", 0); + callBackObj.put("requestAt", betDateTimeStr); + log.info(LOG_PREFIX + "SEND_CANCEL request body: " + callBackObj.toString()); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("N")) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + log.info(LOG_PREFIX + "-----INSERT_CANCEL_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_CANCEL_END-----"); + + JSONObject resData = null; + if(data.getGameCategory().equals("casino")) { + resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } else { + resData = callBackService.changeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } + log.info(LOG_PREFIX + "SEND_CANCEL status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_CANCEL response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(balance); + balanceData.setBeforeBalance(balance - amount); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + } else if(resData.getLong("result_code") == 98) { + int balance = resData.getInt("balance"); + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(balance); + balanceData.setBeforeBalance(balance - amount); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + } else { + response = new NexusResponse(); + response.setCode(-999); + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + response.setMsg(msg); + httpStatus = HttpStatus.OK; + } + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + int afBalance = balance + amount; + + log.info(LOG_PREFIX + "-----INSERT_CANCEL_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_CANCEL_END-----"); + + tranParam.put("balance", afBalance); + tranParam.put("preBalance", balance); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(afBalance); + balanceData.setBeforeBalance(balance); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + + if(siteVendorInfo.get("siteCbUrl") != null && !"".equals(siteVendorInfo.get("siteCbUrl").toString())) { + callBackObj.put("balance", afBalance); + if(data.getGameCategory().equals("casino")) { + asyncCallBackService.asyncChangeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } else { + asyncCallBackService.asyncChangeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } + } + } + + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + response = new NexusResponse(); + response.setCode(-999); + response.setMsg("TIMEOUT_ERROR"); + httpStatus = HttpStatus.OK; + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + response = new NexusResponse(); + response.setCode(-999); + response.setMsg("RESULT_SERVER_ERROR"); + httpStatus = HttpStatus.OK; + } + + ResponseEntity res = new ResponseEntity(response, httpStatus); + log.info(LOG_PREFIX+ "Response::" + response.toString()); + + return res; + } + + + @ResponseBody + @RequestMapping(path = "/callAdjust") + public ResponseEntity callAdjust(HttpServletRequest request, @RequestBody NexusSmlRequest requestBody) throws Exception { + NexusResponse response = null; + HttpStatus httpStatus = null; + + String apiKey = requestBody.getApiKey(); + NexusSmlData data = requestBody.getParams(); + String siteUsername = data.getSiteUsername(); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + String betDateTimeStr = data.getCreatedAt(); + if(betDateTimeStr == null || betDateTimeStr.equals("")) { + betDateTimeStr = sdf.format(System.currentTimeMillis()); + } else { + betDateTimeStr = betDateTimeStr.replace("T", " ").replace("Z", ""); + betDateTimeStr = makeEdate(betDateTimeStr, 32400000); + } + data.setBetDateTime(betDateTimeStr); + + if(siteUsername == null || siteUsername.equals("") || siteUsername.equals("invalid-user")) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("존재하지 않는 회원입니다"); + httpStatus = HttpStatus.OK; + return new ResponseEntity(response, httpStatus); + } + + long siteIdx = Long.parseLong(siteUsername.substring(0, 3), 16); + String memberId = siteUsername.substring(3, siteUsername.length()); + final String LOG_PREFIX = "#-CB::NEXUS::"+memberId+"::"+data.getTransactionKey()+"::callAdjust:::"; + log.info(LOG_PREFIX+ "Request::" + requestBody.toString()); + + try { + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "nexus"); + sParam.put("vendorGameCode", data.getVendorKey()); + log.info(LOG_PREFIX + "getSiteVendorInfo::"+sParam.toString()); + HashMap siteVendorInfo = siteService.getSiteVendorInfo(sParam); + if(siteVendorInfo == null) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("존재하지 않는 회원입니다"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "존재하지 않는 회원입니다::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + if(!apiKey.equals(siteVendorInfo.get("vendorApiKey").toString())) { + response = new NexusResponse(); + response.setCode(-1); + response.setMsg("API키가 일치하지 않습니다"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "API키가 일치하지 않습니다::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + // ##--isTransfer 처리-## + final String IS_TRANSFER = siteVendorInfo.get("isTransfer").toString(); + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + Double amountD = Double.parseDouble(data.getAmount()); + int amount = amountD.intValue(); + + String vendorTranKey = data.getTransactionKey(); + String tranId = data.getTransactionKey(); + String betId = data.getParentTransactionKey(); + if(betId == null || betId.equals("")) { + betId = data.getTransactionKey(); + } + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("Y")) { + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(tranId); + if(cntTr > 0) { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(balance); + balanceData.setBeforeBalance(balance + amount); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "중복요청::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + // 베팅 체크 + int cntBet = siteService.getBetIdCheck2(betId); + if(cntBet == 0) { + response = new NexusResponse(); + response.setCode(-999); + response.setMsg("NOT_FOUND_REF_DATA"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "NOT_FOUND_REF_DATA::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + } + + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + String gameName = data.getGameName(); + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "nexus"); + tranParam.put("vendorTranKey", vendorTranKey); + tranParam.put("gameType", data.getGameType()); + tranParam.put("gameId", data.getGameId()); + tranParam.put("gameIdx", gameName); + if(amount >= 0) { + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + } else { + tranParam.put("tranType", "debit"); + tranParam.put("depositAmt", amount*-1); + tranParam.put("creditAmt", "0"); + } + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "nexus"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", gameName); + if(data.getGameId() == null) data.setGameId(""); + callBackObj.put("gameId", data.getGameId()); + callBackObj.put("gameType", data.getGameType()); + callBackObj.put("tranType", "adjust"); + if(amount >= 0) { + callBackObj.put("debit", 0); + callBackObj.put("credit", amount); + } else { + callBackObj.put("debit", amount*-1); + callBackObj.put("credit", 0); + } + callBackObj.put("isCancel", 0); + callBackObj.put("isBonus", 0); + callBackObj.put("requestAt", betDateTimeStr); + log.info(LOG_PREFIX + "SEND_ADJUST request body: " + callBackObj.toString()); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("N")) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + log.info(LOG_PREFIX + "-----INSERT_ADJUST_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_ADJUST_END-----"); + + JSONObject resData = null; + if(data.getGameCategory().equals("casino")) { + resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } else { + resData = callBackService.changeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } + log.info(LOG_PREFIX + "SEND_ADJUST status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_ADJUST response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(balance); + balanceData.setBeforeBalance(balance + amount); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + } else if(resData.getLong("result_code") == 98) { + int balance = resData.getInt("balance"); + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(balance); + balanceData.setBeforeBalance(balance + amount); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + } else { + response = new NexusResponse(); + response.setCode(-999); + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + response.setMsg(msg); + httpStatus = HttpStatus.OK; + } + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + int afBalance = balance + amount; + + log.info(LOG_PREFIX + "-----INSERT_ADJUST_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_ADJUST_END-----"); + + tranParam.put("balance", afBalance); + tranParam.put("preBalance", balance); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + NexusBalanceData balanceData = new NexusBalanceData(); + balanceData.setBalance(afBalance); + balanceData.setBeforeBalance(balance); + balanceData.setCurrency("KRW"); + response = new NexusResponse(); + response.setCode(0); + response.setData(balanceData); + httpStatus = HttpStatus.OK; + + if(siteVendorInfo.get("siteCbUrl") != null && !"".equals(siteVendorInfo.get("siteCbUrl").toString())) { + callBackObj.put("balance", afBalance); + if(data.getGameCategory().equals("casino")) { + asyncCallBackService.asyncChangeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } else { + asyncCallBackService.asyncChangeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } + } + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + response = new NexusResponse(); + response.setCode(-999); + response.setMsg("TIMEOUT_ERROR"); + httpStatus = HttpStatus.OK; + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + response = new NexusResponse(); + response.setCode(-999); + response.setMsg("RESULT_SERVER_ERROR"); + httpStatus = HttpStatus.OK; + } + + ResponseEntity res = new ResponseEntity(response, httpStatus); + log.info(LOG_PREFIX+ "Response::" + response.toString()); + + return res; + } + + + /** + * 에볼루션 상세 콜백 + * @param request + * @param requestBody + * @return + * @throws Exception + */ + @ResponseBody + @RequestMapping(path = "/callDetail") + public ResponseEntity callDetail(HttpServletRequest request, @RequestBody net.sf.json.JSONObject requestBody) throws Exception { + NexusResponse response = null; + HttpStatus httpStatus = null; + + String apiKey = requestBody.getString("apiKey"); + final String LOG_PREFIX = "#-CB::callDetail::nexus::"+apiKey+":::"; + // log.info(LOG_PREFIX+ "Request::" + requestBody.toString()); + + try { + JSONObject bodyObj = new JSONObject(requestBody.toString()); + JSONArray params = bodyObj.getJSONArray("params"); + String prevRefId = ""; + for(int i=0; i(); + detailMap.put("refId", refId); + detailMap.put("orgDetail", orgDetail.toString()); + detailMap.put("parDetail", null); + try { + int result = siteService.insertEvoDetail(detailMap); + log.info(LOG_PREFIX2+ "insertEvoDetail result::" + result); + } catch(DataIntegrityViolationException de) { + log.error(LOG_PREFIX2+ "Duplicate refId"); + continue; + } + + } + + response = new NexusResponse(); + response.setCode(0); + response.setMsg("SUCCESS"); + httpStatus = HttpStatus.OK; + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + response = new NexusResponse(); + response.setCode(-8); + response.setMsg("TIMEOUT_ERROR"); + httpStatus = HttpStatus.OK; + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + response = new NexusResponse(); + response.setCode(-9); + response.setMsg("DETAIL_SERVER_ERROR"); + httpStatus = HttpStatus.OK; + } + + ResponseEntity res = new ResponseEntity(response, httpStatus); + log.info(LOG_PREFIX+ "Response::" + response.toString()); + + return res; + } + + + /** + * UTC 시간을 한국 시간(KST)으로 변환 + * @param utcTimeStr UTC 시간 문자열 (예: 2026-02-06T04:39:05.243Z) + * @return 한국 시간 문자열 (예: 2026-02-06T13:39:05.243+09:00) + */ + private static String convertUtcToKstTime(String utcTimeStr) { + try { + if (utcTimeStr == null || !utcTimeStr.endsWith("Z")) { + return utcTimeStr; + } + + // UTC 시간 파싱 + Instant instant = Instant.parse(utcTimeStr); + // 한국 시간대로 변환 (UTC+9) + ZonedDateTime kstTime = instant.atZone(ZoneId.of("Asia/Seoul")); + // ISO 8601 형식으로 포맷 (타임존 포함) + return kstTime.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME); + } catch (Exception e) { + log.error("UTC to KST conversion error: " + e.getMessage()); + return utcTimeStr; // 변환 실패시 원본 반환 + } + } + + /** + * JSON 객체를 재귀적으로 순회하며 시간 필드를 UTC에서 KST로 변환 + * @param jsonObj 변환할 JSON 객체 + */ + private static void convertUtcToKst(JSONObject jsonObj) { + try { + // 변환할 시간 필드 목록 + String[] timeFields = {"startedAt", "settledAt", "placedOn", "recordedAt"}; + + Iterator keys = jsonObj.keys(); + while (keys.hasNext()) { + String key = keys.next(); + Object value = jsonObj.get(key); + + // 시간 필드인 경우 변환 + for (String timeField : timeFields) { + if (key.equals(timeField) && value instanceof String) { + String utcTime = (String) value; + String kstTime = convertUtcToKstTime(utcTime); + jsonObj.put(key, kstTime); + break; + } + } + + // 중첩된 JSONObject인 경우 재귀 호출 + if (value instanceof JSONObject) { + convertUtcToKst((JSONObject) value); + } + // 중첩된 JSONArray인 경우 각 요소 처리 + else if (value instanceof JSONArray) { + JSONArray jsonArray = (JSONArray) value; + for (int i = 0; i < jsonArray.length(); i++) { + Object arrayItem = jsonArray.get(i); + if (arrayItem instanceof JSONObject) { + convertUtcToKst((JSONObject) arrayItem); + } + } + } + } + } catch (Exception e) { + log.error("JSON time conversion error: " + e.getMessage()); + } + } + + + private static String makeDateStrForUTC(boolean flag, String strDate) { + String result = ""; + if(flag) { + // 2022-05-01 00:00:00.000 => 2022-05-01T00:00:00.000Z + result = strDate.replace(" ", "T") + "Z"; + } else { + // 2022-05-01T00:00:00.000Z => 2022-05-01 00:00:00.000 + result = strDate.replace("T", " ").replace("Z", ""); + } + return result; + } + + private static String makeEdate(String paramDate, int flag) { + // TODO Auto-generated method stub + String eDate = ""; + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + try { + if(paramDate == null) { + // eDate = sdf.format(System.currentTimeMillis()); + eDate = sdf.format(System.currentTimeMillis() - 32400000); + } else { + Date date = sdf.parse(paramDate); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + calendar.add(Calendar.MILLISECOND, flag); + Date date2 = calendar.getTime(); + eDate = sdf.format(date2); + } + } catch(Exception e) { + log.error(e.getMessage()); + } + return eDate; + } +} diff --git a/src/main/java/com/bb/front/CallBackOnixController.java b/src/main/java/com/bb/front/CallBackOnixController.java new file mode 100644 index 0000000..e2f6665 --- /dev/null +++ b/src/main/java/com/bb/front/CallBackOnixController.java @@ -0,0 +1,973 @@ +package com.bb.front; + +import java.net.SocketTimeoutException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; + +import org.apache.http.conn.ConnectTimeoutException; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.ResourceAccessException; +import org.springframework.web.client.RestTemplate; + +import com.bb.model.OnixResponse; +import com.bb.service.AsyncSiteService; +import com.bb.service.CallBackService; +import com.bb.service.SiteService; + +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +/** + * Onix Seamless API Callback Controller + * + * API 엔드포인트: + * - /balance: 유저 잔고 조회 + * - /changeBalance: 유저 머니 변경 (베팅, 승리, 취소 등) + * + * 모든 응답은 2초 이내로 반환되어야 함 + * CORS 헤더 필수: Access-Control-Allow-Origin: * + */ +@Slf4j +@RequiredArgsConstructor +@SecurityRequirement(name = "Authorization") +@EnableScheduling +@RestController +@RequestMapping("/api/callback/onix") +public class CallBackOnixController { + + @Autowired + private SiteService siteService; + + @Autowired + private CallBackService callBackService; + + @Autowired + private AsyncSiteService asyncCallBackService; + + @Autowired + RestTemplate restTemplate; + + + @ResponseBody + @RequestMapping(path = {"/balance", "/balance/"}) + public ResponseEntity balance(HttpServletRequest request, @RequestParam("userid") String onixUsername) throws Exception { + OnixResponse response = null; + + long siteIdx = Long.parseLong(onixUsername.substring(0, 3), 16); + String memberId = onixUsername.substring(3, onixUsername.length()); + final String LOG_PREFIX = "#-CB::ONIX::balance::"+memberId+":::"; + log.info(LOG_PREFIX+ "Request::" + onixUsername); + + try { + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + log.info(LOG_PREFIX + "SITE_API_INFO_PARAM::"+sParam.toString()); + HashMap siteApiInfo = siteService.getSiteApiInfo(sParam); + if(siteApiInfo == null) { + log.error(LOG_PREFIX+ "Error Msg: NOT_FOUND_SITE_INFO"); + response = new OnixResponse(); + response.setResult(0); + response.setBalance(0); + return new ResponseEntity(response, HttpStatus.OK); + } + + if(siteApiInfo.get("memberIdx") == null) { + log.error(LOG_PREFIX+ "존재하지 않는 회원"); + response = new OnixResponse(); + response.setResult(0); + response.setBalance(0); + return new ResponseEntity(response, HttpStatus.OK); + } + + // ##--isTransfer 처리-## + long balance = 0L; + if("N".equals(siteApiInfo.get("isTransfer").toString())) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + JSONObject member = new JSONObject(); + member.put("userId", memberId); + log.info(LOG_PREFIX+ "balance Req ::"+ member.toString()); + JSONObject resData = callBackService.getBalance(siteApiInfo, member); + if(resData == null) { + log.error(LOG_PREFIX+ "Error Msg: BALANCE_CALLBACK_ERROR"); + response = new OnixResponse(); + response.setResult(0); + response.setBalance(0); + return new ResponseEntity(response, HttpStatus.OK); + } + log.info(LOG_PREFIX+ "balance Res ::"+ resData.toString()); + balance = resData.getLong("balance"); // int -> long 변경 + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + balance = siteService.getUserBalance(balanceMap); + + if(siteApiInfo.get("siteCbUrl") != null && !"".equals(siteApiInfo.get("siteCbUrl").toString())) { + JSONObject member = new JSONObject(); + member.put("userId", memberId); + member.put("balance", balance); + asyncCallBackService.asyncBalance(LOG_PREFIX, siteApiInfo, member); + } + } + + // Onix 문서: {"result":1, "balance": 10000} 형식으로 응답 + response = new OnixResponse(); + response.setResult(1); // 성공 = 1 + response.setBalance(balance); + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + response = new OnixResponse(); + response.setResult(0); + response.setBalance(0); + return new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + response = new OnixResponse(); + response.setResult(0); + response.setBalance(0); + return new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + ResponseEntity res = new ResponseEntity(response, HttpStatus.OK); + log.info(LOG_PREFIX+ "Response::" + response.toString()); + + return res; + } + + @PostMapping(path = {"/changeBalance", "/changeBalance/"}) + public ResponseEntity changeBalance(HttpServletRequest request, @RequestBody net.sf.json.JSONObject requestBody) { + + ResponseEntity resEntity = null; + log.info("#-CB::ONIX::changeBalance::Request::" + requestBody.toString()); + + String onixUsername = requestBody.getString("userid"); + long siteIdx = Long.parseLong(onixUsername.substring(0, 3), 16); + String memberId = onixUsername.substring(3, onixUsername.length()); + String transactionId = requestBody.getString("tranid"); + String transactionType = requestBody.getString("type"); + + final String LOG_PREFIX = "#-CB::ONIX::changeBalance::"+memberId+"::"+transactionId+"::"+transactionType+":::"; + log.info(LOG_PREFIX+ "Request::" + requestBody.toString()); + + try { + // "time":"2023-07-05 21:16:39.473" + String betDateTimeStr = requestBody.getString("time"); + log.info(LOG_PREFIX+ "========== BF_betDateTimeStr::" + betDateTimeStr); + betDateTimeStr = betDateTimeStr.substring(0, 19); + betDateTimeStr = betDateTimeStr.replace("T", " "); + //log.info(LOG_PREFIX+ "========== MF_betDateTimeStr::" + betDateTimeStr); + //betDateTimeStr = makeEdate(LOG_PREFIX, betDateTimeStr, 32400000); + log.info(LOG_PREFIX+ "========== AF_betDateTimeStr::" + betDateTimeStr); + + // 사이트 정보 조회 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "onix"); + sParam.put("vendorGameCode", "evolution"); + log.info(LOG_PREFIX + "getSiteVendorInfo::" + sParam.toString()); + HashMap siteVendorInfo = siteService.getSiteVendorInfo(sParam); + + if(siteVendorInfo == null) { + log.error(LOG_PREFIX + "존재하지 않는 회원입니다"); + OnixResponse response = OnixResponse.failure(); + resEntity = new ResponseEntity(response, HttpStatus.OK); + return resEntity; + } + + if(transactionType.equals("bet")) { + int amount = Math.abs(requestBody.getInt("amount")); + resEntity = callBet(LOG_PREFIX, siteIdx, memberId, requestBody, betDateTimeStr, siteVendorInfo, amount); + + } else if(transactionType.equals("win") || transactionType.equals("lose")) { + int amount = Math.abs(requestBody.getInt("amount")); + resEntity = callWin(LOG_PREFIX, siteIdx, memberId, requestBody, betDateTimeStr, siteVendorInfo, amount); + + } else if(transactionType.equals("cancel")) { + int amount = Math.abs(requestBody.getInt("amount")); + resEntity = callCancel(LOG_PREFIX, siteIdx, memberId, requestBody, betDateTimeStr, siteVendorInfo, amount); + + } else { + log.error(LOG_PREFIX + "unknown_transaction_type"); + OnixResponse response = OnixResponse.failure(); + resEntity = new ResponseEntity(response, HttpStatus.OK); + return resEntity; + } + + } catch (ResourceAccessException rae) { + if (rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX + "[ConnectTimeoutException]" + rae.getMessage()); + } + if (rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX + "[SocketTimeoutException]" + rae.getMessage()); + } + if (rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX + "[InterruptedException]" + rae.getMessage()); + } + + OnixResponse response = OnixResponse.failure(); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + return resEntity; + + } catch (Exception e) { + log.error(LOG_PREFIX + "[Exception]" + e.toString()); + e.printStackTrace(); + OnixResponse response = OnixResponse.failure(); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + return resEntity; + } + + log.info(LOG_PREFIX + "Response::" + resEntity.toString()); + + return resEntity; + } + + private ResponseEntity callBet(String LOG_PREFIX, long siteIdx, String memberId, + net.sf.json.JSONObject transaction, String betDateTimeStr, HashMap siteVendorInfo, int amount) { + + LOG_PREFIX = LOG_PREFIX + "callBet:::"; + ResponseEntity resEntity = null; + OnixResponse response = new OnixResponse(); + + // ##--isTransfer 처리-## + final String IS_TRANSFER = siteVendorInfo.get("isTransfer").toString(); + + try { + + String gameType = ""; // transaction.optString("gametype"); + String gameName = transaction.optString("title"); + + String tableId = transaction.optString("subcode"); + String targetTableId = tableId.replaceAll(" ", "").toLowerCase(); + + String banGameType = siteVendorInfo.get("banGameType").toString().replaceAll(" ", "").toLowerCase(); + String banGameId = siteVendorInfo.get("banGameId").toString().replaceAll(" ", "").toLowerCase(); + + if (!"".equals(gameType) && !"".equals(banGameType) && banGameType.contains(gameType + "|")) { + log.error(LOG_PREFIX + "Ban Game Type : " + gameType); + response = OnixResponse.failure(); + resEntity = new ResponseEntity(response, HttpStatus.OK); + return resEntity; + } + + if (!"".equals(targetTableId) && !"".equals(banGameId) && banGameId.contains(targetTableId + "|")) { + log.error(LOG_PREFIX + "Ban Game Id : " + banGameId); + response = OnixResponse.failure(); + resEntity = new ResponseEntity(response, HttpStatus.OK); + return resEntity; + } + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + String tranId = transaction.getString("tranid"); + String betId = transaction.getString("realround"); + String betKey = betId; + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("Y")) { + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(tranId); + if(cntTr > 0) { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + log.error(LOG_PREFIX+ "중복요청::Response::" + response.toString()); + response = OnixResponse.success(balance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + return resEntity; + } + } + + if (siteVendorInfo.get("lastInVendorIdx") == null || "0".equals(siteVendorInfo.get("lastInVendorIdx").toString())) { + HashMap memParam = new HashMap<>(); + memParam.put("siteIdx", siteIdx); + memParam.put("memberIdx", memberIdx); + memParam.put("lastInVendorIdx", Integer.parseInt(siteVendorInfo.get("vendorIdx").toString())); + int updResult = siteService.updMemLastVendorIdx(memParam); + } else { + int lastInVendorIdx = Integer.parseInt(siteVendorInfo.get("lastInVendorIdx").toString()); + if (lastInVendorIdx != vendorIdx) { + log.error(LOG_PREFIX + "VendorIdx doesn't match"); + response = OnixResponse.failure(); + resEntity = new ResponseEntity(response, HttpStatus.OK); + return resEntity; + } + } + + long siteCredit = Long.parseLong(siteVendorInfo.get("credit").toString()); + // ##--isTransfer 처리-## + if (siteCredit < amount && IS_TRANSFER.equals("N")) { + log.error(LOG_PREFIX + "NO_SITE_CREDIT"); + response = OnixResponse.failure(); + resEntity = new ResponseEntity(response, HttpStatus.OK); + return resEntity; + } + + // 최대 베팅 금액 처리 (userMaxBet 우선 적용) + long siteMaxBet = Long.parseLong(siteVendorInfo.get("siteMaxBet").toString()); + long userMaxBet = 0; + if(siteVendorInfo.get("userMaxBet") != null && !siteVendorInfo.get("userMaxBet").toString().isEmpty()) { + try { + userMaxBet = Long.parseLong(siteVendorInfo.get("userMaxBet").toString()); + } catch (NumberFormatException e) { + userMaxBet = 0; + } + } + + // 최종 maxBet 결정: userMaxBet이 0이면 siteMaxBet 사용, 0이 아니면 userMaxBet 사용 + long finalMaxBet = (userMaxBet > 0) ? userMaxBet : siteMaxBet; + log.info(LOG_PREFIX+ "MaxBet Info - siteMaxBet: " + siteMaxBet + ", userMaxBet: " + userMaxBet + ", finalMaxBet: " + finalMaxBet); + + if (finalMaxBet < amount) { + log.error(LOG_PREFIX + "MAX_BET_AMOUNT_OVER"); + log.error(LOG_PREFIX + "finalMaxBet : " + finalMaxBet + ", amount : " + amount); + response = OnixResponse.failure(); + resEntity = new ResponseEntity(response, HttpStatus.OK); + return resEntity; + } + + boolean isParsing = false; + String game = transaction.optString("game"); + if("evolution_new".equals(game)) { + isParsing = true; + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "onix"); + tranParam.put("vendorTranKey", betKey); + tranParam.put("gameType", gameType); + tranParam.put("gameId", tableId); + tranParam.put("gameIdx", gameName); + tranParam.put("tranType", "debit"); + tranParam.put("depositAmt", amount); + tranParam.put("creditAmt", "0"); + tranParam.put("isCancel", "N"); + if(isParsing) { + tranParam.put("isTie", "P"); + } else { + tranParam.put("isTie", "N"); + } + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("betKey", betKey); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "onix"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", gameName); + callBackObj.put("gameId", tableId); + callBackObj.put("gameType", gameType); + callBackObj.put("tranType", "debit"); + callBackObj.put("debit", amount); + callBackObj.put("credit", 0); + callBackObj.put("isCancel", 0); + callBackObj.put("isBonus", 0); + if(isParsing) { + callBackObj.put("isData", "Y"); + } else { + callBackObj.put("isData", "N"); + } + callBackObj.put("requestAt", betDateTimeStr); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("N")) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + log.info(LOG_PREFIX + "-----INSERT_BET_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_BET_END-----"); + + log.info(LOG_PREFIX + "SEND_BET request body: " + callBackObj.toString()); + JSONObject resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + log.info(LOG_PREFIX + "SEND_BET status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_BET response body: " + resData.toString()); + + if (resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + long balance = resData.getLong("balance"); + response = OnixResponse.success(balance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + } else if (resData.getLong("result_code") == 98) { + long balance = resData.getLong("balance"); + response = OnixResponse.success(balance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + } else if (resData.getLong("result_code") == 80) { + long balance = resData.getLong("balance"); + response = OnixResponse.success(balance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + } else { + String msg = ""; + if (resData.has("error_msg")) msg = resData.getString("error_msg"); + log.error(LOG_PREFIX + msg); + response = OnixResponse.failure(); + resEntity = new ResponseEntity(response, HttpStatus.OK); + } + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + int afBalance = balance - amount; + + if(balance < amount) { + log.error(LOG_PREFIX + "beforeBalance is less than amount"); + response = OnixResponse.failure(); + resEntity = new ResponseEntity(response, HttpStatus.OK); + return resEntity; + } + + log.info(LOG_PREFIX + "-----INSERT_BET_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_BET_END-----"); + + tranParam.put("balance", afBalance); + tranParam.put("preBalance", balance); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + response = OnixResponse.success(afBalance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + + if(siteVendorInfo.get("siteCbUrl") != null && !"".equals(siteVendorInfo.get("siteCbUrl").toString())) { + callBackObj.put("balance", afBalance); + asyncCallBackService.asyncChangeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } + } + + } catch (ResourceAccessException rae) { + if (rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX + "[ConnectTimeoutException]" + rae.getMessage()); + } + if (rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX + "[SocketTimeoutException]" + rae.getMessage()); + } + if (rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX + "[InterruptedException]" + rae.getMessage()); + } + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } catch (Exception e) { + log.error(LOG_PREFIX + "[Exception]" + e.toString()); + e.printStackTrace(); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + return resEntity; + } + + private ResponseEntity callWin(String LOG_PREFIX, long siteIdx, String memberId, + net.sf.json.JSONObject transaction, String betDateTimeStr, HashMap siteVendorInfo, int amount) { + + LOG_PREFIX = LOG_PREFIX + "callWin:::"; + ResponseEntity resEntity = null; + OnixResponse response = new OnixResponse(); + + // ##--isTransfer 처리-## + final String IS_TRANSFER = siteVendorInfo.get("isTransfer").toString(); + + try { + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + String tranId = transaction.getString("tranid"); + String betId = transaction.getString("realround"); + String betKey = betId; + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + + net.sf.json.JSONArray details = transaction.optJSONArray("details"); + net.sf.json.JSONObject detailObj = null; + String gameType = ""; // transaction.optString(""); + String gameName = transaction.optString("title"); + if(details != null && details.size() > 0) { + detailObj = details.optJSONObject(0); + if(detailObj != null) { + gameType = detailObj.optString("gameType"); + HashMap detailMap = new HashMap<>(); + detailMap.put("refId", betId); + detailMap.put("orgDetail", detailObj.toString()); + detailMap.put("parDetail", null); + try { + int result = siteService.insertEvoDetail(detailMap); + log.info(LOG_PREFIX+ "insertEvoDetail result::" + result); + } catch(DataIntegrityViolationException de) { + log.error(LOG_PREFIX+ "Duplicate refId"); + } + } + if(gameType == null) gameType = ""; + } + String tableId = transaction.optString("subcode"); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("Y")) { + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(tranId); + if(cntTr > 0) { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + log.error(LOG_PREFIX+ "중복요청::Response::" + response.toString()); + response = OnixResponse.success(balance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + return resEntity; + } + + // 베팅 체크 + int cntBet = siteService.getBetIdCheck2(betId); + if(cntBet == 0) { + // 처리한 베팅 존재X + log.error(LOG_PREFIX+ "처리한 베팅 존재X"); + response = OnixResponse.failure(); + resEntity = new ResponseEntity(response, HttpStatus.OK); + return resEntity; + } + } + + if (siteVendorInfo.get("lastInVendorIdx") == null || "0".equals(siteVendorInfo.get("lastInVendorIdx").toString())) { + HashMap memParam = new HashMap<>(); + memParam.put("siteIdx", siteIdx); + memParam.put("memberIdx", memberIdx); + memParam.put("lastInVendorIdx", Integer.parseInt(siteVendorInfo.get("vendorIdx").toString())); + int updResult = siteService.updMemLastVendorIdx(memParam); + } else { + int lastInVendorIdx = Integer.parseInt(siteVendorInfo.get("lastInVendorIdx").toString()); + if (lastInVendorIdx != vendorIdx) { + log.error(LOG_PREFIX + "VendorIdx doesn't match"); + response = OnixResponse.failure(); + resEntity = new ResponseEntity(response, HttpStatus.OK); + return resEntity; + } + } + + boolean isParsing = false; + String game = transaction.optString("game"); + if("evolution_new".equals(game)) { + isParsing = true; + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "onix"); + tranParam.put("vendorTranKey", betKey); + tranParam.put("gameType", gameType); + tranParam.put("gameId", tableId); + tranParam.put("gameIdx", gameName); + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + tranParam.put("isCancel", "N"); + if(isParsing) { + tranParam.put("isTie", "P"); + } else { + tranParam.put("isTie", "N"); + } + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("betKey", betKey); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "onix"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", gameName); + callBackObj.put("gameId", tableId); + callBackObj.put("gameType", gameType); + callBackObj.put("tranType", "credit"); + callBackObj.put("debit", 0); + callBackObj.put("credit", amount); + callBackObj.put("isCancel", 0); + callBackObj.put("isBonus", 0); + if(isParsing) { + callBackObj.put("isData", "Y"); + } else { + callBackObj.put("isData", "N"); + } + callBackObj.put("requestAt", betDateTimeStr); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("N")) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + log.info(LOG_PREFIX + "-----INSERT_RESULT_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_RESULT_END-----"); + + log.info(LOG_PREFIX + "SEND_RESULT request body: " + callBackObj.toString()); + JSONObject resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + log.info(LOG_PREFIX + "SEND_RESULT status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_RESULT response body: " + resData.toString()); + + if (resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + long balance = resData.getLong("balance"); + response = OnixResponse.success(balance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + } else if (resData.getLong("result_code") == 98) { + long balance = resData.getLong("balance"); + response = OnixResponse.success(balance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + } else { + String msg = ""; + if (resData.has("error_msg")) msg = resData.getString("error_msg"); + log.error(LOG_PREFIX + msg); + response = OnixResponse.failure(); + resEntity = new ResponseEntity(response, HttpStatus.OK); + } + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + int afBalance = balance + amount; + + log.info(LOG_PREFIX + "-----INSERT_RESULT_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_RESULT_END-----"); + + tranParam.put("balance", afBalance); + tranParam.put("preBalance", balance); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + response = OnixResponse.success(afBalance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + + if(siteVendorInfo.get("siteCbUrl") != null && !"".equals(siteVendorInfo.get("siteCbUrl").toString())) { + callBackObj.put("balance", afBalance); + asyncCallBackService.asyncChangeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } + } + + } catch (ResourceAccessException rae) { + if (rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX + "[ConnectTimeoutException]" + rae.getMessage()); + } + if (rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX + "[SocketTimeoutException]" + rae.getMessage()); + } + if (rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX + "[InterruptedException]" + rae.getMessage()); + } + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } catch (Exception e) { + log.error(LOG_PREFIX + "[Exception]" + e.toString()); + e.printStackTrace(); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + return resEntity; + } + + private ResponseEntity callCancel(String LOG_PREFIX, long siteIdx, String memberId, + net.sf.json.JSONObject transaction, String betDateTimeStr, HashMap siteVendorInfo, int amount) { + + LOG_PREFIX = LOG_PREFIX + "callCancel:::"; + ResponseEntity resEntity = null; + OnixResponse response = new OnixResponse(); + + // ##--isTransfer 처리-## + final String IS_TRANSFER = siteVendorInfo.get("isTransfer").toString(); + + try { + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + String tranId = transaction.getString("tranid"); + String betId = transaction.getString("realround"); + String betKey = betId; + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + + net.sf.json.JSONArray details = transaction.optJSONArray("details"); + net.sf.json.JSONObject detailObj = null; + String gameType = ""; // transaction.optString(""); + String gameName = transaction.optString("title"); + if(details != null && details.size() > 0) { + detailObj = details.optJSONObject(0); + if(detailObj != null) { + gameType = detailObj.optString("gameType"); + HashMap detailMap = new HashMap<>(); + detailMap.put("refId", betId); + detailMap.put("orgDetail", detailObj.toString()); + detailMap.put("parDetail", null); + try { + int result = siteService.insertEvoDetail(detailMap); + log.info(LOG_PREFIX+ "insertEvoDetail result::" + result); + } catch(DataIntegrityViolationException de) { + log.error(LOG_PREFIX+ "Duplicate refId"); + } + } + if(gameType == null) gameType = ""; + } + String tableId = transaction.optString("subcode"); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("Y")) { + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(tranId); + if(cntTr > 0) { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + log.error(LOG_PREFIX+ "중복요청::Response::" + response.toString()); + response = OnixResponse.success(balance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + return resEntity; + } + + // 베팅 체크 + int cntBet = siteService.getBetIdCheck2(betId); + if(cntBet == 0) { + // 처리한 베팅 존재X + log.error(LOG_PREFIX+ "처리한 베팅 존재X"); + response = OnixResponse.failure(); + resEntity = new ResponseEntity(response, HttpStatus.OK); + return resEntity; + } + } + + if (siteVendorInfo.get("lastInVendorIdx") == null || "0".equals(siteVendorInfo.get("lastInVendorIdx").toString())) { + HashMap memParam = new HashMap<>(); + memParam.put("siteIdx", siteIdx); + memParam.put("memberIdx", memberIdx); + memParam.put("lastInVendorIdx", Integer.parseInt(siteVendorInfo.get("vendorIdx").toString())); + int updResult = siteService.updMemLastVendorIdx(memParam); + } else { + int lastInVendorIdx = Integer.parseInt(siteVendorInfo.get("lastInVendorIdx").toString()); + if (lastInVendorIdx != vendorIdx) { + log.error(LOG_PREFIX + "VendorIdx doesn't match"); + response = OnixResponse.failure(); + resEntity = new ResponseEntity(response, HttpStatus.OK); + return resEntity; + } + } + + boolean isParsing = false; + String game = transaction.optString("game"); + if("evolution_new".equals(game)) { + isParsing = true; + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "onix"); + tranParam.put("vendorTranKey", betKey); + tranParam.put("gameType", gameType); + tranParam.put("gameId", tableId); + tranParam.put("gameIdx", gameName); + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + tranParam.put("isCancel", "Y"); + if(isParsing) { + tranParam.put("isTie", "P"); + } else { + tranParam.put("isTie", "N"); + } + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("betKey", betKey); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "onix"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", gameName); + callBackObj.put("gameId", tableId); + callBackObj.put("gameType", gameType); + callBackObj.put("tranType", "credit"); + callBackObj.put("debit", 0); + callBackObj.put("credit", amount); + callBackObj.put("isCancel", 1); + callBackObj.put("isBonus", 0); + if(isParsing) { + callBackObj.put("isData", "Y"); + } else { + callBackObj.put("isData", "N"); + } + callBackObj.put("requestAt", betDateTimeStr); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("N")) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + log.info(LOG_PREFIX + "-----INSERT_CANCEL_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_CANCEL_END-----"); + + log.info(LOG_PREFIX + "SEND_CANCEL request body: " + callBackObj.toString()); + JSONObject resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + log.info(LOG_PREFIX + "SEND_CANCEL status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_CANCEL response body: " + resData.toString()); + + if (resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + long balance = resData.getLong("balance"); + response = OnixResponse.success(balance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + } else if (resData.getLong("result_code") == 98) { + long balance = resData.getLong("balance"); + response = OnixResponse.success(balance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + } else { + String msg = ""; + if (resData.has("error_msg")) msg = resData.getString("error_msg"); + log.error(LOG_PREFIX + msg); + response = OnixResponse.failure(); + resEntity = new ResponseEntity(response, HttpStatus.OK); + } + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + int afBalance = balance + amount; + + log.info(LOG_PREFIX + "-----INSERT_RESULT_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_RESULT_END-----"); + + tranParam.put("balance", afBalance); + tranParam.put("preBalance", balance); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + response = OnixResponse.success(afBalance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + + if(siteVendorInfo.get("siteCbUrl") != null && !"".equals(siteVendorInfo.get("siteCbUrl").toString())) { + callBackObj.put("balance", afBalance); + asyncCallBackService.asyncChangeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } + } + + } catch (ResourceAccessException rae) { + if (rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX + "[ConnectTimeoutException]" + rae.getMessage()); + } + if (rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX + "[SocketTimeoutException]" + rae.getMessage()); + } + if (rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX + "[InterruptedException]" + rae.getMessage()); + } + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } catch (Exception e) { + log.error(LOG_PREFIX + "[Exception]" + e.toString()); + e.printStackTrace(); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + return resEntity; + } + + private static String makeEdate(String LOG_PREFIX, String paramDate, int flag) { + // TODO Auto-generated method stub + String eDate = ""; + SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + try { + Date date = sdf1.parse(paramDate); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + calendar.add(Calendar.MILLISECOND, flag); + Date date2 = calendar.getTime(); + eDate = sdf2.format(date2); + } catch(Exception e) { + log.error(LOG_PREFIX+ "makeEdate::Exception::"+e.getMessage()); + } + return eDate; + } +} diff --git a/src/main/java/com/bb/front/CallBackPowerBall.java b/src/main/java/com/bb/front/CallBackPowerBall.java new file mode 100644 index 0000000..7d665fb --- /dev/null +++ b/src/main/java/com/bb/front/CallBackPowerBall.java @@ -0,0 +1,710 @@ +package com.bb.front; + +import java.net.SocketTimeoutException; +import java.util.HashMap; +import java.util.List; + +import jakarta.servlet.http.HttpServletRequest; + +import org.apache.http.conn.ConnectTimeoutException; +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.ResourceAccessException; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.WebClientRequestException; +import org.springframework.web.reactive.function.client.WebClientResponseException; + +import com.bb.model.PowerballData; +import com.bb.model.PowerballRequest; +import com.bb.model.PowerballResponse; +import com.bb.service.CallBackService; +import com.bb.service.SiteService; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@RestController +@Slf4j +@RequestMapping("/api/callback/powerball") +@RequiredArgsConstructor +@SecurityRequirement(name = "Authorization") +public class CallBackPowerBall { + + + @Autowired + SiteService siteService; + + @Autowired + CallBackService callBackService; + + @Autowired + WebClient webClient; + + + @ResponseBody + @RequestMapping(path = "/balance") + public ResponseEntity balance(HttpServletRequest request, @RequestParam String id, @RequestParam String siteName) throws Exception { + PowerballResponse response = null; + PowerballData data = null; + HttpStatus httpStatus = HttpStatus.OK; + + //사이트정보 + HashMap sParam = new HashMap(); + long siteIdx = Long.parseLong(id.substring(0, 3), 16); + String memberId = id.substring(3, id.length()); + final String LOG_PREFIX = "#-CB::POWER_BALL::"+memberId+"::BALANCE::::"; + + log.info(LOG_PREFIX+ "id:"+id+", siteName:"+siteName); + + try { + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + HashMap siteApiInfo = siteService.getSiteApiInfo(sParam); + if(siteApiInfo == null) { + response = new PowerballResponse(); + response.setResult("FAILED"); + response.setMsg("NOT_FOUND_USER"); + data = new PowerballData(); + data.setSiteId(siteName); + data.setMemId(id); + data.setBalance("0"); + response.setData(data); + log.error(LOG_PREFIX+ "Response Body: "+response.toString()); + return new ResponseEntity(response, httpStatus); + } + + JSONObject member = new JSONObject(); + member.put("userId", memberId); + log.info(LOG_PREFIX + "SEND_BALANCE request body: " + member.toString()); + + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/json"); + header.add("Accept", "application/json"); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + + ResponseEntity responseEntity = webClient.post() + .uri(siteApiInfo.get("siteCbUrl")+"/balance") + .headers(h -> h.addAll(header)) + .bodyValue(member.toString()) + .retrieve() + .toEntity(String.class) + .block(); + + log.info(LOG_PREFIX+ "SEND_BALANCE status code: " + responseEntity.getStatusCode()); + log.info(LOG_PREFIX+ "SEND_BALANCE response body: " + responseEntity.getBody()); + + JSONObject resData = new JSONObject(responseEntity.getBody()); + int balance = resData.getInt("balance"); + + response = new PowerballResponse(); + response.setResult("SUCCESS"); + response.setMsg(""); + data = new PowerballData(); + data.setSiteId(siteName); + data.setMemId(id); + data.setBalance(Integer.toString(balance)); + response.setData(data); + + } catch (WebClientResponseException e) { + // HttpServerErrorException handling + if (e.getStatusCode().is5xxServerError()) { + log.error(LOG_PREFIX+ "WebClientResponseException 5xx: " + e.getResponseBodyAsString()); + response = new PowerballResponse(); + response.setResult("FAILED"); + response.setMsg("BALANCE_SERVER_ERROR"); + data = new PowerballData(); + data.setSiteId(siteName); + data.setMemId(id); + data.setBalance("0"); + response.setData(data); + } + // HttpClientErrorException handling + else if (e.getStatusCode().is4xxClientError()) { + log.error(LOG_PREFIX+ "WebClientResponseException 4xx: " + e.getResponseBodyAsString()); + response = new PowerballResponse(); + response.setResult("FAILED"); + response.setMsg("BALANCE_SERVER_ERROR"); + data = new PowerballData(); + data.setSiteId(siteName); + data.setMemId(id); + data.setBalance("0"); + response.setData(data); + } else { + log.error(LOG_PREFIX+ "WebClientResponseException: " + e.getResponseBodyAsString()); + response = new PowerballResponse(); + response.setResult("FAILED"); + response.setMsg("BALANCE_SERVER_ERROR"); + data = new PowerballData(); + data.setSiteId(siteName); + data.setMemId(id); + data.setBalance("0"); + response.setData(data); + } + + } catch (WebClientRequestException e) { + // 타임아웃 등 연결 오류 + Throwable cause = e.getCause(); + if (cause instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectTimeoutException: " + cause.getMessage()); + } else if (cause instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "SocketTimeoutException: " + cause.getMessage()); + } else { + log.error(LOG_PREFIX+ "WebClientRequestException: " + e.getMessage()); + } + + response = new PowerballResponse(); + response.setResult("FAILED"); + response.setMsg("TIMEOUT_ERROR"); + data = new PowerballData(); + data.setSiteId(siteName); + data.setMemId(id); + data.setBalance("0"); + response.setData(data); + + /* + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectTimeoutException: " + rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "SocketTimeoutException: " + rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "InterruptedException: " + rae.getMessage()); + } + + response = new PowerballResponse(); + response.setResult("FAILED"); + response.setMsg("TIMEOUT_ERROR"); + data = new PowerballData(); + data.setSiteId(siteName); + data.setMemId(id); + data.setBalance("0"); + response.setData(data); + */ + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception: " + e.getMessage()); + response = new PowerballResponse(); + response.setResult("FAILED"); + response.setMsg("BALANCE_SERVER_ERROR"); + data = new PowerballData(); + data.setSiteId(siteName); + data.setMemId(id); + data.setBalance("0"); + response.setData(data); + } + + log.error(LOG_PREFIX+ "Response Body: " + response.toString()); + ResponseEntity res = new ResponseEntity(response, httpStatus); + + return res; + } + + + @ResponseBody + @RequestMapping(path = "/bet") + public ResponseEntity bet(HttpServletRequest request, @RequestBody net.sf.json.JSONObject reqBodyObj) throws Exception { + PowerballResponse response = null; + PowerballData data = null; + HttpStatus httpStatus = HttpStatus.OK; + + ObjectMapper mapper = new ObjectMapper(); + PowerballRequest reqBody = mapper.readValue(reqBodyObj.toString(), new TypeReference() {}); + + //사이트정보 + HashMap sParam = new HashMap(); + long siteIdx = Long.parseLong(reqBody.getId().substring(0, 3), 16); + String memberId = reqBody.getId().substring(3, reqBody.getId().length()); + + String siteId = reqBody.getSiteId(); + String id = reqBody.getId(); + String transactionId = reqBody.getBetId(); + String gameName = reqBody.getGameName(); + + String gameType = reqBody.getGameType(); + String gameTypeName = ""; + String betType = reqBody.getBetType(); + String betTypeName = ""; + String rateType = ""; + + final String LOG_PREFIX = "#-CB::POWER_BALL::"+memberId+"::"+transactionId+"::BET::::"; + + log.info(LOG_PREFIX+ "reqBodyObj:"+reqBodyObj); + log.info(LOG_PREFIX+ "reqBody:"+reqBody); + + try { + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", ""); + sParam.put("vendorGameCode", "powerball"); + log.info(LOG_PREFIX + "getSiteVendorInfo::"+sParam.toString()); + HashMap siteVendorInfo = siteService.getSiteVendorInfo(sParam); + if(siteVendorInfo == null) { + response = new PowerballResponse(); + response.setResult("FAILED"); + response.setMsg("NOT_FOUND_USER"); + data = new PowerballData(); + data.setSiteId(siteId); + data.setMemId(id); + data.setBalance("0"); + response.setData(data); + log.error(LOG_PREFIX+ "Response Body: "+response.toString()); + return new ResponseEntity(response, httpStatus); + } + log.info(LOG_PREFIX + "siteVendorInfo::"+siteVendorInfo.toString()); + + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + int amount = Math.abs(reqBody.getBetAmt()); + long siteCredit = Long.parseLong(siteVendorInfo.get("credit").toString()); + if(siteCredit < amount) { + response = new PowerballResponse(); + response.setResult("FAILED"); + response.setMsg("NO_SITE_CREDIT"); + data = new PowerballData(); + data.setSiteId(siteId); + data.setMemId(id); + data.setBalance("0"); + response.setData(data); + log.error(LOG_PREFIX+ "Response Body: "+response.toString()); + return new ResponseEntity(response, httpStatus); + } + + String vendorTranKey = transactionId; + String tranId = siteId + "#D#" + vendorTranKey; + String betId = siteId + "#" + vendorTranKey; + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + + List> infoList = siteService.getPowerBallInfoList(gameType); + for(HashMap info : infoList) { + if(betType.equals(info.get("betType").toString())) { + gameTypeName = info.get("gameTypeName").toString(); + betTypeName = info.get("betTypeName").toString(); + rateType = info.get("rateType").toString(); + } + } + + if(gameTypeName.equals("") || betTypeName.equals("")) { + response = new PowerballResponse(); + response.setResult("FAILED"); + response.setMsg("NOT_FOUND_GAME_TYPE"); + data = new PowerballData(); + data.setSiteId(siteId); + data.setMemId(id); + data.setBalance("0"); + response.setData(data); + log.error(LOG_PREFIX+ "Response Body: "+response.toString()); + return new ResponseEntity(response, httpStatus); + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "powerball"); + tranParam.put("vendorTranKey", vendorTranKey); + tranParam.put("gameType", gameType); + tranParam.put("gameId", ""); + tranParam.put("gameIdx", gameName+"("+gameTypeName+")"); + tranParam.put("tranType", "debit"); + tranParam.put("depositAmt", amount); + tranParam.put("creditAmt", 0); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + + log.info(LOG_PREFIX + "-----INSERT_BET_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_BET_END-----"); + + JSONObject debit = new JSONObject(); + debit.put("betId", betId); + debit.put("tranId", tranId); + debit.put("userId", memberId); + debit.put("vendorIdx", vendorIdx); + debit.put("vendorKey", vendorKey); + debit.put("vendor", "powerball"); + debit.put("gameIdx", vendorIdx); + debit.put("gameKey", gameName+"("+gameTypeName+")"); + debit.put("gameType", gameType); + debit.put("gameId", ""); + debit.put("tranType", "debit"); + debit.put("debit", amount); + debit.put("credit", 0); + debit.put("isCancel", 0); + debit.put("isBonus", 0); + + /** + * betType : 유저가 배팅한 타입 + * gameType : 게임 타입 + * resultType : 결과 타입 + */ + + JSONArray detailsArr = new JSONArray(); + + JSONObject detailItem = new JSONObject(); + detailItem.put("detailId", betType+"("+betTypeName+")"); + detailItem.put("detailType", rateType); + detailItem.put("detailName", gameType+"("+gameTypeName+")"); + detailItem.put("betAmt", amount); + detailItem.put("betWinAmt", 0); + detailsArr.put(detailItem); + + debit.put("betDetails", detailsArr); + + log.info(LOG_PREFIX + "SEND_DEBIT request body: " + debit.toString()); + JSONObject resData = new JSONObject(); + resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, debit); + log.info(LOG_PREFIX + "SEND_DEBIT status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_DEBIT response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + + response = new PowerballResponse(); + response.setResult("SUCCESS"); + response.setMsg(""); + data = new PowerballData(); + data.setSiteId(siteId); + data.setMemId(id); + data.setBalance(Integer.toString(balance)); + response.setData(data); + } else { + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + response = new PowerballResponse(); + response.setResult("FAILED"); + response.setMsg(msg); + data = new PowerballData(); + data.setSiteId(siteId); + data.setMemId(id); + data.setBalance("0"); + response.setData(data); + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectTimeoutException: " + rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "SocketTimeoutException: " + rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "InterruptedException: " + rae.getMessage()); + } + + response = new PowerballResponse(); + response.setResult("FAILED"); + response.setMsg("TIMEOUT_ERROR"); + data = new PowerballData(); + data.setSiteId(siteId); + data.setMemId(id); + data.setBalance("0"); + response.setData(data); + + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception: " + e.getMessage()); + response = new PowerballResponse(); + response.setResult("FAILED"); + response.setMsg("BET_SERVER_ERROR"); + data = new PowerballData(); + data.setSiteId(siteId); + data.setMemId(id); + data.setBalance("0"); + response.setData(data); + } + + + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "Response Body: " + response.toString()); + ResponseEntity res = new ResponseEntity(response, httpStatus); + + return res; + } + + + @ResponseBody + @RequestMapping(path = "/result") + public ResponseEntity result(HttpServletRequest request, @RequestBody net.sf.json.JSONObject reqBodyObj) throws Exception { + PowerballResponse response = null; + PowerballData data = null; + HttpStatus httpStatus = HttpStatus.OK; + + ObjectMapper mapper = new ObjectMapper(); + PowerballRequest reqBody = mapper.readValue(reqBodyObj.toString(), new TypeReference() {}); + + //사이트정보 + HashMap sParam = new HashMap(); + long siteIdx = Long.parseLong(reqBody.getId().substring(0, 3), 16); + String memberId = reqBody.getId().substring(3, reqBody.getId().length()); + + String siteId = reqBody.getSiteId(); + String id = reqBody.getId(); + String transactionId = reqBody.getBetId(); + String gameName = reqBody.getGameName(); + + String gameType = reqBody.getGameType(); + String gameTypeName = ""; + String betType = reqBody.getBetType(); + String betTypeName = ""; + if(reqBody.getResultType() == null) { + reqBody.setResultType(""); + } + String resultType = reqBody.getResultType(); + String resultTypeName = ""; + String rateType = ""; + + final String LOG_PREFIX = "#-CB::POWER_BALL::"+memberId+"::"+transactionId+"::RESULT::::"; + + log.info(LOG_PREFIX+ "reqBodyObj:"+reqBodyObj); + log.info(LOG_PREFIX+ "reqBody:"+reqBody); + + try { + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", ""); + sParam.put("vendorGameCode", "powerball"); + log.info(LOG_PREFIX + "getSiteVendorInfo::"+sParam.toString()); + HashMap siteVendorInfo = siteService.getSiteVendorInfo(sParam); + if(siteVendorInfo == null) { + response = new PowerballResponse(); + response.setResult("FAILED"); + response.setMsg("NOT_FOUND_USER"); + data = new PowerballData(); + data.setSiteId(siteId); + data.setMemId(id); + data.setBalance("0"); + response.setData(data); + log.error(LOG_PREFIX+ "Response Body: "+response.toString()); + return new ResponseEntity(response, httpStatus); + } + log.info(LOG_PREFIX + "siteVendorInfo::"+siteVendorInfo.toString()); + + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + int amount = Math.abs(reqBody.getBetWinAmt()); + long siteCredit = Long.parseLong(siteVendorInfo.get("credit").toString()); + if(siteCredit < amount) { + response = new PowerballResponse(); + response.setResult("FAILED"); + response.setMsg("NO_SITE_CREDIT"); + data = new PowerballData(); + data.setSiteId(siteId); + data.setMemId(id); + data.setBalance("0"); + response.setData(data); + log.error(LOG_PREFIX+ "Response Body: "+response.toString()); + return new ResponseEntity(response, httpStatus); + } + + String vendorTranKey = transactionId; + String tranId = siteId + "#C#" + vendorTranKey; + String betId = siteId + "#" + vendorTranKey; + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + + List> infoList = siteService.getPowerBallInfoList(gameType); + for(HashMap info : infoList) { + if(betType.equals(info.get("betType").toString())) { + gameTypeName = info.get("gameTypeName").toString(); + betTypeName = info.get("betTypeName").toString(); + rateType = info.get("rateType").toString(); + } + if(resultType.equals(info.get("betType").toString())) { + resultTypeName = info.get("betTypeName").toString(); + } + } + + if(gameTypeName.equals("") || betTypeName.equals("")) { + response = new PowerballResponse(); + response.setResult("FAILED"); + response.setMsg("NOT_FOUND_GAME_TYPE"); + data = new PowerballData(); + data.setSiteId(siteId); + data.setMemId(id); + data.setBalance("0"); + response.setData(data); + log.error(LOG_PREFIX+ "Response Body: "+response.toString()); + return new ResponseEntity(response, httpStatus); + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "powerball"); + tranParam.put("vendorTranKey", vendorTranKey); + tranParam.put("gameType", gameType); + tranParam.put("gameId", ""); + tranParam.put("gameIdx", gameName+"("+gameTypeName+")"); + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", 0); + tranParam.put("creditAmt", amount); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + + /** + * betType : 유저가 배팅한 타입 + * gameType : 게임 타입 + * resultType : 결과 타입 + */ + + JSONArray detailsArr = new JSONArray(); + JSONObject detailItem = new JSONObject(); + detailItem.put("detailId", betType+"("+betTypeName+")"); + detailItem.put("detailType", rateType); + detailItem.put("detailName", gameType+"("+gameTypeName+")"); + detailItem.put("betAmt", 0); + detailItem.put("betWinAmt", amount); + + JSONObject detailCredit = new JSONObject(); + detailCredit.put("rateType", rateType); + detailCredit.put("betType", betType); + detailCredit.put("betTypeName", betTypeName); + detailCredit.put("gameType", gameType); + detailCredit.put("gameTypeName", gameTypeName); + detailCredit.put("resultType", resultType); + detailCredit.put("resultTypeName", resultTypeName); + detailCredit.put("betAmt", reqBody.getBetAmt()); + detailCredit.put("betWinAmt", reqBody.getBetWinAmt()); + + detailItem.put("detail", detailCredit); + detailsArr.put(detailItem); + + tranParam.put("detail", detailCredit.toString()); + log.info(LOG_PREFIX + "-----INSERT_BET_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_BET_END-----"); + + JSONObject credit = new JSONObject(); + credit.put("betId", betId); + credit.put("tranId", tranId); + credit.put("userId", memberId); + credit.put("vendorIdx", vendorIdx); + credit.put("vendorKey", vendorKey); + credit.put("vendor", "powerball"); + credit.put("gameIdx", vendorIdx); + credit.put("gameKey", gameName+"("+gameTypeName+")"); + credit.put("gameType", gameType); + credit.put("gameId", ""); + credit.put("tranType", "credit"); + credit.put("debit", 0); + credit.put("credit", amount); + credit.put("isCancel", 0); + credit.put("isBonus", 0); + credit.put("betDetails", detailsArr); + + log.info(LOG_PREFIX + "SEND_CREDIT request body: " + credit.toString()); + JSONObject resData = new JSONObject(); + resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, credit); + log.info(LOG_PREFIX + "SEND_CREDIT status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_CREDIT response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + + response = new PowerballResponse(); + response.setResult("SUCCESS"); + response.setMsg(""); + data = new PowerballData(); + data.setSiteId(siteId); + data.setMemId(id); + data.setBalance(Integer.toString(balance)); + response.setData(data); + } else { + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + response = new PowerballResponse(); + response.setResult("FAILED"); + response.setMsg(msg); + data = new PowerballData(); + data.setSiteId(siteId); + data.setMemId(id); + data.setBalance("0"); + response.setData(data); + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectTimeoutException: " + rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "SocketTimeoutException: " + rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "InterruptedException: " + rae.getMessage()); + } + + response = new PowerballResponse(); + response.setResult("FAILED"); + response.setMsg("TIMEOUT_ERROR"); + data = new PowerballData(); + data.setSiteId(siteId); + data.setMemId(id); + data.setBalance("0"); + response.setData(data); + + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception: " + e.getMessage()); + response = new PowerballResponse(); + response.setResult("FAILED"); + response.setMsg("RESULT_SERVER_ERROR"); + data = new PowerballData(); + data.setSiteId(siteId); + data.setMemId(id); + data.setBalance("0"); + response.setData(data); + } + + + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "Response Body: " + response.toString()); + ResponseEntity res = new ResponseEntity(response, httpStatus); + + return res; + } +} diff --git a/src/main/java/com/bb/front/CallBackPowerBallGame.java b/src/main/java/com/bb/front/CallBackPowerBallGame.java new file mode 100644 index 0000000..0dd3246 --- /dev/null +++ b/src/main/java/com/bb/front/CallBackPowerBallGame.java @@ -0,0 +1,469 @@ +package com.bb.front; + +import java.net.SocketTimeoutException; +import java.util.HashMap; +import java.util.UUID; + +import org.apache.http.conn.ConnectTimeoutException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.ResourceAccessException; + +import com.bb.service.CallBackService; +import com.bb.service.SiteService; + +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import net.sf.json.JSONObject; + +@RestController +@Slf4j +@RequestMapping("/api/callback/pbg") +@RequiredArgsConstructor +@SecurityRequirement(name = "Authorization") +public class CallBackPowerBallGame { + + @Autowired + SiteService siteService; + + @Autowired + CallBackService callBackService; + + + @ResponseBody + @RequestMapping(path = "/balance") + public ResponseEntity balance(HttpServletRequest request, @RequestBody net.sf.json.JSONObject requestBody) throws Exception { + JSONObject resData = new JSONObject(); + HttpStatus httpStatus = null; + String userId = requestBody.getString("userId"); + + long siteIdx = Long.parseLong(userId.substring(0, 3), 16); + String memberId = userId.substring(3, userId.length()); + final String LOG_PREFIX = "#-CB::PBG::balance::"+memberId+":::"; + + try { + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + + HashMap siteApiInfo = siteService.getSiteApiInfo(sParam); + if(siteApiInfo==null) { + log.error(LOG_PREFIX+ "Error Msg: NOT_FOUND_SITE_INFO"); + return new ResponseEntity(resData, HttpStatus.INTERNAL_SERVER_ERROR); + } + + org.codehaus.jettison.json.JSONObject member = new org.codehaus.jettison.json.JSONObject(); + member.put("userId", memberId); + log.info(LOG_PREFIX+ "Callback URL::" + siteApiInfo.get("siteCbUrl")+"/balance"); + log.info(LOG_PREFIX+ "Callback Param::" + member.toString()); + + member.put("userId", memberId); + org.codehaus.jettison.json.JSONObject resBalancedData = callBackService.getBalance(siteApiInfo, member); + if(resBalancedData == null) { + log.error(LOG_PREFIX+ "Error Msg: BALANCE_CALLBACK_ERROR"); + return new ResponseEntity(resData, HttpStatus.INTERNAL_SERVER_ERROR); + } + int balance = resBalancedData.getInt("balance"); + resData.put("success", true); + + JSONObject data = new JSONObject(); + + data.put("balance", balance); + resData.put("data", data); + httpStatus = HttpStatus.OK; + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + log.error(LOG_PREFIX+ "[ResourceAccessException]"+rae.getMessage()); + httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; + resData.put("success", false); + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.getMessage()); + resData.put("success", false); + httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; + } + + ResponseEntity res = new ResponseEntity(resData, httpStatus); + log.info(LOG_PREFIX+ "Response: "+resData.toString()); + + return new ResponseEntity(resData, HttpStatus.OK); + } + + + @ResponseBody + @PostMapping(path = "/bet", produces = "application/json") // JSON만 생산 + public ResponseEntity bet(HttpServletRequest request, @RequestBody JSONObject requestBody) throws Exception { + + String userId = requestBody.getString("userId"); + //JSONObject transaction = requestBody.getJSONObject("transaction"); + String tranType = "bet"; + long siteIdx = Long.parseLong(userId.substring(0, 3), 16); + String memberId = userId.substring(3, userId.length()); + final String LOG_PREFIX = "#-CB::PBG::bet::"+memberId+"::"+tranType+":::"; + log.info(LOG_PREFIX+ "Request Body: "+requestBody.toString()); + + JSONObject resData = new JSONObject(); + HttpStatus httpStatus = null; + + try { + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "pbg"); + sParam.put("vendorGameCode", "pbg"); + HashMap siteApiInfo = siteService.getSiteVendorInfo(sParam); + if(siteApiInfo==null) { + log.error(LOG_PREFIX+ "siteApiInfo is null "+tranType+" "+userId+"::"+ "Error Msg: NOT_FOUND_SITE_INFO"); + return new ResponseEntity(resData, HttpStatus.INTERNAL_SERVER_ERROR); + } + + long amount = requestBody.getLong("betAmt"); + + long memberIdx = Long.parseLong(siteApiInfo.get("memberIdx").toString()); + long vendorIdx = Long.parseLong(siteApiInfo.get("vendorIdx").toString()); + + String siteId = siteApiInfo.get("siteId").toString(); + String vendorApiId = siteApiInfo.get("vendorApiId").toString(); + String vendorKey = siteApiInfo.get("vendorKey").toString(); + + // 2025-06-10T07:12:54.355000Z + + String betDateTimeStr = requestBody.getString("betDate")+".000"; + + + if(amount < 0) { + long siteCredit = Long.parseLong(siteApiInfo.get("credit").toString()); + if(siteCredit < amount) { + log.error(LOG_PREFIX+ "SITE_IDX: "+siteIdx+" NO_SITE_CREDIT"); + return new ResponseEntity(resData, HttpStatus.INTERNAL_SERVER_ERROR); + } + + long siteMaxBet = Long.parseLong(siteApiInfo.get("siteMaxBet").toString()); + if(siteMaxBet < amount) { + log.error(LOG_PREFIX+ "SITE_IDX: "+siteIdx+"MAX_BET_AMOUNT_OVER"); + return new ResponseEntity(resData, HttpStatus.INTERNAL_SERVER_ERROR); + } + } + UUID uuid = UUID.randomUUID(); + String uid = uuid.toString(); + + String vendorTranKey = requestBody.getString("gameId")+uid; + String tranId = requestBody.getString("gameId")+uid; + String betId = requestBody.getString("gameId"); + + String gameName = requestBody.getString("gameType") +"_"+requestBody.getString("betType"); + String gameId = "1"; + String gameType = "minigame"; + + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", "MINIGAME"); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "pbg"); + tranParam.put("vendorTranKey", vendorTranKey); + tranParam.put("gameType", gameType); + tranParam.put("gameId", ""); + tranParam.put("gameIdx", gameName); + + tranParam.put("tranType", "debit"); + tranParam.put("depositAmt", Math.abs(amount)); + tranParam.put("creditAmt", "0"); + + //tranParam.put("isCancel", "N"); + + tranParam.put("isCancel", "N"); + + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + log.info(LOG_PREFIX+ "-----INSERT_BET_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX+ "-----INSERT_BET_END-----"); + + org.codehaus.jettison.json.JSONObject callBackObj = new org.codehaus.jettison.json.JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "pbg"); + callBackObj.put("gameIdx", 1); + callBackObj.put("gameKey", gameName); + callBackObj.put("gameId", gameId); + callBackObj.put("gameType", gameType); + + callBackObj.put("tranType", "debit"); + callBackObj.put("debit", Math.abs(amount)); + callBackObj.put("credit", 0); + callBackObj.put("isCancel", 0); + callBackObj.put("isBonus", 0); + + callBackObj.put("requestAt", ""); + log.info(LOG_PREFIX+ "SEND_BET request body: " + callBackObj.toString()); + org.codehaus.jettison.json.JSONObject resTranData = callBackService.changeBalance(LOG_PREFIX, siteApiInfo, callBackObj); + log.info(LOG_PREFIX+ "SEND_BET response body: " + resTranData.toString()); + + if(resTranData.getLong("result_code") == 0) { + // 성공 + tranParam.put("balance", resTranData.getLong("balance")); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX+ "UPDATE_CALLBACK_API_STATUS END"); + + long balance = resTranData.getLong("balance"); + JSONObject data = new JSONObject(); + data.put("balance", balance); + + resData.put("success", true); + resData.put("data", data); + httpStatus = HttpStatus.OK; + + } else if(resTranData.getLong("result_code") == 98) { + // 중복 + + + resData.put("success", false); + + httpStatus = HttpStatus.OK; + } else { + // 실패 + log.error(LOG_PREFIX+ "CALLBACK_ERROR"); + httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "::"+userId+"::"+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "::"+userId+"::"+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "::"+userId+"::"+ "[InterruptedException]"+rae.getMessage()); + } + + log.error(LOG_PREFIX+ "::"+userId+"::"+ "[ResourceAccessException]"+rae.getMessage()); + + httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; + resData.put("success", false); + + } catch (Exception e) { + log.error(LOG_PREFIX+ "#-PBG::::"+userId+"::"+ "[Exception]"+e.getMessage()); + + httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; + resData.put("success", false); + } + + ResponseEntity res = new ResponseEntity(resData, httpStatus); + log.info(LOG_PREFIX+ "::"+userId+"::"+ "Response: "+resData.toString()); + + return new ResponseEntity(resData, httpStatus); + } + + @ResponseBody + @PostMapping(path = "/result", produces = "application/json") // JSON만 생산 + public ResponseEntity result(HttpServletRequest request, @RequestBody JSONObject requestBody) throws Exception { + + String userId = requestBody.getString("userId"); + //JSONObject transaction = requestBody.getJSONObject("transaction"); + String tranType = "result"; + long siteIdx = Long.parseLong(userId.substring(0, 3), 16); + String memberId = userId.substring(3, userId.length()); + final String LOG_PREFIX = "#-CB::PBG::RESULT::"+memberId+"::"+tranType+":::"; + log.info(LOG_PREFIX+ "Request Body: "+requestBody.toString()); + + JSONObject resData = new JSONObject(); + HttpStatus httpStatus = null; + + net.sf.json.JSONArray resultList = requestBody.getJSONArray("result"); + Long lastBalance =0L; + + try { + for(int r=0;r(resData, HttpStatus.INTERNAL_SERVER_ERROR); + } + + long amount = tranbet.getLong("betWinAmt"); + + long memberIdx = Long.parseLong(siteApiInfo.get("memberIdx").toString()); + long vendorIdx = Long.parseLong(siteApiInfo.get("vendorIdx").toString()); + + String siteId = siteApiInfo.get("siteId").toString(); + String vendorApiId = siteApiInfo.get("vendorApiId").toString(); + String vendorKey = siteApiInfo.get("vendorKey").toString(); + + // 2025-06-10T07:12:54.355000Z + + String betDateTimeStr = tranbet.getString("betDate")+".000"; + + + UUID uuid = UUID.randomUUID(); + String uid = uuid.toString(); + + String vendorTranKey = tranbet.getString("gameId")+uid; + String tranId = tranbet.getString("gameId")+uid; + String betId = tranbet.getString("gameId"); + + String gameName = tranbet.getString("gameType") +"_"+tranbet.getString("betType"); + String gameId = "1"; + String gameType = "minigame"; + + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", "MINIGAME"); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "pbg"); + tranParam.put("vendorTranKey", vendorTranKey); + tranParam.put("gameType", gameType); + tranParam.put("gameId", ""); + tranParam.put("gameIdx", gameName); + + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", 0); + tranParam.put("creditAmt", Math.abs(amount)); + + //tranParam.put("isCancel", "N"); + + tranParam.put("isCancel", "N"); + + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + log.info(LOG_PREFIX+ "-----RESULT-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX+ "-----INSERT_RESULT_END-----"); + + org.codehaus.jettison.json.JSONObject callBackObj = new org.codehaus.jettison.json.JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "pbg"); + callBackObj.put("gameIdx", 1); + callBackObj.put("gameKey", gameName); + callBackObj.put("gameId", gameId); + callBackObj.put("gameType", gameType); + + callBackObj.put("tranType", "credit"); + callBackObj.put("debit", 0); + callBackObj.put("credit", Math.abs(amount)); + callBackObj.put("isCancel", 0); + callBackObj.put("isBonus", 0); + + callBackObj.put("requestAt", ""); + log.info(LOG_PREFIX+ "SEND_RESULT request body: " + callBackObj.toString()); + org.codehaus.jettison.json.JSONObject resTranData = callBackService.changeBalance(LOG_PREFIX, siteApiInfo, callBackObj); + log.info(LOG_PREFIX+ "SEND_RESULT response body: " + resTranData.toString()); + + if(resTranData.getLong("result_code") == 0) { + // 성공 + tranParam.put("balance", resTranData.getLong("balance")); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX+ "UPDATE_CALLBACK_API_STATUS END"); + + lastBalance = resTranData.getLong("balance"); + + + } else if(resTranData.getLong("result_code") == 98) { + // 중복 + //resData.put("success", false); + } else { + // 실패 + // log.error(LOG_PREFIX+ "CALLBACK_ERROR"); + httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; + } + Thread.sleep(300); + } catch (Exception e) { + log.error(LOG_PREFIX+ "#-POWER RESULT ERROR::::"+userId+"::"+ "[Exception]"+e.getMessage()); + + //httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; + // resData.put("success", false); + } + } + + JSONObject data = new JSONObject(); + data.put("balance", lastBalance); + + resData.put("success", true); + resData.put("data", data); + httpStatus = HttpStatus.OK; + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "::"+userId+"::"+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "::"+userId+"::"+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "::"+userId+"::"+ "[InterruptedException]"+rae.getMessage()); + } + + log.error(LOG_PREFIX+ "::"+userId+"::"+ "[ResourceAccessException]"+rae.getMessage()); + + httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; + resData.put("success", false); + + } catch (Exception e) { + log.error(LOG_PREFIX+ "#-Grand::::"+userId+"::"+ "[Exception]"+e.getMessage()); + + httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; + resData.put("success", false); + } + + ResponseEntity res = new ResponseEntity(resData, httpStatus); + log.info(LOG_PREFIX+ "::"+userId+"::"+ "Response: "+resData.toString()); + + return new ResponseEntity(resData, httpStatus); + } + +} diff --git a/src/main/java/com/bb/front/CallBackPracpController.java b/src/main/java/com/bb/front/CallBackPracpController.java new file mode 100644 index 0000000..3279b4b --- /dev/null +++ b/src/main/java/com/bb/front/CallBackPracpController.java @@ -0,0 +1,1193 @@ +package com.bb.front; + +import java.net.SocketTimeoutException; +import java.nio.charset.StandardCharsets; +import java.text.SimpleDateFormat; +import java.util.Base64; +import java.util.HashMap; + +import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import jakarta.servlet.http.HttpServletRequest; + +import org.apache.http.conn.ConnectTimeoutException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.ResourceAccessException; + +import com.bb.service.AsyncSiteService; +import com.bb.service.CallBackService; +import com.bb.service.SiteService; + +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import net.sf.json.JSONObject; + +@Slf4j +@RequestMapping("/api/cb/pracp") +@RequiredArgsConstructor +@SecurityRequirement(name = "Authorization") +@EnableScheduling +@RestController +public class CallBackPracpController { + + @Autowired + SiteService siteService; + + @Autowired + CallBackService callBackService; + + @Autowired + AsyncSiteService asyncCallBackService; + + + @ResponseBody + @GetMapping(value = "/{agentId}/balance") + public ResponseEntity balance(HttpServletRequest request, @PathVariable String agentId, @RequestParam("player_code") String playerCode) throws Exception { + JSONObject resData = new JSONObject(); + JSONObject resultObj = new JSONObject(); + HttpStatus httpStatus = HttpStatus.OK; + + HashMap keyParam = new HashMap<>(); + keyParam.put("agentId", agentId); + keyParam.put("vendorTitle", "pracp"); + HashMap apiKeyInfo = siteService.getApiKeyInfo2(keyParam); + + String pracpUserId = decryptAES256(playerCode, apiKeyInfo.get("callbackPrivateKey"), apiKeyInfo.get("callbackPublicKey")); + if(pracpUserId == null || "".equals(pracpUserId)) pracpUserId = playerCode; + + long siteIdx = Long.parseLong(pracpUserId.substring(0, 3), 16); + String memberId = pracpUserId.substring(3, pracpUserId.length()); + final String LOG_PREFIX = "#-CB::PRACP::balance::"+memberId+":::"; + + log.info(LOG_PREFIX+ "PathVariable::agentId::"+agentId); + log.info(LOG_PREFIX+ "RequestParam::playerCode::"+playerCode); + + try { + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + HashMap siteApiInfo = siteService.getSiteApiInfo(sParam); + if(siteApiInfo == null) { + log.error(LOG_PREFIX+ "Error Msg: NOT_FOUND_SITE_INFO"); + resData.put("status", "FAIL"); + resultObj.put("balance", 0); + resData.put("result", resultObj); + return new ResponseEntity(resData, httpStatus); + } + + // ##--isTransfer 처리-## + int balance = 0; + if("N".equals(siteApiInfo.get("isTransfer").toString())) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + org.codehaus.jettison.json.JSONObject member = new org.codehaus.jettison.json.JSONObject(); + member.put("userId", memberId); + log.info(LOG_PREFIX+ "Callback URL::" + siteApiInfo.get("siteCbUrl")+"/balance"); + log.info(LOG_PREFIX+ "Callback Param::" + member.toString()); + + member.put("userId", memberId); + org.codehaus.jettison.json.JSONObject resBalancedData = callBackService.getBalance(siteApiInfo, member); + if(resBalancedData == null) { + log.error(LOG_PREFIX+ "Error Msg: BALANCE_CALLBACK_ERROR"); + resData.put("status", "FAIL"); + resultObj.put("balance", 0); + resData.put("result", resultObj); + return new ResponseEntity(resData, httpStatus); + } + balance = resBalancedData.getInt("balance"); + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + balance = siteService.getUserBalance(balanceMap); + + if(siteApiInfo.get("siteCbUrl") != null && !"".equals(siteApiInfo.get("siteCbUrl").toString())) { + org.codehaus.jettison.json.JSONObject member = new org.codehaus.jettison.json.JSONObject(); + member.put("userId", memberId); + member.put("balance", balance); + asyncCallBackService.asyncBalance(LOG_PREFIX, siteApiInfo, member); + } + } + + resData.put("status", "OK"); + resultObj.put("balance", balance); + resData.put("result", resultObj); + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + log.error(LOG_PREFIX+ "[ResourceAccessException]"+rae.getMessage()); + + resData.put("status", "FAIL"); + resultObj.put("balance", 0); + resData.put("result", resultObj); + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.getMessage()); + + resData.put("status", "FAIL"); + resultObj.put("balance", 0); + resData.put("result", resultObj); + } + + ResponseEntity res = new ResponseEntity(resData, httpStatus); + log.info(LOG_PREFIX+ "Response: "+resData.toString()); + + return res; + } + + @ResponseBody + @PostMapping(value = "/{agentId}/transaction") + public ResponseEntity transaction(HttpServletRequest request, @PathVariable String agentId, @RequestBody JSONObject requestBody) throws Exception { + ResponseEntity resEntity = null; + JSONObject resData = new JSONObject(); + JSONObject resultObj = new JSONObject(); + HttpStatus httpStatus = HttpStatus.OK; + + HashMap keyParam = new HashMap<>(); + keyParam.put("agentId", agentId); + keyParam.put("vendorTitle", "pracp"); + HashMap apiKeyInfo = siteService.getApiKeyInfo2(keyParam); + + String playerCode = requestBody.getString("player_code"); + String pracpUserId = decryptAES256(playerCode, apiKeyInfo.get("callbackPrivateKey"), apiKeyInfo.get("callbackPublicKey")); + if(pracpUserId == null || "".equals(pracpUserId)) pracpUserId = playerCode; + + long siteIdx = Long.parseLong(pracpUserId.substring(0, 3), 16); + String memberId = pracpUserId.substring(3, pracpUserId.length()); + String transactionId = requestBody.getString("uuid"); + final String LOG_PREFIX = "#-CB::PRACP::transaction::"+memberId+"::"+transactionId+"::"; + log.info(LOG_PREFIX+ "Request::" + requestBody.toString()); + + log.info(LOG_PREFIX+ "PathVariable::agentId::"+agentId); + log.info(LOG_PREFIX+ "RequestParam::playerCode::"+playerCode); + + try { + String transactionType = requestBody.getString("type"); + String vendorGameCode = requestBody.getString("provider_code"); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + String betDateTimeStr = ""; + betDateTimeStr = sdf.format(System.currentTimeMillis()); + log.info(LOG_PREFIX+ "========== betDateTimeStr::" + betDateTimeStr); + + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "pracp"); + sParam.put("vendorGameCode", vendorGameCode); + log.info(LOG_PREFIX + "getSiteVendorInfo::"+sParam.toString()); + HashMap siteVendorInfo = siteService.getSiteVendorInfo(sParam); + if(siteVendorInfo == null) { + log.error(LOG_PREFIX+ "존재하지 않는 회원입니다"); + resData.put("status", "FAIL"); + resultObj.put("balance", 0); + resData.put("result", resultObj); + resEntity = new ResponseEntity(resData, httpStatus); + return resEntity; + } + + if(transactionType.equals("Bet")) { + log.info(LOG_PREFIX+ "callBet() ================= type: "+transactionType); + int amount = Math.abs(requestBody.getInt("amount")); + resData = callBet(LOG_PREFIX, siteIdx, memberId, requestBody, betDateTimeStr, siteVendorInfo, amount); + + } else if(transactionType.equals("Win")) { + log.info(LOG_PREFIX+ "callWin() ================= type: "+transactionType); + int amount = Math.abs(requestBody.getInt("amount")); + resData = callWin(LOG_PREFIX, siteIdx, memberId, requestBody, betDateTimeStr, siteVendorInfo, amount); + + } else if(transactionType.equals("Cancel")) { + log.info(LOG_PREFIX+ "callCancel() ================= type: "+transactionType); + int amount = 0; + if(requestBody.has("amount")) { + amount = requestBody.getInt("amount"); + } + resData = callCancel(LOG_PREFIX, siteIdx, memberId, requestBody, betDateTimeStr, siteVendorInfo, amount); + + } else if(transactionType.equals("Promo")) { + log.info(LOG_PREFIX+ "callPromo() ================= type: "+transactionType); + int amount = requestBody.getInt("amount"); + resData = callPromo(LOG_PREFIX, siteIdx, memberId, requestBody, betDateTimeStr, siteVendorInfo, amount); + + } else { + log.error(LOG_PREFIX+ "unknown_transaction_type"); + resData.put("status", "FAIL"); + resultObj.put("balance", 0); + resData.put("result", resultObj); + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + log.error(LOG_PREFIX+ "[ResourceAccessException]"+rae.getMessage()); + + resData.put("status", "FAIL"); + resultObj.put("balance", 0); + resData.put("result", resultObj); + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.getMessage()); + + resData.put("status", "FAIL"); + resultObj.put("balance", 0); + resData.put("result", resultObj); + } + + log.info(LOG_PREFIX+ "Response: "+resData.toString()); + resEntity = new ResponseEntity(resData, httpStatus); + + return resEntity; + } + + + private JSONObject callBet(String LOG_PREFIX, long siteIdx, String memberId, JSONObject requestBody, + String betDateTimeStr, HashMap siteVendorInfo, int amount) { + JSONObject response = new JSONObject(); + JSONObject resultObj = new JSONObject(); + + try { + // ##--isTransfer 처리-## + final String IS_TRANSFER = siteVendorInfo.get("isTransfer").toString(); + + String vendorTranKey = requestBody.getString("round_id"); + String tranId = requestBody.getString("uuid"); + String betId = requestBody.getString("refer_uuid"); + if(betId == null || "".equals(betId)) betId = tranId; + + String gameType = requestBody.getString("game_type").replaceAll(" ", "").toLowerCase(); + String gameId = requestBody.getString("game_code").replaceAll(" ", "").toLowerCase(); + + String banGameType = siteVendorInfo.get("banGameType").toString().replaceAll(" ", "").toLowerCase(); + String banGameId = siteVendorInfo.get("banGameId").toString().replaceAll(" ", "").toLowerCase(); + + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + Long vendorIdx = Long.parseLong(siteVendorInfo.get("vendorIdx").toString()); + String gameName = requestBody.getString("game_name"); + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + LOG_PREFIX = LOG_PREFIX + "callBet:::"; + + if(!"".equals(gameType) && !"".equals(banGameType) && banGameType.contains(gameType+"|")) { + log.error(LOG_PREFIX+ "Ban Game Type : " + gameType); + response.put("status", "FAIL"); + resultObj.put("balance", 0); + response.put("result", resultObj); + return response; + } + + if(!"".equals(gameId) && !"".equals(banGameId) && banGameId.contains(gameId+"|")) { + log.error(LOG_PREFIX+ "Ban Game Id : " + banGameId); + response.put("status", "FAIL"); + resultObj.put("balance", 0); + response.put("result", resultObj); + return response; + } + + if(siteVendorInfo.get("lastInVendorIdx")==null || "0".equals(siteVendorInfo.get("lastInVendorIdx").toString())) { + HashMap memParam = new HashMap<>(); + memParam.put("siteIdx", siteIdx); + memParam.put("memberIdx", memberIdx); + memParam.put("lastInVendorIdx", Integer.parseInt(siteVendorInfo.get("vendorIdx").toString())); + int updResult = siteService.updMemLastVendorIdx(memParam); + } else { + int lastInVendorIdx = Integer.parseInt(siteVendorInfo.get("lastInVendorIdx").toString()); + if(lastInVendorIdx != vendorIdx) { + log.error(LOG_PREFIX+ "VendorIdx doesn't match"); + response.put("status", "FAIL"); + resultObj.put("balance", 0); + response.put("result", resultObj); + return response; + } + } + + long siteCredit = Long.parseLong(siteVendorInfo.get("credit").toString()); + // ##--isTransfer 처리-## + if(siteCredit < amount && IS_TRANSFER.equals("N")) { + log.error(LOG_PREFIX+ "NO_SITE_CREDIT"); + response.put("status", "FAIL"); + resultObj.put("balance", 0); + response.put("result", resultObj); + return response; + } + + // 최대 베팅 금액 처리 (userMaxBet 우선 적용) + long siteMaxBet = Long.parseLong(siteVendorInfo.get("siteMaxBet").toString()); + long userMaxBet = 0; + if(siteVendorInfo.get("userMaxBet") != null && !siteVendorInfo.get("userMaxBet").toString().isEmpty()) { + try { + userMaxBet = Long.parseLong(siteVendorInfo.get("userMaxBet").toString()); + } catch (NumberFormatException e) { + userMaxBet = 0; + } + } + + // 최종 maxBet 결정: userMaxBet이 0이면 siteMaxBet 사용, 0이 아니면 userMaxBet 사용 + long finalMaxBet = (userMaxBet > 0) ? userMaxBet : siteMaxBet; + log.info(LOG_PREFIX+ "MaxBet Info - siteMaxBet: " + siteMaxBet + ", userMaxBet: " + userMaxBet + ", finalMaxBet: " + finalMaxBet); + + if(finalMaxBet < amount) { + log.error(LOG_PREFIX+ "MAX_BET_AMOUNT_OVER"); + log.error(LOG_PREFIX+ "finalMaxBet : " + finalMaxBet +", amount : " + amount); + response.put("status", "FAIL"); + resultObj.put("balance", 0); + response.put("result", resultObj); + return response; + } + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("Y")) { + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(tranId); + if(cntTr > 0) { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + response.put("status", "BET_ALREADY_EXIST"); + resultObj.put("balance", balance); + response.put("result", resultObj); + log.error(LOG_PREFIX+ "중복요청::Response::" + response.toString()); + return response; + } + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", "SLOT"); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "pracp"); + tranParam.put("vendorTranKey", vendorTranKey); + tranParam.put("gameType", gameType); + tranParam.put("gameId", gameId); + tranParam.put("gameIdx", gameName); + tranParam.put("tranType", "debit"); + tranParam.put("depositAmt", amount); + tranParam.put("creditAmt", "0"); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + + org.codehaus.jettison.json.JSONObject callBackObj = new org.codehaus.jettison.json.JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "pracp"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", gameName); + callBackObj.put("gameId", gameId); + callBackObj.put("gameType", gameType); + callBackObj.put("tranType", "debit"); + callBackObj.put("debit", amount); + callBackObj.put("credit", 0); + callBackObj.put("isCancel", 0); + callBackObj.put("isBonus", 0); + callBackObj.put("isData", "N"); + callBackObj.put("requestAt", betDateTimeStr); + log.info(LOG_PREFIX + "SEND_BET request body: " + callBackObj.toString()); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("N")) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + log.info(LOG_PREFIX + "-----INSERT_BET_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_BET_END-----"); + + org.codehaus.jettison.json.JSONObject resData = callBackService.changeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + log.info(LOG_PREFIX + "SEND_BET status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_BET response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + response.put("status", "OK"); + resultObj.put("balance", balance); + response.put("result", resultObj); + } else if(resData.getLong("result_code") == 98) { + int balance = resData.getInt("balance"); + response.put("status", "BET_ALREADY_EXIST"); + resultObj.put("balance", balance); + response.put("result", resultObj); + } else if(resData.getLong("result_code") == 80) { + int balance = resData.getInt("balance"); + response.put("status", "INSUFFICIENT_FUNDS"); + resultObj.put("balance", balance); + response.put("result", resultObj); + } else { + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + log.error(LOG_PREFIX+ msg); + response.put("status", "FAIL"); + resultObj.put("balance", 0); + response.put("result", resultObj); + } + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + int afBalance = balance - amount; + + if(balance < amount) { + response.put("status", "INSUFFICIENT_FUNDS"); + resultObj.put("balance", balance); + response.put("result", resultObj); + log.error(LOG_PREFIX+ "잔액부족::Response::" + response.toString()); + return response; + } + + log.info(LOG_PREFIX + "-----INSERT_BET_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_BET_END-----"); + + tranParam.put("balance", afBalance); + tranParam.put("preBalance", balance); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + response.put("status", "OK"); + resultObj.put("balance", afBalance); + response.put("result", resultObj); + + if(siteVendorInfo.get("siteCbUrl") != null && !"".equals(siteVendorInfo.get("siteCbUrl").toString())) { + callBackObj.put("balance", afBalance); + asyncCallBackService.asyncChangeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + response.put("status", "FAIL"); + resultObj.put("balance", 0); + response.put("result", resultObj); + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + response.put("status", "FAIL"); + resultObj.put("balance", 0); + response.put("result", resultObj); + } + + return response; + } + + private JSONObject callWin(String LOG_PREFIX, long siteIdx, String memberId, JSONObject requestBody, + String betDateTimeStr, HashMap siteVendorInfo, int amount) { + JSONObject response = new JSONObject(); + JSONObject resultObj = new JSONObject(); + + try { + // ##--isTransfer 처리-## + final String IS_TRANSFER = siteVendorInfo.get("isTransfer").toString(); + + String vendorTranKey = requestBody.getString("round_id"); + String tranId = requestBody.getString("uuid"); + String betId = requestBody.getString("refer_uuid"); + if(betId == null || "".equals(betId)) betId = tranId; + + String gameType = requestBody.getString("game_type").replaceAll(" ", "").toLowerCase(); + String gameId = requestBody.getString("game_code").replaceAll(" ", "").toLowerCase(); + + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + Long vendorIdx = Long.parseLong(siteVendorInfo.get("vendorIdx").toString()); + String gameName = requestBody.getString("game_name"); + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + LOG_PREFIX = LOG_PREFIX + "callWin:::"; + + int siteMaxWin = Integer.parseInt(siteVendorInfo.get("siteMaxWin").toString()); + int overCreditAmt = 0; + if(siteMaxWin < amount && siteMaxWin != 0) { + log.error(LOG_PREFIX+ "MAX_WIN_AMOUNT_OVER"); + log.error(LOG_PREFIX+ "siteMaxWin : " + siteMaxWin +", amount : " + amount); + overCreditAmt = amount - siteMaxWin; + amount = siteMaxWin; + log.error(LOG_PREFIX+ "Change amount : " + amount +", overCreditAmt : " + overCreditAmt); + } + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("Y")) { + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(tranId); + if(cntTr > 0) { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + response.put("status", "BET_ALREADY_EXIST"); + resultObj.put("balance", balance); + response.put("result", resultObj); + log.error(LOG_PREFIX+ "중복요청::Response::" + response.toString()); + return response; + } + + // 베팅 체크 + int cntBet = siteService.getBetIdCheck2(betId); + if(cntBet == 0) { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + response.put("status", "BET_DOES_NOT_EXIST"); + resultObj.put("balance", balance); + response.put("result", resultObj); + log.error(LOG_PREFIX+ "NOT_FOUND_REF_DATA::Response::" + response.toString()); + return response; + } + + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", "SLOT"); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "pracp"); + tranParam.put("vendorTranKey", vendorTranKey); + tranParam.put("gameType", gameType); + tranParam.put("gameId", gameId); + tranParam.put("gameIdx", gameName); + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + tranParam.put("overCreditAmt", overCreditAmt); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + + org.codehaus.jettison.json.JSONObject callBackObj = new org.codehaus.jettison.json.JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "pracp"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", gameName); + callBackObj.put("gameId", gameId); + callBackObj.put("gameType", gameType); + callBackObj.put("tranType", "credit"); + callBackObj.put("debit", 0); + callBackObj.put("credit", amount); + callBackObj.put("isCancel", 0); + callBackObj.put("isBonus", 0); + callBackObj.put("isData", "N"); + callBackObj.put("requestAt", betDateTimeStr); + log.info(LOG_PREFIX + "SEND_RESULT request body: " + callBackObj.toString()); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("N")) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + log.info(LOG_PREFIX + "-----INSERT_RESULT_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_RESULT_END-----"); + + org.codehaus.jettison.json.JSONObject resData = callBackService.changeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + log.info(LOG_PREFIX + "SEND_RESULT status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_RESULT response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + response.put("status", "OK"); + resultObj.put("balance", balance); + response.put("result", resultObj); + } else if(resData.getLong("result_code") == 98) { + int balance = resData.getInt("balance"); + response.put("status", "BET_ALREADY_SETTLED"); + resultObj.put("balance", balance); + response.put("result", resultObj); + } else if(resData.getLong("result_code") == 99) { + int balance = resData.getInt("balance"); + response.put("status", "BET_DOES_NOT_EXIST"); + resultObj.put("balance", balance); + response.put("result", resultObj); + } else { + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + log.error(LOG_PREFIX+ msg); + response.put("status", "FAIL"); + resultObj.put("balance", 0); + response.put("result", resultObj); + } + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + int afBalance = balance + amount; + + log.info(LOG_PREFIX + "-----INSERT_RESULT_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_RESULT_END-----"); + + tranParam.put("balance", afBalance); + tranParam.put("preBalance", balance); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + response.put("status", "OK"); + resultObj.put("balance", afBalance); + response.put("result", resultObj); + + if(siteVendorInfo.get("siteCbUrl") != null && !"".equals(siteVendorInfo.get("siteCbUrl").toString())) { + callBackObj.put("balance", afBalance); + asyncCallBackService.asyncChangeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + response.put("status", "FAIL"); + resultObj.put("balance", 0); + response.put("result", resultObj); + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + response.put("status", "FAIL"); + resultObj.put("balance", 0); + response.put("result", resultObj); + } + + return response; + } + + private JSONObject callCancel(String LOG_PREFIX, long siteIdx, String memberId, + JSONObject requestBody, String betDateTimeStr, HashMap siteVendorInfo, int amount) { + JSONObject response = new JSONObject(); + JSONObject resultObj = new JSONObject(); + + try { + // ##--isTransfer 처리-## + final String IS_TRANSFER = siteVendorInfo.get("isTransfer").toString(); + + String vendorTranKey = requestBody.getString("round_id"); + String tranId = requestBody.getString("uuid"); + + String referUuid = requestBody.getString("refer_uuid"); + // 참조되는 트랜잭션 찾기 + HashMap refInfo = siteService.getRefBetInfoByTranId(referUuid); + if(refInfo == null) { + response.put("status", "BET_DOES_NOT_EXIST"); + resultObj.put("balance", 0); + response.put("result", resultObj); + return response; + } + + String betId = refInfo.get("refId").toString(); + String referTranType = refInfo.get("tranType").toString(); + + String gameType = requestBody.getString("game_type").replaceAll(" ", "").toLowerCase(); + String gameId = requestBody.getString("game_code").replaceAll(" ", "").toLowerCase(); + + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + Long vendorIdx = Long.parseLong(siteVendorInfo.get("vendorIdx").toString()); + String gameName = requestBody.getString("game_name"); + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + LOG_PREFIX = LOG_PREFIX + "callCancel:::"; + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("Y")) { + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(tranId); + if(cntTr > 0) { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + response.put("status", "BET_ALREADY_EXIST"); + resultObj.put("balance", balance); + response.put("result", resultObj); + log.error(LOG_PREFIX+ "중복요청::Response::" + response.toString()); + return response; + } + + // 베팅 체크 + int cntBet = siteService.getBetIdCheck2(betId); + if(cntBet == 0) { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + response.put("status", "BET_DOES_NOT_EXIST"); + resultObj.put("balance", balance); + response.put("result", resultObj); + log.error(LOG_PREFIX+ "NOT_FOUND_REF_DATA::Response::" + response.toString()); + return response; + } + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", "SLOT"); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "pracp"); + tranParam.put("vendorTranKey", vendorTranKey); + tranParam.put("gameType", gameType); + tranParam.put("gameId", gameId); + tranParam.put("gameIdx", gameName); + if(referTranType.equals("debit")) { + // 배팅 취소 + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", Math.abs(amount)); + } else { + // 당첨 취소 + tranParam.put("tranType", "debit"); + tranParam.put("depositAmt", Math.abs(amount)); + tranParam.put("creditAmt", "0"); + } + tranParam.put("isCancel", "Y"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + + org.codehaus.jettison.json.JSONObject callBackObj = new org.codehaus.jettison.json.JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "pracp"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", gameName); + callBackObj.put("gameId", gameId); + callBackObj.put("gameType", gameType); + if(referTranType.equals("debit")) { + // 배팅 취소 + callBackObj.put("tranType", "credit"); + callBackObj.put("debit", 0); + callBackObj.put("credit", Math.abs(amount)); + callBackObj.put("isCancel", 1); + } else { + // 당첨 취소 + callBackObj.put("tranType", "adjust"); + callBackObj.put("debit", Math.abs(amount)); + callBackObj.put("credit", 0); + callBackObj.put("isCancel", 0); + } + callBackObj.put("isBonus", 0); + callBackObj.put("isData", "N"); + callBackObj.put("requestAt", betDateTimeStr); + log.info(LOG_PREFIX + "SEND_CANCEL request body: " + callBackObj.toString()); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("N")) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + log.info(LOG_PREFIX + "-----INSERT_CANCEL_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_CANCEL_END-----"); + + org.codehaus.jettison.json.JSONObject resData = callBackService.changeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + log.info(LOG_PREFIX + "SEND_CANCEL status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_CANCEL response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + response.put("status", "OK"); + resultObj.put("balance", balance); + response.put("result", resultObj); + } else if(resData.getLong("result_code") == 98) { + int balance = resData.getInt("balance"); + response.put("status", "BET_ALREADY_SETTLED"); + resultObj.put("balance", balance); + response.put("result", resultObj); + } else if(resData.getLong("result_code") == 99) { + int balance = resData.getInt("balance"); + response.put("status", "BET_DOES_NOT_EXIST"); + resultObj.put("balance", balance); + response.put("result", resultObj); + } else { + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + log.error(LOG_PREFIX+ msg); + response.put("status", "FAIL"); + resultObj.put("balance", 0); + response.put("result", resultObj); + } + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + int afBalance = 0; + if(referTranType.equals("debit")) { + // 배팅 취소 + afBalance = balance + Math.abs(amount); + } else { + // 당첨 취소 + afBalance = balance - Math.abs(amount); + } + + log.info(LOG_PREFIX + "-----INSERT_CANCEL_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_CANCEL_END-----"); + + tranParam.put("balance", afBalance); + tranParam.put("preBalance", balance); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + response.put("status", "OK"); + resultObj.put("balance", afBalance); + response.put("result", resultObj); + + if(siteVendorInfo.get("siteCbUrl") != null && !"".equals(siteVendorInfo.get("siteCbUrl").toString())) { + callBackObj.put("balance", afBalance); + asyncCallBackService.asyncChangeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + response.put("status", "FAIL"); + resultObj.put("balance", 0); + response.put("result", resultObj); + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + response.put("status", "FAIL"); + resultObj.put("balance", 0); + response.put("result", resultObj); + } + + return response; + } + + private JSONObject callPromo(String LOG_PREFIX, long siteIdx, String memberId, + JSONObject requestBody, String betDateTimeStr, HashMap siteVendorInfo, int amount) { + JSONObject response = new JSONObject(); + JSONObject resultObj = new JSONObject(); + + try { + // ##--isTransfer 처리-## + final String IS_TRANSFER = siteVendorInfo.get("isTransfer").toString(); + + String vendorTranKey = requestBody.getString("round_id"); + String tranId = requestBody.getString("uuid"); + String betId = requestBody.getString("refer_uuid"); + if(betId == null || "".equals(betId)) betId = tranId; + + String gameType = requestBody.getString("game_type").replaceAll(" ", "").toLowerCase(); + String gameId = requestBody.getString("game_code").replaceAll(" ", "").toLowerCase(); + + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + Long vendorIdx = Long.parseLong(siteVendorInfo.get("vendorIdx").toString()); + String gameName = requestBody.getString("game_name"); + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + LOG_PREFIX = LOG_PREFIX + "callPromo:::"; + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("Y")) { + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(tranId); + if(cntTr > 0) { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + response.put("status", "BET_ALREADY_EXIST"); + resultObj.put("balance", balance); + response.put("result", resultObj); + log.error(LOG_PREFIX+ "중복요청::Response::" + response.toString()); + return response; + } + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", "SLOT"); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "pracp"); + tranParam.put("vendorTranKey", vendorTranKey); + tranParam.put("gameType", gameType); + tranParam.put("gameId", gameId); + tranParam.put("gameIdx", gameName); + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + + org.codehaus.jettison.json.JSONObject callBackObj = new org.codehaus.jettison.json.JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "pracp"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", gameName); + callBackObj.put("gameId", gameId); + callBackObj.put("gameType", gameType); + callBackObj.put("tranType", "credit"); + callBackObj.put("debit", 0); + callBackObj.put("credit", amount); + callBackObj.put("isCancel", 0); + callBackObj.put("isBonus", 1); + callBackObj.put("isData", "N"); + callBackObj.put("requestAt", betDateTimeStr); + log.info(LOG_PREFIX + "SEND_PROMO request body: " + callBackObj.toString()); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("N")) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + log.info(LOG_PREFIX + "-----INSERT_PROMO_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_PROMO_END-----"); + + org.codehaus.jettison.json.JSONObject resData = callBackService.changeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + log.info(LOG_PREFIX + "SEND_PROMO status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_PROMO response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + response.put("status", "OK"); + resultObj.put("balance", balance); + response.put("result", resultObj); + } else if(resData.getLong("result_code") == 98) { + int balance = resData.getInt("balance"); + response.put("status", "BET_ALREADY_SETTLED"); + resultObj.put("balance", balance); + response.put("result", resultObj); + } else if(resData.getLong("result_code") == 99) { + int balance = resData.getInt("balance"); + response.put("status", "BET_DOES_NOT_EXIST"); + resultObj.put("balance", balance); + response.put("result", resultObj); + } else { + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + log.error(LOG_PREFIX+ msg); + response.put("status", "FAIL"); + resultObj.put("balance", 0); + response.put("result", resultObj); + } + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + int afBalance = balance + amount; + + log.info(LOG_PREFIX + "-----INSERT_PROMO_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_PROMO_END-----"); + + tranParam.put("balance", afBalance); + tranParam.put("preBalance", balance); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + response.put("status", "OK"); + resultObj.put("balance", afBalance); + response.put("result", resultObj); + + if(siteVendorInfo.get("siteCbUrl") != null && !"".equals(siteVendorInfo.get("siteCbUrl").toString())) { + callBackObj.put("balance", afBalance); + asyncCallBackService.asyncChangeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + response.put("status", "FAIL"); + resultObj.put("balance", 0); + response.put("result", resultObj); + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + response.put("status", "FAIL"); + resultObj.put("balance", 0); + response.put("result", resultObj); + } + + return response; + } + + private static String decryptAES256(String encryptedData, String keyBase64, String ivBase64) { + try { + // JS의 encryptedData = encryptedData.split(" ").join("+")와 동일 + encryptedData = encryptedData.replace(" ", "+"); + + System.out.println("[DECRYPT] Starting decryption process"); + System.out.println("[DECRYPT] Input data:"); + System.out.println("encryptedData = " + encryptedData); + System.out.println("keyBase64 = " + keyBase64); + System.out.println("ivBase64 = " + ivBase64); + + // Base64 → byte[] + byte[] keyBytes = Base64.getDecoder().decode(keyBase64); + byte[] ivBytes = Base64.getDecoder().decode(ivBase64); + byte[] encryptedBytes = Base64.getDecoder().decode(encryptedData); + + System.out.println("[DECRYPT] Key and IV buffers created successfully"); + + // Key, IV 설정 + SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES"); + IvParameterSpec ivSpec = new IvParameterSpec(ivBytes); + + // Cipher 생성 (AES-256-CBC + PKCS5Padding) + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec); + + // 복호화 + byte[] decryptedBytes = cipher.doFinal(encryptedBytes); + String decrypted = new String(decryptedBytes, StandardCharsets.UTF_8); + + System.out.println("[DECRYPT] Decryption successful"); + System.out.println("[DECRYPT] Decrypted result: " + + (decrypted.length() > 10 ? decrypted.substring(0, 10) + "..." : decrypted)); + + return decrypted; + + } catch (Exception e) { + System.err.println("[DECRYPT] Decryption failed with error: " + e.getMessage()); + return ""; + } + } +} diff --git a/src/main/java/com/bb/front/CallBackPragmaticController.java b/src/main/java/com/bb/front/CallBackPragmaticController.java new file mode 100644 index 0000000..b5b59b2 --- /dev/null +++ b/src/main/java/com/bb/front/CallBackPragmaticController.java @@ -0,0 +1,1731 @@ +package com.bb.front; + +import java.net.URLDecoder; +import java.text.DecimalFormat; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +import org.codehaus.jettison.json.JSONException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.reactive.function.client.WebClient; + +import com.bb.jwt.JwtManager; +import com.bb.model.BetParam; +import com.bb.model.Member; +import com.bb.service.AsyncSiteService; +import com.bb.service.CallBackService; +import com.bb.service.SiteService; + +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import net.sf.json.JSONObject; + +@RestController +@Slf4j +@RequestMapping("/api/callback/pp/") +@RequiredArgsConstructor +@SecurityRequirement(name = "Authorization") +public class CallBackPragmaticController { + + @Autowired + private final JwtManager jwtManager; + + @Autowired + SiteService siteService; + + @Autowired + WebClient webClient; + + @Autowired + CallBackService callBackService; + + @Autowired + AsyncSiteService asyncCallBackService; + + @CrossOrigin + @PostMapping(value = "/Authenticate") + public @ResponseBody JSONObject authenticate(HttpServletRequest request, + @RequestBody(required = false) String parambody) throws Exception { + JSONObject resData = new JSONObject(); + String hash = URLDecoder.decode(request.getParameter("hash"), "UTF-8"); + String userId = URLDecoder.decode(request.getParameter("token"), "UTF-8"); + String providerId = URLDecoder.decode(request.getParameter("providerId"), "UTF-8"); + /* + * String ipAdress = URLDecoder.decode(request.getParameter("ipAdress"), + * "UTF-8"); String chosenBalance = + * URLDecoder.decode(request.getParameter("chosenBalance"), "UTF-8"); String + * lunchingType = URLDecoder.decode(request.getParameter("lunchingType"), + * "UTF-8"); String proviousToken = + * URLDecoder.decode(request.getParameter("proviousToken"), "UTF-8"); + */ + + try { + //String userId = token; + HashMap sParam = new HashMap(); + sParam.put("siteIdx", Integer.parseInt(userId.substring(0, 3), 16)); + sParam.put("memberId", userId.substring(3, userId.length())); + String memberId = userId.substring(3, userId.length()); + final String LOG_PREFIX = "#-CB::PP::"+memberId+"::authenticate:::"; + log.info(LOG_PREFIX+ "userId : " + userId); + + HashMap siteApiInfo = siteService.getSiteApiInfo(sParam); + log.info(LOG_PREFIX+ "siteApiInfo {}", siteApiInfo); + final String IS_TRANSFER = siteApiInfo.get("isTransfer").toString(); + + + double balance = 0L; + // ##--isTransfer 처리-## + if (IS_TRANSFER.equals("Y")) { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteApiInfo.get("siteIdx")); + balanceMap.put("memberId", memberId); + balance = Double.parseDouble("" + siteService.getUserBalance(balanceMap)); + + if(siteApiInfo.get("siteCbUrl") != null && !"".equals(siteApiInfo.get("siteCbUrl").toString())) { + org.codehaus.jettison.json.JSONObject member = new org.codehaus.jettison.json.JSONObject(); + member.put("userId", memberId); + member.put("balance", balance); + asyncCallBackService.asyncBalance(LOG_PREFIX, siteApiInfo, member); + } + + } else { + DecimalFormat formatter = new DecimalFormat("0.##"); + + org.codehaus.jettison.json.JSONObject memberParam = new org.codehaus.jettison.json.JSONObject(); + memberParam.put("userId", memberId); + org.codehaus.jettison.json.JSONObject cbResData = callBackService.getBalance(siteApiInfo, memberParam); + balance = cbResData.getDouble("balance"); + } + + double bonus = 0.00; + resData.put("userId", siteApiInfo.get("siteIdxHex").toString() + memberId); + resData.put("currency", "VND"); + resData.put("cash", balance); + resData.put("bonus", bonus); + resData.put("error", 0); + resData.put("description", "Success"); + + } catch (Exception e) { + log.info(e.toString()); + resData.put("error", 2); + resData.put("description", "Player not found or logged out."); + + } + return resData; + } + + @CrossOrigin + @PostMapping(value = "/Balance") + public @ResponseBody JSONObject balance(HttpServletRequest request, @RequestBody(required = false) String parambody) + throws Exception { + JSONObject resData = new JSONObject(); + String hash = URLDecoder.decode(request.getParameter("hash"), "UTF-8"); + // String token = URLDecoder.decode(request.getParameter("userId"), "UTF-8"); + String userId = URLDecoder.decode(request.getParameter("userId"), "UTF-8"); + String providerId = URLDecoder.decode(request.getParameter("providerId"), "UTF-8"); + /* + * String ipAdress = URLDecoder.decode(request.getParameter("ipAdress"), + * "UTF-8"); String chosenBalance = + * URLDecoder.decode(request.getParameter("chosenBalance"), "UTF-8"); String + * lunchingType = URLDecoder.decode(request.getParameter("lunchingType"), + * "UTF-8"); String proviousToken = + * URLDecoder.decode(request.getParameter("proviousToken"), "UTF-8"); + */ + + try { + HashMap sParam = new HashMap(); + sParam.put("siteIdx", Integer.parseInt(userId.substring(0, 3), 16)); + sParam.put("memberId", userId.substring(3, userId.length())); + String memberId = userId.substring(3, userId.length()); + final String LOG_PREFIX = "#-CB::PP::"+memberId+"::balance:::"; + + HashMap siteApiInfo = siteService.getSiteApiInfo(sParam); + String siteId = siteApiInfo.get("siteId").toString(); + log.info(LOG_PREFIX+ "# sparam() : " + siteApiInfo.toString()); + + if (siteApiInfo == null) { + resData.put("error", 2); + resData.put("description", "Player not found or logged out."); + return resData; + } + final String IS_TRANSFER = siteApiInfo.get("isTransfer").toString(); + double balance = 0L; + // ##--isTransfer 처리-## + if (IS_TRANSFER.equals("Y")) { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteApiInfo.get("siteIdx")); + balanceMap.put("memberId", memberId); + balance = Double.parseDouble("" + siteService.getUserBalance(balanceMap)); + + if(siteApiInfo.get("siteCbUrl") != null && !"".equals(siteApiInfo.get("siteCbUrl").toString())) { + org.codehaus.jettison.json.JSONObject member = new org.codehaus.jettison.json.JSONObject(); + member.put("userId", memberId); + member.put("balance", balance); + asyncCallBackService.asyncBalance(LOG_PREFIX, siteApiInfo, member); + } + + } else { + + org.codehaus.jettison.json.JSONObject memberParam = new org.codehaus.jettison.json.JSONObject(); + memberParam.put("userId", memberId); + org.codehaus.jettison.json.JSONObject cbResData = callBackService.getBalance(siteApiInfo, memberParam); + balance = cbResData.getDouble("balance"); + } + + double bonus = 0.00; + + resData.put("currency", "VND"); + resData.put("cash", balance); + resData.put("bonus", bonus); + resData.put("error", 0); + resData.put("description", "Success"); + + } catch (Exception e) { + resData.put("error", 120); + resData.put("description", "Internal Server Error(no-retry)"); + + + } + return resData; + } + + @CrossOrigin + @PostMapping(value = "/Bet") + public @ResponseBody JSONObject bet(HttpServletRequest request, @RequestBody(required = false) String parambody) + throws Exception { + JSONObject resData = new JSONObject(); + String hash = URLDecoder.decode(request.getParameter("hash"), "UTF-8"); + String userId = URLDecoder.decode(request.getParameter("userId"), "UTF-8"); + String gameId = URLDecoder.decode(request.getParameter("gameId"), "UTF-8"); + String roundId = URLDecoder.decode(request.getParameter("roundId"), "UTF-8"); + String amountStr = URLDecoder.decode(request.getParameter("amount"), "UTF-8"); + String reference = URLDecoder.decode(request.getParameter("reference"), "UTF-8"); + String providerId = URLDecoder.decode(request.getParameter("providerId"), "UTF-8"); + String timestamp = URLDecoder.decode(request.getParameter("timestamp"), "UTF-8"); + String roundDetails = URLDecoder.decode(request.getParameter("roundDetails"), "UTF-8"); + + try { + HashMap sParam = new HashMap(); + + sParam.put("siteIdx", Integer.parseInt(userId.substring(0, 3), 16)); + sParam.put("memberId", userId.substring(3, userId.length())); + String memberId = userId.substring(3, userId.length()); + final String LOG_PREFIX = "#-CB::PP::"+memberId+"::bet:::"; + log.info(LOG_PREFIX+ "# sparam () : " + sParam.toString()); + + HashMap siteApiInfo = siteService.getSiteApiInfo(sParam); + String siteId = siteApiInfo.get("siteId").toString(); + log.info(LOG_PREFIX+ "# sparam siteApiInfo () : " + siteApiInfo.toString()); + + if (siteApiInfo == null) { + log.info(LOG_PREFIX+ "# sparam BET 0() : no setting"); + resData.put("error", 2); + resData.put("description", "Player not found or logged out."); + return resData; + } + + Map authParam = new HashMap(); + authParam.put("memberId", memberId); + authParam.put("siteId", siteId); + authParam.put("siteIdx", siteApiInfo.get("siteIdx")); + + // ##--isTransfer 처리-## + log.info(LOG_PREFIX+ "# sparam authParam {} ", authParam.toString()); + Member member = siteService.getMemberByToken(authParam); + + if (member == null) { + log.info(LOG_PREFIX+ "# sparam BET1 () : no member"); + resData.put("error", 2); + resData.put("description", "Player not found or logged out."); + return resData; + } + + long targetSiteCredit = siteService.getSiteCredit(siteApiInfo.get("siteId").toString()); + log.info(LOG_PREFIX+ "# sparam targetSiteCredit {} ", targetSiteCredit); + + double amount = Double.parseDouble(amountStr); + log.info(LOG_PREFIX+ "# sparam amount {} ", amount); + + + final String IS_TRANSFER = siteApiInfo.get("isTransfer").toString(); + + if ((targetSiteCredit < amount || targetSiteCredit < 0) && IS_TRANSFER.equals("N") ) { + log.info(LOG_PREFIX+ "# sparam BET2 () : no cash"); + resData.put("error", 1); + resData.put("description", "Insufficient balance"); + return resData; + } + + int vendorIdx = 17; + String vendorKey = "S02"; + String vendorCetegory = "SLOT"; + if (!(gameId.startsWith("vs") || gameId.startsWith("cs"))) { + vendorIdx = 2; + vendorKey = "C02"; + vendorCetegory = "CASINO"; + } + + sParam.put("vendorIdx", vendorIdx); + long maxBet = siteService.getSiteMaxBet(sParam); + + // userMaxBet 조회 (userMaxBet 우선 적용) + long userMaxBet = 0; + Long userMaxBetObj = siteService.getUserMaxBet(sParam); + if(userMaxBetObj != null) { + userMaxBet = userMaxBetObj; + } + + // 최종 maxBet 결정: userMaxBet이 0이면 siteMaxBet 사용, 0이 아니면 userMaxBet 사용 + long finalMaxBet = (userMaxBet > 0) ? userMaxBet : maxBet; + log.info(LOG_PREFIX+ "MaxBet Info - siteMaxBet: " + maxBet + ", userMaxBet: " + userMaxBet + ", finalMaxBet: " + finalMaxBet); + + if (amount > finalMaxBet) { + log.info(LOG_PREFIX + "# sparam finalMaxBet {} ", finalMaxBet); + log.info(LOG_PREFIX + "# sparam BET3 () : max bet limit"); + resData.put("error", 310); + resData.put("description", "bet limits"); + + return resData; + } + + HashMap tranParam = new HashMap(); + + String refId = siteId + roundId; + + log.info(LOG_PREFIX+ "# sparam refId {}", siteId + roundId); + + tranParam.put("tranId", siteId + reference); + tranParam.put("refId", refId); + tranParam.put("siteIdx", siteApiInfo.get("siteIdx")); + tranParam.put("siteId", siteId); + tranParam.put("completed", true); + tranParam.put("memberIdx", member.getMemberIdx()); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "pragmatic"); + tranParam.put("vendorTranKey", reference); + tranParam.put("gameType", "slot"); + tranParam.put("gameId", gameId); + tranParam.put("gameIdx", gameId); + tranParam.put("tranType", "debit"); + tranParam.put("depositAmt", amount); + tranParam.put("creditAmt", "0"); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", "dfngtnslt_est88"); + + tranParam.put("isTransfer", IS_TRANSFER); + double balance = 0L; + + org.codehaus.jettison.json.JSONObject debit = new org.codehaus.jettison.json.JSONObject(); + double fakeAmount = amount;// *100; + debit.put("betId", refId); + debit.put("tranId", siteId + reference); + + debit.put("userId", member.getMemberId()); + debit.put("vendorIdx", vendorIdx); + debit.put("vendorKey", vendorKey); + debit.put("vendor", "pragmatic"); + debit.put("gameIdx", 1); + debit.put("gameKey", gameId); + debit.put("gameType", "slot"); + debit.put("gameId", gameId); + debit.put("tranType", "debit"); + debit.put("debit", fakeAmount); + debit.put("credit", 0); + debit.put("isCancel", 0); + debit.put("isBonus", 0); + debit.put("decYn", "Y"); + + if (IS_TRANSFER.equals("Y")) { + + + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(siteId + reference); + + + try { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteApiInfo.get("siteIdx")); + balanceMap.put("memberId", memberId); + balance = Double.parseDouble("" + siteService.getUserBalance(balanceMap)); + + if (balance < amount) { + resData.put("error", 1); + resData.put("description","Insufficient balance"); + return resData; + } + + + if (cntTr == 0) { + siteService.commonBetinsert(tranParam); + } + double afBalance = balance - amount; + log.info(LOG_PREFIX+ "siteService.updateCbApi(tranParam)"); + tranParam.put("balance", (double)afBalance); + tranParam.put("preBalance", (double)balance); + if (cntTr == 0) { + int res = siteService.updateCbApi(tranParam); + } + resData.put("transactionId", reference); + resData.put("currency", "VND"); + if (cntTr == 0) { + resData.put("cash", afBalance); + }else { + resData.put("cash", balance); + } + resData.put("bonus", 0); + resData.put("usedPromo", 0); + resData.put("error", 0); + resData.put("description", "Success"); + + if(siteApiInfo.get("siteCbUrl") != null && !"".equals(siteApiInfo.get("siteCbUrl").toString())) { + debit.put("balance", afBalance); + if(vendorCetegory.equals("SLOT")) { + asyncCallBackService.asyncChangeBalanceSlot("PRAGMATIC BET - ", siteApiInfo, debit); + } else { + asyncCallBackService.asyncChangeBalance("PRAGMATIC BET - ", siteApiInfo, debit); + } + } + + } catch (Exception e) { + resData.put("error", 120); + resData.put("description", "Internal Server Error(no-retry)"); + + + + + return resData; + } + + } else { + + siteService.commonBetinsert(tranParam); + + org.codehaus.jettison.json.JSONObject cbResData = new org.codehaus.jettison.json.JSONObject(); + + if (vendorCetegory.equals("SLOT")) { + cbResData = callBackService.changeBalanceSlot("PRAGMATIC BET - ", siteApiInfo, debit); + } else { + cbResData = callBackService.changeBalance("PRAGMATIC BET - ", siteApiInfo, debit); + } + + log.info(LOG_PREFIX+ "cbResData {}", cbResData.toString()); + + if (cbResData.getLong("result_code") == 0 || cbResData.getLong("result_code") == 98) { + log.info(LOG_PREFIX+ "siteService.updateCbApi(tranParam)"); + tranParam.put("balance", Double.parseDouble(cbResData.getString("balance"))); + if (cbResData.getLong("result_code") == 0 ) { + int res = siteService.updateCbApi(tranParam); + } + resData.put("transactionId", reference); + resData.put("currency", "VND"); + resData.put("cash", Double.parseDouble(cbResData.getString("balance"))); + resData.put("bonus", 0); + resData.put("usedPromo", 0); + resData.put("error", 0); + resData.put("description", "Success"); + } else if (cbResData.getLong("result_code") == 80) { + resData.put("error", 1); + resData.put("description", "Insufficient balance"); + return resData; + } else if (cbResData.getLong("result_code") == 81) { + resData.put("error", 310); + resData.put("description", "bet limits"); + return resData; + } else { + resData.put("error", 120); + resData.put("description", "Internal Server Error(no-retry)"); + } + } + + } catch (Exception e) { + String memberId = userId.substring(3, userId.length()); + final String LOG_PREFIX = "#-CB::PP::"+memberId+"::bet:::"; + log.error(LOG_PREFIX+ e.toString()); + resData.put("error", 120); + resData.put("description", "Internal Server Error(no-retry)"); + + } + return resData; + } + + @CrossOrigin + @PostMapping(value = "/Refund") + public @ResponseBody JSONObject refund(HttpServletRequest request, @RequestBody(required = false) String parambody) + throws Exception { + JSONObject resData = new JSONObject(); + String hash = URLDecoder.decode(request.getParameter("hash"), "UTF-8"); + String userId = URLDecoder.decode(request.getParameter("userId"), "UTF-8"); + String reference = URLDecoder.decode(request.getParameter("reference"), "UTF-8"); + String providerId = URLDecoder.decode(request.getParameter("providerId"), "UTF-8"); + + try { + HashMap sParam = new HashMap(); + + sParam.put("siteIdx", Integer.parseInt(userId.substring(0, 3), 16)); + sParam.put("memberId", userId.substring(3, userId.length())); + String memberId = userId.substring(3, userId.length()); + final String LOG_PREFIX = "#-CB::PP::"+memberId+"::refund:::"; + HashMap siteApiInfo = siteService.getSiteApiInfo(sParam); + String siteId = siteApiInfo.get("siteId").toString(); + log.info(LOG_PREFIX+ "# sparam() : " + siteApiInfo.toString()); + + if (siteApiInfo == null) { + + resData.put("error", 2); + resData.put("description", "Player not found or logged out."); + return resData; + } + + Map authParam = new HashMap(); + authParam.put("memberId", memberId); + authParam.put("siteId", siteId); + authParam.put("siteIdx", siteApiInfo.get("siteIdx")); + + // 회원정보 + Member member = siteService.getMemberByToken(authParam); + + if (member == null) { + resData.put("error", 2); + resData.put("description", "Player not found or logged out."); + return resData; + } + + // 베팅 정보 가져오기 없으면 에러 + HashMap betInfo = siteService.getBetInfoByTranId(reference); + + double amount = Double.parseDouble(betInfo.get("depositAmt").toString()); + + final String IS_TRANSFER = siteApiInfo.get("isTransfer").toString(); + + + int vendorIdx = Integer.parseInt(betInfo.get("vendorIdx").toString()); + String vendorKey = "S02"; + String vendorCetegory = "SLOT"; + if(vendorIdx!=17) { + vendorKey = "C02"; + vendorCetegory = "CASINO"; + } + + HashMap tranParam = new HashMap(); + + String refId = betInfo.get("refId").toString(); + + tranParam.put("tranId", betInfo.get("tranId").toString() + "#R"); + tranParam.put("refId", refId); + tranParam.put("siteIdx", siteApiInfo.get("siteIdx")); + tranParam.put("siteId", siteId); + tranParam.put("completed", true); + tranParam.put("memberIdx", member.getMemberIdx()); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", Integer.parseInt(betInfo.get("vendorIdx").toString())); + tranParam.put("vendorCode", "pragmatic"); + tranParam.put("vendorTranKey", reference); + tranParam.put("gameType", "slot"); + tranParam.put("gameId", betInfo.get("gameIdx").toString()); + tranParam.put("gameIdx", betInfo.get("gameIdx").toString()); + + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + tranParam.put("isCancel", "Y"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", "dfngtnslt_est88"); + + tranParam.put("isTransfer", IS_TRANSFER); + + + org.codehaus.jettison.json.JSONObject debit = new org.codehaus.jettison.json.JSONObject(); + double fakeAmount = amount;// *100; + debit.put("betId", refId); + debit.put("tranId", betInfo.get("tranId").toString() + "#R"); + + debit.put("userId", member.getMemberId()); + debit.put("vendorIdx", vendorIdx); + debit.put("vendorKey", vendorKey); + debit.put("vendor", "pragmatic"); + debit.put("gameIdx", 1); + debit.put("gameKey", betInfo.get("gameIdx").toString()); + debit.put("gameType", "slot"); + debit.put("gameId", betInfo.get("gameIdx").toString()); + debit.put("tranType", "credit"); + debit.put("debit", 0); + debit.put("credit", fakeAmount); + debit.put("isCancel", 1); + debit.put("isBonus", 0); + debit.put("decYn", "Y"); + + + if (IS_TRANSFER.equals("N")) { + siteService.commonBetinsert(tranParam); + org.codehaus.jettison.json.JSONObject cbResData = new org.codehaus.jettison.json.JSONObject(); + if (vendorCetegory.equals("SLOT")) { + cbResData = callBackService.changeBalanceSlot("PRAGMATIC REFUND - ", siteApiInfo, debit); + } else { + cbResData = callBackService.changeBalance("PRAGMATIC REFUND - ", siteApiInfo, debit); + } + + if (cbResData.getLong("result_code") == 0 || cbResData.getLong("result_code") == 98) { + log.info(LOG_PREFIX+ "siteService.updateCbApi(tranParam)"); + tranParam.put("balance", Double.parseDouble(cbResData.getString("balance"))); + + if (cbResData.getLong("result_code") == 0 ) { + int res = siteService.updateCbApi(tranParam); + } + + resData.put("transactionId", reference); + resData.put("currency", "VND"); + resData.put("cash", Double.parseDouble(cbResData.getString("balance"))); + resData.put("bonus", 0); + resData.put("error", 0); + resData.put("description", "Success"); + + } else { + resData.put("error", 120); + resData.put("description", "Internal Server Error(no-retry)"); + } + + }else { + + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(betInfo.get("tranId").toString() + "#R"); + + if(cntTr==0) { + siteService.commonBetinsert(tranParam); + } + try { + double balance = 0L; + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteApiInfo.get("siteIdx")); + balanceMap.put("memberId", memberId); + balance = Double.parseDouble("" + siteService.getUserBalance(balanceMap)); + + double afBalance = balance + amount; + log.info(LOG_PREFIX+ "siteService.updateCbApi(tranParam)"); + tranParam.put("balance", (double)afBalance); + tranParam.put("preBalance", (double)balance); + if(cntTr==0) { + int res = siteService.updateCbApi(tranParam); + } + resData.put("transactionId", reference); + resData.put("currency", "VND"); + if(cntTr==0) { + resData.put("cash", afBalance); + }else { + resData.put("cash", balance); + } + resData.put("bonus", 0); + resData.put("error", 0); + resData.put("description", "Success"); + + if(siteApiInfo.get("siteCbUrl") != null && !"".equals(siteApiInfo.get("siteCbUrl").toString())) { + debit.put("balance", afBalance); + if(vendorCetegory.equals("SLOT")) { + asyncCallBackService.asyncChangeBalanceSlot("PRAGMATIC REFUND - ", siteApiInfo, debit); + } else { + asyncCallBackService.asyncChangeBalance("PRAGMATIC REFUND - ", siteApiInfo, debit); + } + } + + }catch(Exception e) { + resData.put("error", 120); + resData.put("description", "Internal Server Error(no-retry)"); + } + } + + } catch (Exception e) { + String memberId = userId.substring(3, userId.length()); + final String LOG_PREFIX = "#-CB::PP::"+memberId+"::refund:::"; + log.error(LOG_PREFIX+ e.toString()); + resData.put("error", 120); + resData.put("description", "Internal Server Error(no-retry)"); + } + return resData; + } + + @CrossOrigin + @PostMapping(value = "/Result") + public @ResponseBody JSONObject result(HttpServletRequest request, @RequestBody(required = false) String parambody) + throws Exception { + JSONObject resData = new JSONObject(); + String hash = URLDecoder.decode(request.getParameter("hash"), "UTF-8"); + String userId = URLDecoder.decode(request.getParameter("userId"), "UTF-8"); + String gameId = URLDecoder.decode(request.getParameter("gameId"), "UTF-8"); + String roundId = URLDecoder.decode(request.getParameter("roundId"), "UTF-8"); + String amountStr = URLDecoder.decode(request.getParameter("amount"), "UTF-8"); + String reference = URLDecoder.decode(request.getParameter("reference"), "UTF-8"); + String providerId = URLDecoder.decode(request.getParameter("providerId"), "UTF-8"); + String timestamp = URLDecoder.decode(request.getParameter("timestamp"), "UTF-8"); + String roundDetails = URLDecoder.decode(request.getParameter("roundDetails"), "UTF-8"); + + try { + HashMap sParam = new HashMap(); + + sParam.put("siteIdx", Integer.parseInt(userId.substring(0, 3), 16)); + sParam.put("memberId", userId.substring(3, userId.length())); + String memberId = userId.substring(3, userId.length()); + final String LOG_PREFIX = "#-CB::PP::"+memberId+"::result:::"; + HashMap siteApiInfo = siteService.getSiteApiInfo(sParam); + String siteId = siteApiInfo.get("siteId").toString(); + log.info(LOG_PREFIX+ "# sparam() : " + siteApiInfo.toString()); + + if (siteApiInfo == null) { + + resData.put("error", 2); + resData.put("description", "Player not found or logged out."); + return resData; + } + + Map authParam = new HashMap(); + authParam.put("memberId", memberId); + authParam.put("siteId", siteId); + authParam.put("siteIdx", siteApiInfo.get("siteIdx")); + + // 회원정보 + Member member = siteService.getMemberByToken(authParam); + + if (member == null) { + resData.put("error", 2); + resData.put("description", "Player not found or logged out."); + return resData; + } + + double amount = Double.parseDouble(amountStr); + final String IS_TRANSFER = siteApiInfo.get("isTransfer").toString(); + + int vendorIdx = 17; + String vendorKey = "S02"; + String vendorCetegory = "SLOT"; + if (!(gameId.startsWith("vs") || gameId.startsWith("cs"))) { + vendorIdx = 2; + vendorKey = "C02"; + vendorCetegory = "CASINO"; + } + + HashMap tranParam = new HashMap(); + + String refId = siteId + roundId; + + tranParam.put("tranId", siteId + reference); + tranParam.put("refId", refId); + tranParam.put("siteIdx", siteApiInfo.get("siteIdx")); + tranParam.put("siteId", siteId); + tranParam.put("completed", true); + tranParam.put("memberIdx", member.getMemberIdx()); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "pragmatic"); + tranParam.put("vendorTranKey", reference); + tranParam.put("gameType", "slot"); + tranParam.put("gameId", gameId); + tranParam.put("gameIdx", gameId); + + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", "dfngtnslt_est88"); + tranParam.put("isTransfer", IS_TRANSFER); + + + + org.codehaus.jettison.json.JSONObject debit = new org.codehaus.jettison.json.JSONObject (); + double fakeAmount = amount;// *100; + debit.put("betId", refId); + debit.put("tranId", siteId + reference); + + debit.put("userId", member.getMemberId()); + debit.put("vendorIdx", vendorIdx); + debit.put("vendorKey", vendorKey); + debit.put("vendor", "pragmatic"); + debit.put("gameIdx", 1); + debit.put("gameKey", gameId); + debit.put("gameType", "slot"); + debit.put("gameId", gameId); + debit.put("tranType", "credit"); + debit.put("debit", 0); + debit.put("credit", fakeAmount); + debit.put("isCancel", 0); + debit.put("isBonus", 0); + debit.put("decYn", "Y"); + + + + if (IS_TRANSFER.equals("N")) { + + siteService.commonBetinsert(tranParam); + + org.codehaus.jettison.json.JSONObject cbResData = new org.codehaus.jettison.json.JSONObject(); + if (vendorCetegory.equals("SLOT")) { + cbResData = callBackService.changeBalanceSlot("PRAGMATIC SEAMLESS Result - ", siteApiInfo, debit); + } else { + cbResData = callBackService.changeBalance("PRAGMATIC SEAMLESS Result - ", siteApiInfo, debit); + } + + if (cbResData.getLong("result_code") == 0 || cbResData.getLong("result_code") == 98) { + log.info(LOG_PREFIX+ "siteService.updateCbApi(tranParam)"); + tranParam.put("balance", Double.parseDouble(cbResData.getString("balance"))); + if (cbResData.getLong("result_code") == 0) { + int res = siteService.updateCbApi(tranParam); + } + resData.put("transactionId", reference); + resData.put("currency", "VND"); + resData.put("cash", Double.parseDouble(cbResData.getString("balance"))); + resData.put("bonus", 0); + resData.put("error", 0); + resData.put("description", "Success"); + + } else { + resData.put("error", 120); + resData.put("description", "Internal Server Error(no-retry)"); + } + + }else { + + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(siteId + reference); + + + if(cntTr == 0) { + siteService.commonBetinsert(tranParam); + } + + try { + double balance = 0L; + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteApiInfo.get("siteIdx")); + balanceMap.put("memberId", memberId); + balance = Double.parseDouble("" + siteService.getUserBalance(balanceMap)); + + double afBalance = balance + amount; + log.info(LOG_PREFIX+ "siteService.updateCbApi(tranParam)"); + tranParam.put("balance", (double)afBalance); + tranParam.put("preBalance", (double)balance); + if(cntTr == 0) { + int res = siteService.updateCbApi(tranParam); + } + resData.put("transactionId", reference); + resData.put("currency", "VND"); + if(cntTr == 0) { + resData.put("cash", afBalance); + }else { + resData.put("cash", balance); + } + resData.put("bonus", 0); + resData.put("error", 0); + resData.put("description", "Success"); + + if(siteApiInfo.get("siteCbUrl") != null && !"".equals(siteApiInfo.get("siteCbUrl").toString())) { + debit.put("balance", afBalance); + if(vendorCetegory.equals("SLOT")) { + asyncCallBackService.asyncChangeBalanceSlot("PRAGMATIC TRANSFER RESULT - ", siteApiInfo, debit); + } else { + asyncCallBackService.asyncChangeBalance("PRAGMATIC TRANSFER RESULT - ", siteApiInfo, debit); + } + } + + }catch(Exception e) { + resData.put("error", 120); + resData.put("description", "Internal Server Error(no-retry)"); + } + } + + } catch (Exception e) { + String memberId = userId.substring(3, userId.length()); + final String LOG_PREFIX = "#-CB::PP::"+memberId+"::result:::"; + log.error(LOG_PREFIX+ e.toString()); + resData.put("error", 120); + resData.put("description", "Internal Server Error(no-retry)"); + + } + return resData; + } + + @CrossOrigin + @PostMapping(value = "/BonusWin") + public @ResponseBody JSONObject bonusWin(HttpServletRequest request, + @RequestBody(required = false) String parambody) throws Exception { + JSONObject resData = new JSONObject(); + String hash = URLDecoder.decode(request.getParameter("hash"), "UTF-8"); + String userId = URLDecoder.decode(request.getParameter("userId"), "UTF-8"); + String amountStr = URLDecoder.decode(request.getParameter("amount"), "UTF-8"); + String reference = URLDecoder.decode(request.getParameter("reference"), "UTF-8"); + String providerId = URLDecoder.decode(request.getParameter("providerId"), "UTF-8"); + String timestamp = URLDecoder.decode(request.getParameter("timestamp"), "UTF-8"); + String roundDetails = URLDecoder.decode(request.getParameter("roundDetails"), "UTF-8"); + + try { + HashMap sParam = new HashMap(); + + sParam.put("siteIdx", Integer.parseInt(userId.substring(0, 3), 16)); + sParam.put("memberId", userId.substring(3, userId.length())); + String memberId = userId.substring(3, userId.length()); + final String LOG_PREFIX = "#-CB::PP::"+memberId+"::bonusWin:::"; + HashMap siteApiInfo = siteService.getSiteApiInfo(sParam); + String siteId = siteApiInfo.get("siteId").toString(); + log.info(LOG_PREFIX+ "# sparam() : " + siteApiInfo.toString()); + + if (siteApiInfo == null) { + + resData.put("error", 2); + resData.put("description", "Player not found or logged out."); + return resData; + } + + Map authParam = new HashMap(); + authParam.put("memberId", memberId); + authParam.put("siteId", siteId); + authParam.put("siteIdx", siteApiInfo.get("siteIdx")); + + // 회원정보 + Member member = siteService.getMemberByToken(authParam); + + if (member == null) { + resData.put("error", 2); + resData.put("description", "Player not found or logged out."); + return resData; + } + + double amount = Double.parseDouble(amountStr); + final String IS_TRANSFER = siteApiInfo.get("isTransfer").toString(); + + HashMap tranParam = new HashMap(); + + String refId = siteId + reference; + + tranParam.put("tranId", refId); + tranParam.put("refId", refId); + tranParam.put("siteIdx", siteApiInfo.get("siteIdx")); + tranParam.put("siteId", siteId); + tranParam.put("completed", true); + tranParam.put("memberIdx", member.getMemberIdx()); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", "SLOT"); + tranParam.put("vendorIdx", 17); + tranParam.put("vendorCode", "pragmatic"); + tranParam.put("vendorTranKey", reference); + tranParam.put("gameType", "slot"); + tranParam.put("gameId", ""); + tranParam.put("gameIdx", providerId); + + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", "dfngtnslt_est88"); + tranParam.put("isTransfer", IS_TRANSFER); + + + org.codehaus.jettison.json.JSONObject debit = new org.codehaus.jettison.json.JSONObject(); + double fakeAmount = amount;// *100; + debit.put("betId", refId); + debit.put("tranId", siteId + reference); + + debit.put("userId", member.getMemberId()); + debit.put("vendorIdx", 17); + debit.put("vendorKey", "S02"); + debit.put("vendor", "pragmatic"); + debit.put("gameIdx", 1); + debit.put("gameKey", ""); + debit.put("gameType", "slot"); + debit.put("gameId", ""); + debit.put("tranType", "credit"); + debit.put("debit", 0); + debit.put("credit", fakeAmount); + debit.put("isCancel", 0); + debit.put("isBonus", 1); + debit.put("decYn", "Y"); + + + if (IS_TRANSFER.equals("N")) { + siteService.commonBetinsert(tranParam); + + org.codehaus.jettison.json.JSONObject cbResData = new org.codehaus.jettison.json.JSONObject(); + cbResData = callBackService.changeBalanceSlot("PRAGMATIC SEAMLESS BONUS - ", siteApiInfo, debit); + + + if (cbResData.getLong("result_code") == 0 || cbResData.getLong("result_code") == 98) { + log.info(LOG_PREFIX+ "siteService.updateCbApi(tranParam)"); + tranParam.put("balance", Double.parseDouble(cbResData.getString("balance"))); + if(cbResData.getLong("result_code") == 0) { + int res = siteService.updateCbApi(tranParam); + } + resData.put("transactionId", reference); + resData.put("currency", "VND"); + resData.put("cash", Double.parseDouble(cbResData.getString("balance"))); + resData.put("bonus", 0); + resData.put("error", 0); + resData.put("description", "Success"); + + } else { + resData.put("error", 120); + resData.put("description", "Internal Server Error(no-retry)"); + } + }else { + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(siteId + reference); + if(cntTr == 0) { + siteService.commonBetinsert(tranParam); + } + try { + double balance = 0L; + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteApiInfo.get("siteIdx")); + balanceMap.put("memberId", memberId); + balance = Double.parseDouble("" + siteService.getUserBalance(balanceMap)); + + double afBalance = balance + amount; + log.info(LOG_PREFIX+ "siteService.updateCbApi(tranParam)"); + tranParam.put("balance", (double)afBalance); + tranParam.put("preBalance", (double)balance); + if(cntTr == 0) { + int res = siteService.updateCbApi(tranParam); + } + resData.put("transactionId", reference); + resData.put("currency", "VND"); + if(cntTr == 0) { + resData.put("cash", afBalance); + }else{ + resData.put("cash", balance); + } + resData.put("bonus", 0); + resData.put("error", 0); + resData.put("description", "Success"); + + if(siteApiInfo.get("siteCbUrl") != null && !"".equals(siteApiInfo.get("siteCbUrl").toString())) { + debit.put("balance", afBalance); + asyncCallBackService.asyncChangeBalanceSlot("PRAGMATIC TRANSFER BONUS - ", siteApiInfo, debit); + } + + + }catch(Exception e) { + resData.put("error", 120); + resData.put("description", "Internal Server Error(no-retry)"); + } + } + + } catch (Exception e) { + String memberId = userId.substring(3, userId.length()); + final String LOG_PREFIX = "#-CB::PP::"+memberId+"::bonusWin:::"; + log.error(LOG_PREFIX+ e.toString()); + resData.put("error", 120); + resData.put("description", "Internal Server Error(no-retry)"); + } + return resData; + } + + @CrossOrigin + @PostMapping(value = "/PromoWin") + public @ResponseBody JSONObject promoWin(HttpServletRequest request, + @RequestBody(required = false) String parambody) throws Exception { + JSONObject resData = new JSONObject(); + String hash = URLDecoder.decode(request.getParameter("hash"), "UTF-8"); + String userId = URLDecoder.decode(request.getParameter("userId"), "UTF-8"); + String amountStr = URLDecoder.decode(request.getParameter("amount"), "UTF-8"); + String reference = URLDecoder.decode(request.getParameter("reference"), "UTF-8"); + String providerId = URLDecoder.decode(request.getParameter("providerId"), "UTF-8"); + String timestamp = URLDecoder.decode(request.getParameter("timestamp"), "UTF-8"); + String roundId = URLDecoder.decode(request.getParameter("roundId"), "UTF-8"); + String gameId = URLDecoder.decode(request.getParameter("gameId "), "UTF-8"); + String campaignId = URLDecoder.decode(request.getParameter("campaignId"), "UTF-8"); + String campaignType = URLDecoder.decode(request.getParameter("campaignType "), "UTF-8"); + + try { + HashMap sParam = new HashMap(); + + sParam.put("siteIdx", Integer.parseInt(userId.substring(0, 3), 16)); + sParam.put("memberId", userId.substring(3, userId.length())); + String memberId = userId.substring(3, userId.length()); + final String LOG_PREFIX = "#-CB::PP::"+memberId+"::promoWin:::"; + HashMap siteApiInfo = siteService.getSiteApiInfo(sParam); + String siteId = siteApiInfo.get("siteId").toString(); + log.info(LOG_PREFIX+ "# sparam() : " + siteApiInfo.toString()); + + if (siteApiInfo == null) { + resData.put("error", 2); + resData.put("description", "Player not found or logged out."); + return resData; + } + + Map authParam = new HashMap(); + authParam.put("memberId", memberId); + authParam.put("siteId", siteId); + authParam.put("siteIdx", siteApiInfo.get("siteIdx")); + + // 회원정보 + Member member = siteService.getMemberByToken(authParam); + + if (member == null) { + resData.put("error", 2); + resData.put("description", "Player not found or logged out."); + return resData; + } + + double amount = Double.parseDouble(amountStr); + final String IS_TRANSFER = siteApiInfo.get("isTransfer").toString(); + + int vendorIdx = 17; + String vendorKey = "S02"; + String vendorCetegory = "SLOT"; + if (!(gameId.startsWith("vs") || gameId.startsWith("cs"))) { + vendorIdx = 2; + vendorKey = "C02"; + vendorCetegory = "CASINO"; + } + + HashMap tranParam = new HashMap(); + + String refId = siteId + reference; + + tranParam.put("tranId", refId); + tranParam.put("refId", refId); + tranParam.put("siteIdx", siteApiInfo.get("siteIdx")); + tranParam.put("siteId", siteId); + tranParam.put("completed", true); + tranParam.put("memberIdx", member.getMemberIdx()); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "pragmatic"); + tranParam.put("vendorTranKey", reference); + tranParam.put("gameType", "slot"); + tranParam.put("gameId", gameId); + tranParam.put("gameIdx", providerId); + + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", "dfngtnslt_est88"); + tranParam.put("isTransfer", IS_TRANSFER); + + org.codehaus.jettison.json.JSONObject debit = new org.codehaus.jettison.json.JSONObject(); + double fakeAmount = amount;// *100; + debit.put("betId", refId); + debit.put("tranId", siteId + reference); + + debit.put("userId", member.getMemberId()); + debit.put("vendorIdx", vendorIdx); + debit.put("vendorKey", vendorKey); + debit.put("vendor", "pragmatic"); + debit.put("gameIdx", 1); + debit.put("gameKey", gameId); + debit.put("gameType", "slot"); + debit.put("gameId", gameId); + debit.put("tranType", "credit"); + debit.put("debit", 0); + debit.put("credit", fakeAmount); + debit.put("isCancel", 0); + debit.put("isBonus", 1); + debit.put("decYn", "Y"); + + if (IS_TRANSFER.equals("N")) { + siteService.commonBetinsert(tranParam); + org.codehaus.jettison.json.JSONObject cbResData = new org.codehaus.jettison.json.JSONObject(); + if (vendorCetegory.equals("SLOT")) { + cbResData = callBackService.changeBalanceSlot("PRAGMATIC PromoWin - ", siteApiInfo, debit); + } else { + cbResData = callBackService.changeBalance("PRAGMATIC PromoWin - ", siteApiInfo, debit); + } + if (cbResData.getLong("result_code") == 0 || cbResData.getLong("result_code") == 98) { + log.info(LOG_PREFIX+ "siteService.updateCbApi(tranParam)"); + tranParam.put("balance", Double.parseDouble(cbResData.getString("balance"))); + if (cbResData.getLong("result_code") == 0) { + int res = siteService.updateCbApi(tranParam); + } + resData.put("transactionId", reference); + resData.put("currency", "VND"); + resData.put("cash", Double.parseDouble(cbResData.getString("balance"))); + resData.put("bonus", 0); + resData.put("error", 0); + resData.put("description", "Success"); + } else { + resData.put("error", 120); + resData.put("description", "Internal Server Error(no-retry)"); + } + + }else { + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(siteId + reference); + if(cntTr == 0) { + siteService.commonBetinsert(tranParam); + } + try { + double balance = 0L; + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteApiInfo.get("siteIdx")); + balanceMap.put("memberId", memberId); + balance = Double.parseDouble("" + siteService.getUserBalance(balanceMap)); + + double afBalance = balance + amount; + log.info(LOG_PREFIX+ "siteService.updateCbApi(tranParam)"); + tranParam.put("balance", (double)afBalance); + tranParam.put("preBalance", (double)balance); + if(cntTr == 0) { + int res = siteService.updateCbApi(tranParam); + } + resData.put("transactionId", reference); + resData.put("currency", "VND"); + if(cntTr == 0) { + resData.put("cash", afBalance); + }else { + resData.put("cash", balance); + } + resData.put("bonus", 0); + resData.put("error", 0); + resData.put("description", "Success"); + + if(siteApiInfo.get("siteCbUrl") != null && !"".equals(siteApiInfo.get("siteCbUrl").toString())) { + debit.put("balance", afBalance); + if(vendorCetegory.equals("SLOT")) { + asyncCallBackService.asyncChangeBalanceSlot("PRAGMATIC TRANSFER PromoWin - ", siteApiInfo, debit); + } else { + asyncCallBackService.asyncChangeBalance("PRAGMATIC TRANSFER PromoWin - ", siteApiInfo, debit); + } + } + + + }catch(Exception e) { + resData.put("error", 120); + resData.put("description", "Internal Server Error(no-retry)"); + } + } + + } catch (Exception e) { + String memberId = userId.substring(3, userId.length()); + final String LOG_PREFIX = "#-CB::PP::"+memberId+"::promoWin:::"; + log.error(LOG_PREFIX+ e.toString()); + resData.put("error", 120); + resData.put("description", "Internal Server Error(no-retry)"); + + } + return resData; + } + + @CrossOrigin + @PostMapping(value = "/JackpotWin") + public @ResponseBody JSONObject jackpotWin(HttpServletRequest request, + @RequestBody(required = false) String parambody) throws Exception { + JSONObject resData = new JSONObject(); + String hash = URLDecoder.decode(request.getParameter("hash"), "UTF-8"); + String userId = URLDecoder.decode(request.getParameter("userId"), "UTF-8"); + String gameId = URLDecoder.decode(request.getParameter("gameId"), "UTF-8"); + String roundId = URLDecoder.decode(request.getParameter("roundId"), "UTF-8"); + String jackpotId = URLDecoder.decode(request.getParameter("jackpotId"), "UTF-8"); + String amountStr = URLDecoder.decode(request.getParameter("amount"), "UTF-8"); + String reference = URLDecoder.decode(request.getParameter("reference"), "UTF-8"); + String providerId = URLDecoder.decode(request.getParameter("providerId"), "UTF-8"); + String timestamp = URLDecoder.decode(request.getParameter("timestamp"), "UTF-8"); + String roundDetails = URLDecoder.decode(request.getParameter("roundDetails"), "UTF-8"); + + try { + HashMap sParam = new HashMap(); + + sParam.put("siteIdx", Integer.parseInt(userId.substring(0, 3), 16)); + sParam.put("memberId", userId.substring(3, userId.length())); + String memberId = userId.substring(3, userId.length()); + final String LOG_PREFIX = "#-CB::PP::"+memberId+"::jackpotWin:::"; + HashMap siteApiInfo = siteService.getSiteApiInfo(sParam); + String siteId = siteApiInfo.get("siteId").toString(); + log.info(LOG_PREFIX+ "# sparam() : " + siteApiInfo.toString()); + + if (siteApiInfo == null) { + + resData.put("error", 2); + resData.put("description", "Player not found or logged out."); + return resData; + } + + Map authParam = new HashMap(); + authParam.put("memberId", memberId); + authParam.put("siteId", siteId); + authParam.put("siteIdx", siteApiInfo.get("siteIdx")); + + // 회원정보 + Member member = siteService.getMemberByToken(authParam); + + if (member == null) { + resData.put("error", 2); + resData.put("description", "Player not found or logged out."); + return resData; + } + + double amount = Double.parseDouble(amountStr); + final String IS_TRANSFER = siteApiInfo.get("isTransfer").toString(); + + int vendorIdx = 17; + String vendorKey = "S02"; + String vendorCetegory = "SLOT"; + if (!(gameId.startsWith("vs") || gameId.startsWith("cs"))) { + vendorIdx = 2; + vendorKey = "C02"; + vendorCetegory = "CASINO"; + } + + HashMap tranParam = new HashMap(); + + String refId = siteId + roundId; + + tranParam.put("tranId", siteId + jackpotId + "#J"); + tranParam.put("refId", refId); + tranParam.put("siteIdx", siteApiInfo.get("siteIdx")); + tranParam.put("siteId", siteId); + tranParam.put("completed", true); + tranParam.put("memberIdx", member.getMemberIdx()); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "pragmatic"); + tranParam.put("vendorTranKey", reference); + tranParam.put("gameType", "slot"); + tranParam.put("gameId", gameId); + tranParam.put("gameIdx", providerId); + + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", "dfngtnslt_est88"); + tranParam.put("isTransfer", IS_TRANSFER); + + org.codehaus.jettison.json.JSONObject debit = new org.codehaus.jettison.json.JSONObject(); + double fakeAmount = amount;// *100; + debit.put("betId", refId); + debit.put("tranId", siteId + jackpotId + "#J"); + + debit.put("userId", member.getMemberId()); + debit.put("vendorIdx", vendorIdx); + debit.put("vendorKey", vendorKey); + debit.put("vendor", "pragmatic"); + debit.put("gameIdx", 1); + debit.put("gameKey", gameId); + debit.put("gameType", "slot"); + debit.put("gameId", gameId); + debit.put("tranType", "credit"); + debit.put("debit", 0); + debit.put("credit", fakeAmount); + debit.put("isCancel", 0); + debit.put("isBonus", 1); + debit.put("decYn", "Y"); + + if (IS_TRANSFER.equals("N")) { + siteService.commonBetinsert(tranParam); + org.codehaus.jettison.json.JSONObject cbResData = new org.codehaus.jettison.json.JSONObject(); + if (vendorCetegory.equals("SLOT")) { + cbResData = callBackService.changeBalanceSlot("PRAGMATIC JackpotWin - ", siteApiInfo, debit); + } else { + cbResData = callBackService.changeBalance("PRAGMATIC JackpotWin - ", siteApiInfo, debit); + } + + if (cbResData.getLong("result_code") == 0 || cbResData.getLong("result_code") == 98) { + log.info(LOG_PREFIX+ "siteService.updateCbApi(tranParam)"); + tranParam.put("balance", Double.parseDouble(cbResData.getString("balance"))); + if (cbResData.getLong("result_code") == 0) { + int res = siteService.updateCbApi(tranParam); + } + + resData.put("transactionId", reference); + resData.put("currency", "VND"); + resData.put("cash", Double.parseDouble(cbResData.getString("balance"))); + resData.put("bonus", 0); + resData.put("error", 0); + resData.put("description", "Success"); + } else { + resData.put("error", 120); + resData.put("description", "Internal Server Error(no-retry)"); + } + }else { + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(siteId + jackpotId + "#J"); + if(cntTr == 0) { + siteService.commonBetinsert(tranParam); + } + try { + double balance = 0L; + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteApiInfo.get("siteIdx")); + balanceMap.put("memberId", memberId); + balance = Double.parseDouble("" + siteService.getUserBalance(balanceMap)); + + double afBalance = balance + amount; + log.info(LOG_PREFIX+ "siteService.updateCbApi(tranParam)"); + tranParam.put("balance", (long)afBalance); + tranParam.put("preBalance", (long)balance); + if(cntTr == 0) { + int res = siteService.updateCbApi(tranParam); + } + + resData.put("transactionId", reference); + resData.put("currency", "VND"); + if(cntTr == 0) { + resData.put("cash", afBalance); + }else { + resData.put("cash", balance); + } + resData.put("bonus", 0); + resData.put("error", 0); + resData.put("description", "Success"); + + if(siteApiInfo.get("siteCbUrl") != null && !"".equals(siteApiInfo.get("siteCbUrl").toString())) { + debit.put("balance", afBalance); + if(vendorCetegory.equals("SLOT")) { + asyncCallBackService.asyncChangeBalanceSlot("PRAGMATIC TRANSFER JackpotWin - ", siteApiInfo, debit); + } else { + asyncCallBackService.asyncChangeBalance("PRAGMATIC TRANSFER JackpotWin - ", siteApiInfo, debit); + } + } + + + }catch(Exception e) { + resData.put("error", 120); + resData.put("description", "Internal Server Error(no-retry)"); + } + } + + } catch (Exception e) { + String memberId = userId.substring(3, userId.length()); + final String LOG_PREFIX = "#-CB::PP::"+memberId+"::jackpotWin:::"; + log.error(LOG_PREFIX+ e.toString()); + resData.put("status", "failure"); + resData.put("balance", "0.00"); + } + return resData; + } + + @CrossOrigin + @PostMapping(value = "/EndRound") + public @ResponseBody JSONObject endRound(HttpServletRequest request, + @RequestBody(required = false) String parambody) throws Exception { + JSONObject resData = new JSONObject(); + String hash = URLDecoder.decode(request.getParameter("hash"), "UTF-8"); + String userId = URLDecoder.decode(request.getParameter("userId"), "UTF-8"); + String gameId = URLDecoder.decode(request.getParameter("gameId"), "UTF-8"); + String roundId = URLDecoder.decode(request.getParameter("roundId"), "UTF-8"); + String providerId = URLDecoder.decode(request.getParameter("providerId"), "UTF-8"); + + try { + HashMap sParam = new HashMap(); + + sParam.put("siteIdx", Integer.parseInt(userId.substring(0, 3), 16)); + sParam.put("memberId", userId.substring(3, userId.length())); + String memberId = userId.substring(3, userId.length()); + final String LOG_PREFIX = "#-CB::PP::"+memberId+"::endRound:::"; + HashMap siteApiInfo = siteService.getSiteApiInfo(sParam); + String siteId = siteApiInfo.get("siteId").toString(); + log.info(LOG_PREFIX+ "# sparam() : " + siteApiInfo.toString()); + + if (siteApiInfo == null) { + + resData.put("error", 2); + resData.put("description", "Player not found or logged out."); + return resData; + } + + Map authParam = new HashMap(); + authParam.put("memberId", memberId); + authParam.put("siteId", siteId); + authParam.put("siteIdx", siteApiInfo.get("siteIdx")); + + // 회원정보 + Member member = siteService.getMemberByToken(authParam); + + if (member == null) { + resData.put("error", 2); + resData.put("description", "Player not found or logged out."); + return resData; + } + + // 크레딧 정보가 없는경우 체크 + BetParam betCheckParam = new BetParam(); + betCheckParam.setBetId(siteId + roundId); + HashMap betCheck = siteService.getBetCheck(betCheckParam); + + int vendorIdx = 17; + String vendorKey = "S02"; + String vendorCetegory = "SLOT"; + if (!(gameId.startsWith("vs") || gameId.startsWith("cs"))) { + vendorIdx = 2; + vendorKey = "C02"; + vendorCetegory = "CASINO"; + } + + + final String IS_TRANSFER = siteApiInfo.get("isTransfer").toString(); + + if (Integer.parseInt(betCheck.get("credit").toString()) == 0) { + + HashMap tranParam = new HashMap(); + + String refId = siteId + roundId; + + tranParam.put("tranId", siteId + roundId + "#CLOSE"); + tranParam.put("refId", refId); + tranParam.put("siteIdx", siteApiInfo.get("siteIdx")); + tranParam.put("siteId", siteId); + tranParam.put("completed", true); + tranParam.put("memberIdx", member.getMemberIdx()); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "pragmatic"); + tranParam.put("vendorTranKey", roundId + "#CLOSE"); + tranParam.put("gameType", "slot"); + tranParam.put("gameId", gameId); + tranParam.put("gameIdx", gameId); + + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", "0"); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", "dfngtnslt_est88"); + tranParam.put("isTransfer", IS_TRANSFER); + + + org.codehaus.jettison.json.JSONObject debit = new org.codehaus.jettison.json.JSONObject(); + + debit.put("betId", refId); + debit.put("tranId", siteId + roundId + "#CLOSE"); + + debit.put("userId", member.getMemberId()); + debit.put("vendorIdx", vendorIdx); + debit.put("vendorKey", vendorKey); + debit.put("vendor", "pragmatic"); + debit.put("gameIdx", 1); + debit.put("gameKey", gameId); + debit.put("gameType", "slot"); + debit.put("gameId", gameId); + debit.put("tranType", "credit"); + debit.put("debit", 0); + debit.put("credit", 0); + debit.put("isCancel", 0); + debit.put("isBonus", 1); + debit.put("decYn", "Y"); + + if (IS_TRANSFER.equals("N")) { + siteService.commonBetinsert(tranParam); + + org.codehaus.jettison.json.JSONObject cbResData = new org.codehaus.jettison.json.JSONObject(); + if (vendorCetegory.equals("SLOT")) { + cbResData = callBackService.changeBalanceSlot("PRAGMATIC ENDGame - ", siteApiInfo, debit); + } else { + cbResData = callBackService.changeBalance("PRAGMATIC ENDGame - ", siteApiInfo, debit); + } + + + if (cbResData.getLong("result_code") == 0 || cbResData.getLong("result_code") == 98) { + log.info(LOG_PREFIX+ "siteService.updateCbApi(tranParam)"); + tranParam.put("balance", Double.parseDouble(cbResData.getString("balance"))); + if (cbResData.getLong("result_code") == 0 ) { + int res = siteService.updateCbApi(tranParam); + } + + resData.put("cash", Double.parseDouble(cbResData.getString("balance"))); + resData.put("bonus", 0); + resData.put("error", 0); + resData.put("description", "Success"); + } + }else { + + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(siteId + roundId + "#CLOSE"); + if(cntTr ==0) { + siteService.commonBetinsert(tranParam); + } + try { + double balance = 0L; + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteApiInfo.get("siteIdx")); + balanceMap.put("memberId", memberId); + balance = Double.parseDouble("" + siteService.getUserBalance(balanceMap)); + + double afBalance = balance; + log.info(LOG_PREFIX+ "siteService.updateCbApi(tranParam)"); + tranParam.put("balance", (long)afBalance); + tranParam.put("preBalance", (long)balance); + if(cntTr ==0) { + int res = siteService.updateCbApi(tranParam); + } + if(cntTr ==0) { + resData.put("cash", afBalance); + }else { + resData.put("cash", balance); + } + + resData.put("bonus", 0); + resData.put("error", 0); + resData.put("description", "Success"); + + if(siteApiInfo.get("siteCbUrl") != null && !"".equals(siteApiInfo.get("siteCbUrl").toString())) { + debit.put("balance", afBalance); + if(vendorCetegory.equals("SLOT")) { + asyncCallBackService.asyncChangeBalanceSlot("PRAGMATIC TRANSFER ENDGame - ", siteApiInfo, debit); + } else { + asyncCallBackService.asyncChangeBalance("PRAGMATIC TRANSFER ENDGame - ", siteApiInfo, debit); + } + } + + + }catch(Exception e) { + resData.put("error", 120); + resData.put("description", "Internal Server Error(no-retry)"); + } + } + } else { + if (IS_TRANSFER.equals("N")) { + double balance = getBalanceDouble(LOG_PREFIX, siteApiInfo.get("siteCbUrl").toString(), memberId); + resData.put("cash", balance); + resData.put("bonus", 0); + resData.put("error", 0); + resData.put("description", "Success"); + + }else { + + double balance = 0L; + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteApiInfo.get("siteIdx")); + balanceMap.put("memberId", memberId); + balance = Double.parseDouble("" + siteService.getUserBalance(balanceMap)); + + double afBalance = balance; + log.info(LOG_PREFIX+ "siteService.updateCbApi(tranParam)"); + + resData.put("cash", afBalance); + resData.put("bonus", 0); + resData.put("error", 0); + resData.put("description", "Success"); + + } + + } + + } catch (Exception e) { + String memberId = userId.substring(3, userId.length()); + final String LOG_PREFIX = "#-CB::PP::"+memberId+"::endRound:::"; + log.error(LOG_PREFIX+ e.toString()); + resData.put("error", 120); + resData.put("description", "Internal Server Error(no-retry)"); + } + return resData; + } + + private org.codehaus.jettison.json.JSONObject getBalance(String LOG_PREFIX, HashMap siteApiInfo, JSONObject member) + throws JSONException { + + org.codehaus.jettison.json.JSONObject res = new org.codehaus.jettison.json.JSONObject(); + + log.info(LOG_PREFIX+ "# site.getSiteCbUrl() : " + siteApiInfo.get("siteCbUrl") + "/balance"); + log.info(LOG_PREFIX+ "# site.getSiteCbUrl() : " + member.toString()); + String url = siteApiInfo.get("siteCbUrl") + "/balance"; + ResponseEntity responseEntity = null; + try { + responseEntity = webClient.post() + .uri(url) + .header("Content-Type", "application/json") + .header("Accept", "application/json") + .header("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36") + .bodyValue(member.toString()) + .retrieve() + .toEntity(String.class) + .block(); + + log.info(LOG_PREFIX+ "status code : {}", responseEntity != null ? responseEntity.getStatusCode() : "NULL"); + log.info(LOG_PREFIX+ "body: {}", responseEntity != null ? responseEntity.getBody() : ""); + + } catch (Exception ex) { + log.error(LOG_PREFIX+ "error calling site cb /balance", ex); + throw ex; + } + + org.codehaus.jettison.json.JSONObject resData = new org.codehaus.jettison.json.JSONObject( + responseEntity != null ? responseEntity.getBody() : "{}"); + + return resData; + + } + + private double getBalanceDouble(String LOG_PREFIX, String cbUrl, String memId) { + double balance = 0L; + try { + + log.info(LOG_PREFIX+ "balance: {}", cbUrl + "/balance"); + + JSONObject members = new JSONObject(); + members.put("userId", memId); + members.put("decYn", "Y"); + + // 회원 머니 + ResponseEntity responseEntity = null; + try { + responseEntity = webClient.post() + .uri(cbUrl + "/balance") + .header("Content-Type", "application/json") + .header("Accept", "application/json") + .header("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36") + .bodyValue(members.toString()) + .retrieve() + .toEntity(String.class) + .block(); + + log.info(LOG_PREFIX+ "status code : {}", responseEntity != null ? responseEntity.getStatusCode() : "NULL"); + log.info(LOG_PREFIX+ "body: {}", responseEntity != null ? responseEntity.getBody() : ""); + + org.codehaus.jettison.json.JSONObject resData = new org.codehaus.jettison.json.JSONObject( + responseEntity != null ? responseEntity.getBody() : "{}"); + balance = Double.parseDouble(resData.getString("balance")); // 문자열이어도 안전("balance");// * 0.01; + + } catch (Exception e) { + log.error(LOG_PREFIX+ "error calling cb balance", e); + throw e; + } + } catch (Exception e) { + + } + return balance; + + } + + private String makeApiKey(String param) { + + int n = 20; // n자리 쿠폰 + char[] chs = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', + 'J', 'K', 'L', 'M', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'N', 'O', 'P', 'Q', + 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', + 'z' }; + + Random rd = new Random(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < n; i++) { + char ch = chs[rd.nextInt(chs.length)]; + sb.append(ch); + } + return param + sb.toString(); + + } + +} diff --git a/src/main/java/com/bb/front/CallBackPrimeController.java b/src/main/java/com/bb/front/CallBackPrimeController.java new file mode 100644 index 0000000..d141e09 --- /dev/null +++ b/src/main/java/com/bb/front/CallBackPrimeController.java @@ -0,0 +1,823 @@ +package com.bb.front; + +import java.net.SocketTimeoutException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; + +import jakarta.servlet.http.HttpServletRequest; + +import org.apache.http.conn.ConnectTimeoutException; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.ResourceAccessException; + +import com.bb.model.PrimeResponse; +import com.bb.service.CallBackService; +import com.bb.service.SiteService; + +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@RequestMapping("/api/callback/prime") +@RequiredArgsConstructor +@SecurityRequirement(name = "Authorization") +@EnableScheduling +@RestController +public class CallBackPrimeController { + + @Autowired + SiteService siteService; + + @Autowired + CallBackService callBackService; + + + @ResponseBody + @RequestMapping(path = "/balance") + public ResponseEntity balance(HttpServletRequest request, @RequestParam("username") String primeUsername) throws Exception { + PrimeResponse response = null; + + long siteIdx = Long.parseLong(primeUsername.substring(0, 3), 16); + String memberId = primeUsername.substring(3, primeUsername.length()); + final String LOG_PREFIX = "#-CB::PRIME::balance::"+memberId+":::"; + log.info(LOG_PREFIX+ "Request::" + primeUsername); + + try { + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + log.info(LOG_PREFIX + "SITE_API_INFO_PARAM::"+sParam.toString()); + HashMap siteApiInfo = siteService.getSiteApiInfo(sParam); + if(siteApiInfo == null) { + log.error(LOG_PREFIX+ "Error Msg: NOT_FOUND_SITE_INFO"); + response = new PrimeResponse(); + response.setBalance(0); + return new ResponseEntity(response, HttpStatus.BAD_REQUEST); + } + + if(siteApiInfo.get("memberIdx") == null) { + log.error(LOG_PREFIX+ "존재하지 않는 회원"); + response = new PrimeResponse(); + response.setBalance(0); + return new ResponseEntity(response, HttpStatus.BAD_REQUEST); + } + + JSONObject member = new JSONObject(); + member.put("userId", memberId); + log.info(LOG_PREFIX+ "balance Req ::"+ member.toString()); + JSONObject resData = callBackService.getBalance(siteApiInfo, member); + if(resData == null) { + log.error(LOG_PREFIX+ "Error Msg: BALANCE_CALLBACK_ERROR"); + response = new PrimeResponse(); + response.setBalance(0); + return new ResponseEntity(response, HttpStatus.BAD_REQUEST); + } + log.info(LOG_PREFIX+ "balance Res ::"+ resData.toString()); + int balance = resData.getInt("balance"); + + response = new PrimeResponse(); + response.setBalance(balance); + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + response = new PrimeResponse(); + response.setBalance(0); + return new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + response = new PrimeResponse(); + response.setBalance(0); + return new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + ResponseEntity res = new ResponseEntity(response, HttpStatus.OK); + log.info(LOG_PREFIX+ "Response::" + response.toString()); + + return res; + } + + + @ResponseBody + @RequestMapping(path = "/changeBalance") + public ResponseEntity changeBalance(HttpServletRequest request, @RequestBody net.sf.json.JSONObject requestBody) throws Exception { + ResponseEntity resEntity = null; + + String primeUsername = requestBody.getString("username"); + long siteIdx = Long.parseLong(primeUsername.substring(0, 3), 16); + String memberId = primeUsername.substring(3, primeUsername.length()); + net.sf.json.JSONObject transaction = requestBody.getJSONObject("transaction"); + net.sf.json.JSONObject game = transaction.getJSONObject("details").getJSONObject("game"); + String transactionId = transaction.getString("id"); + String transactionType = transaction.getString("type"); + + final String LOG_PREFIX = "#-CB::PRIME::changeBalance::"+memberId+"::"+transactionId+"::"+transactionType+":::"; + log.info(LOG_PREFIX+ "Request::" + requestBody.toString()); + + try { + // "processed_at":"2025-01-16T09:25:23.000000Z" + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS"); + String betDateTimeStr = transaction.getString("processed_at"); + log.info(LOG_PREFIX+ "========== BF_betDateTimeStr::" + betDateTimeStr); + betDateTimeStr = betDateTimeStr.substring(0, 19); + betDateTimeStr = betDateTimeStr.replace("T", " "); + log.info(LOG_PREFIX+ "========== MF_betDateTimeStr::" + betDateTimeStr); + betDateTimeStr = makeEdate(LOG_PREFIX, betDateTimeStr, 32400000); + log.info(LOG_PREFIX+ "========== AF_betDateTimeStr::" + betDateTimeStr); + + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "prime"); + sParam.put("vendorGameCode", game.getString("vendor_code")); + log.info(LOG_PREFIX + "getSiteVendorInfo::"+sParam.toString()); + HashMap siteVendorInfo = siteService.getSiteVendorInfo(sParam); + if(siteVendorInfo == null) { + log.error(LOG_PREFIX+ "존재하지 않는 회원입니다"); + PrimeResponse response = new PrimeResponse(); + resEntity = new ResponseEntity(response, HttpStatus.BAD_REQUEST); + return resEntity; + } + + if(transactionType.equals("bet")) { + int amount = Math.abs(requestBody.getInt("amount")); + resEntity = callBet(LOG_PREFIX, siteIdx, memberId, transaction, betDateTimeStr, siteVendorInfo, amount); + + } else if(transactionType.equals("win")) { + int amount = Math.abs(requestBody.getInt("amount")); + resEntity = callWin(LOG_PREFIX, siteIdx, memberId, transaction, betDateTimeStr, siteVendorInfo, amount); + + } else if(transactionType.equals("cancel")) { + int amount = Math.abs(requestBody.getInt("amount")); + resEntity = callCancel(LOG_PREFIX, siteIdx, memberId, transaction, betDateTimeStr, siteVendorInfo, amount); + + } else if(transactionType.equals("adjust")) { + int amount = requestBody.getInt("amount"); + //resEntity = callAdjust(LOG_PREFIX, siteIdx, memberId, transaction, betDateTimeStr, siteVendorInfo, amount); + + } else if(transactionType.equals("promo_win")) { + int amount = Math.abs(requestBody.getInt("amount")); + //resEntity = callPromoWin(LOG_PREFIX, siteIdx, memberId, transaction, betDateTimeStr, siteVendorInfo, amount); + + } else { + log.error(LOG_PREFIX+ "unknown_transaction_type"); + PrimeResponse response = new PrimeResponse(); + resEntity = new ResponseEntity(response, HttpStatus.BAD_REQUEST); + return resEntity; + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + PrimeResponse response = new PrimeResponse(); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + return resEntity; + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + PrimeResponse response = new PrimeResponse(); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + return resEntity; + } + + log.info(LOG_PREFIX+ "Response::" + resEntity.toString()); + + return resEntity; + } + + private ResponseEntity callBet(String LOG_PREFIX, long siteIdx, String memberId, + net.sf.json.JSONObject transaction, String betDateTimeStr, HashMap siteVendorInfo, int amount) { + + LOG_PREFIX = LOG_PREFIX + "callBet:::"; + ResponseEntity resEntity = null; + PrimeResponse response = new PrimeResponse(); + + try { + net.sf.json.JSONObject details = transaction.getJSONObject("details"); + net.sf.json.JSONObject game = details.getJSONObject("game"); + + String gameType = game.getString("type").replaceAll(" ", "").toLowerCase(); + String betKey = game.getString("id")+"#"+transaction.getString("referer_id"); + String gameName = game.getString("title"); + + String tableId = game.getString("game_code"); + String targetTableId = tableId.replaceAll(" ", "").toLowerCase(); + + String banGameType = siteVendorInfo.get("banGameType").toString().replaceAll(" ", "").toLowerCase(); + String banGameId = siteVendorInfo.get("banGameId").toString().replaceAll(" ", "").toLowerCase(); + + if(!"".equals(gameType) && !"".equals(banGameType) && banGameType.contains(gameType+"|")) { + log.error(LOG_PREFIX+ "Ban Game Type : " + gameType); + resEntity = new ResponseEntity(response, HttpStatus.BAD_REQUEST); // 501 + return resEntity; + } + + if(!"".equals(targetTableId) && !"".equals(banGameId) && banGameId.contains(targetTableId+"|")) { + log.error(LOG_PREFIX+ "Ban Game Id : " + banGameId); + resEntity = new ResponseEntity(response, HttpStatus.BAD_REQUEST); // 502 + return resEntity; + } + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + String tranId = transaction.getString("id"); + String betId = transaction.getString("referer_id"); + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + + /* + int cnt1 = siteService.getTranIdCheck(tranId); + if(cnt1 != 0) { + // 중복베팅 + log.error(LOG_PREFIX+ "중복베팅"); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + return resEntity; + } + */ + + if(siteVendorInfo.get("lastInVendorIdx")==null || "0".equals(siteVendorInfo.get("lastInVendorIdx").toString())) { + HashMap memParam = new HashMap<>(); + memParam.put("siteIdx", siteIdx); + memParam.put("memberIdx", memberIdx); + memParam.put("lastInVendorIdx", Integer.parseInt(siteVendorInfo.get("vendorIdx").toString())); + int updResult = siteService.updMemLastVendorIdx(memParam); + } else { + int lastInVendorIdx = Integer.parseInt(siteVendorInfo.get("lastInVendorIdx").toString()); + if(lastInVendorIdx != vendorIdx) { + log.error(LOG_PREFIX+ "VendorIdx doesn't match"); + resEntity = new ResponseEntity(response, HttpStatus.BAD_REQUEST); + return resEntity; + } + } + + long siteCredit = Long.parseLong(siteVendorInfo.get("credit").toString()); + if(siteCredit < amount) { + log.error(LOG_PREFIX+ "NO_SITE_CREDIT"); + resEntity = new ResponseEntity(response, HttpStatus.BAD_REQUEST); + return resEntity; + } + + // 최대 베팅 금액 처리 (userMaxBet 우선 적용) + long siteMaxBet = Long.parseLong(siteVendorInfo.get("siteMaxBet").toString()); + long userMaxBet = 0; + if(siteVendorInfo.get("userMaxBet") != null && !siteVendorInfo.get("userMaxBet").toString().isEmpty()) { + try { + userMaxBet = Long.parseLong(siteVendorInfo.get("userMaxBet").toString()); + } catch (NumberFormatException e) { + userMaxBet = 0; + } + } + + // 최종 maxBet 결정: userMaxBet이 0이면 siteMaxBet 사용, 0이 아니면 userMaxBet 사용 + long finalMaxBet = (userMaxBet > 0) ? userMaxBet : siteMaxBet; + log.info(LOG_PREFIX+ "MaxBet Info - siteMaxBet: " + siteMaxBet + ", userMaxBet: " + userMaxBet + ", finalMaxBet: " + finalMaxBet); + + if(finalMaxBet < amount) { + log.error(LOG_PREFIX+ "MAX_BET_AMOUNT_OVER"); + log.error(LOG_PREFIX+ "finalMaxBet : " + finalMaxBet +", amount : " + amount); + resEntity = new ResponseEntity(response, HttpStatus.BAD_REQUEST); + return resEntity; + } + + boolean isParsing = false; + log.info(LOG_PREFIX + "BF_isParsing::"+isParsing); + Boolean genuine = false; + if(transaction.has("genuine")) { + log.info(LOG_PREFIX + "transaction.has(\"genuine\") is true"); + genuine = transaction.getBoolean("genuine"); + log.info(LOG_PREFIX + "transaction.genuine::"+genuine.booleanValue()); + // genuine = true : 정품 + // genuine = null or false : 하이브리드(파싱) + if(genuine != null && genuine.booleanValue() == true) { + isParsing = false; + } else { + isParsing = true; + } + } else { + log.info(LOG_PREFIX + "transaction.has(\"genuine\") is false"); + isParsing = true; + } + log.info(LOG_PREFIX + "AF_isParsing::"+isParsing); + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "prime"); + tranParam.put("vendorTranKey", betKey); + tranParam.put("gameType", game.getString("type")); + tranParam.put("gameId", tableId); + tranParam.put("gameType", game.getString("type")); + tranParam.put("gameId", tableId); + tranParam.put("gameIdx", gameName); + tranParam.put("tranType", "debit"); + tranParam.put("depositAmt", amount); + tranParam.put("creditAmt", "0"); + tranParam.put("isCancel", "N"); + if(isParsing) { + tranParam.put("isTie", "P"); + } else { + tranParam.put("isTie", "N"); + } + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + log.info(LOG_PREFIX + "-----INSERT_BET_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_BET_END-----"); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("betKey", betKey); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "prime"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", gameName); + callBackObj.put("gameId", tableId); + callBackObj.put("gameType", game.getString("type")); + callBackObj.put("tranType", "debit"); + callBackObj.put("debit", amount); + callBackObj.put("credit", 0); + callBackObj.put("isCancel", 0); + callBackObj.put("isBonus", 0); + if(isParsing) { + callBackObj.put("isData", "Y"); + } else { + callBackObj.put("isData", "N"); + } + callBackObj.put("requestAt", betDateTimeStr); + log.info(LOG_PREFIX + "SEND_BET request body: " + callBackObj.toString()); + JSONObject resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + log.info(LOG_PREFIX + "SEND_BET status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_BET response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + response.setBalance(balance); + response.setBeforeBalance(balance+amount); + resEntity = new ResponseEntity(response, HttpStatus.OK); + } else if(resData.getLong("result_code") == 98) { + int balance = resData.getInt("balance"); + response.setBalance(balance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + } else if(resData.getLong("result_code") == 80) { + int balance = resData.getInt("balance"); + response.setBalance(balance); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } else { + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + log.error(LOG_PREFIX+ msg); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + return resEntity; + } + + + private ResponseEntity callWin(String LOG_PREFIX, long siteIdx, String memberId, + net.sf.json.JSONObject transaction, String betDateTimeStr, HashMap siteVendorInfo, int amount) { + + LOG_PREFIX = LOG_PREFIX + "callWin:::"; + ResponseEntity resEntity = null; + PrimeResponse response = new PrimeResponse(); + + try { + net.sf.json.JSONObject details = transaction.getJSONObject("details"); + net.sf.json.JSONObject game = details.getJSONObject("game"); + + String tableId = game.getString("game_code"); + String betKey = game.getString("id")+"#"+transaction.getString("referer_id"); + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + String tranId = transaction.getString("id"); + String betId = transaction.getString("referer_id"); + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + + /* + int cnt1 = siteService.getTranIdCheck(tranId); + if(cnt1 != 0) { + // 중복베팅 + log.error(LOG_PREFIX+ "중복베팅"); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + return resEntity; + } + */ + + int cnt2 = siteService.getBetIdCheck(betId); + if(cnt2 == 0) { + // 처리한 베팅 존재X + log.error(LOG_PREFIX+ "처리한 베팅 존재X"); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + return resEntity; + } + + boolean isParsing = false; + log.info(LOG_PREFIX + "BF_isParsing::"+isParsing); + Boolean genuine = false; + if(transaction.has("genuine")) { + log.info(LOG_PREFIX + "transaction.has(\"genuine\") is true"); + genuine = transaction.getBoolean("genuine"); + log.info(LOG_PREFIX + "transaction.genuine::"+genuine.booleanValue()); + // genuine = true : 정품 + // genuine = null or false : 하이브리드(파싱) + if(genuine != null && genuine.booleanValue() == true) { + isParsing = false; + } else { + isParsing = true; + } + } else { + log.info(LOG_PREFIX + "transaction.has(\"genuine\") is false"); + isParsing = true; + } + log.info(LOG_PREFIX + "AF_isParsing::"+isParsing); + + String isDebitParse = siteService.getDebitIsParse(betId); + log.info(LOG_PREFIX + "isDebitParse::"+isDebitParse); + if(isDebitParse == null) { + log.error(LOG_PREFIX+ "처리한 베팅 존재X"); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + return resEntity; + } else { + if("P".equals(isDebitParse)) { + isParsing = true; + } + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "prime"); + tranParam.put("vendorTranKey", betKey); + tranParam.put("gameType", game.getString("type")); + tranParam.put("gameId", tableId); + tranParam.put("gameType", game.getString("type")); + tranParam.put("gameId", tableId); + tranParam.put("gameIdx", game.getString("title")); + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + tranParam.put("isCancel", "N"); + if(isParsing) { + tranParam.put("isTie", "P"); + } else { + tranParam.put("isTie", "N"); + } + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + log.info(LOG_PREFIX + "-----INSERT_RESULT_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_RESULT_END-----"); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("betKey", betKey); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "prime"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", game.getString("title")); + callBackObj.put("gameId", tableId); + callBackObj.put("gameType", game.getString("type")); + callBackObj.put("tranType", "credit"); + callBackObj.put("debit", 0); + callBackObj.put("credit", amount); + callBackObj.put("isCancel", 0); + callBackObj.put("isBonus", 0); + if(isParsing) { + callBackObj.put("isData", "Y"); + } else { + callBackObj.put("isData", "N"); + } + callBackObj.put("requestAt", betDateTimeStr); + log.info(LOG_PREFIX + "SEND_RESULT request body: " + callBackObj.toString()); + JSONObject resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + log.info(LOG_PREFIX + "SEND_RESULT status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_RESULT response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + response.setBalance(balance); + response.setBeforeBalance(balance-amount); + resEntity = new ResponseEntity(response, HttpStatus.OK); + + } else if(resData.getLong("result_code") == 98) { + int balance = resData.getInt("balance"); + response.setBalance(balance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + + } else { + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + log.error(LOG_PREFIX+ msg); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + return resEntity; + } + + + private ResponseEntity callCancel(String LOG_PREFIX, long siteIdx, String memberId, + net.sf.json.JSONObject transaction, String betDateTimeStr, HashMap siteVendorInfo, int amount) { + + ResponseEntity resEntity = null; + PrimeResponse response = new PrimeResponse(); + + try { + net.sf.json.JSONObject details = transaction.getJSONObject("details"); + net.sf.json.JSONObject game = details.getJSONObject("game"); + + String tableId = game.getString("game_code"); + String betKey = game.getString("id")+"#"+transaction.getString("referer_id"); + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + String tranId = transaction.getString("id"); + String betId = transaction.getString("referer_id"); + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + + /* + int cnt1 = siteService.getTranIdCheck(tranId); + if(cnt1 != 0) { + // 중복베팅 + log.error(LOG_PREFIX+ "중복베팅"); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + return resEntity; + } + */ + + int cnt2 = siteService.getBetIdCheck(betId); + if(cnt2 == 0) { + // 처리한 베팅 존재X + log.error(LOG_PREFIX+ "처리한 베팅 존재X"); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + return resEntity; + } + + boolean isParsing = false; + log.info(LOG_PREFIX + "BF_isParsing::"+isParsing); + Boolean genuine = false; + if(transaction.has("genuine")) { + log.info(LOG_PREFIX + "transaction.has(\"genuine\") is true"); + genuine = transaction.getBoolean("genuine"); + log.info(LOG_PREFIX + "transaction.genuine::"+genuine.booleanValue()); + // genuine = true : 정품 + // genuine = null or false : 하이브리드(파싱) + if(genuine != null && genuine.booleanValue() == true) { + isParsing = false; + } else { + isParsing = true; + } + } else { + log.info(LOG_PREFIX + "transaction.has(\"genuine\") is false"); + isParsing = true; + } + log.info(LOG_PREFIX + "AF_isParsing::"+isParsing); + + String isDebitParse = siteService.getDebitIsParse(betId); + log.info(LOG_PREFIX + "isDebitParse::"+isDebitParse); + if(isDebitParse == null) { + log.error(LOG_PREFIX+ "처리한 베팅 존재X"); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + return resEntity; + } else { + if("P".equals(isDebitParse)) { + isParsing = true; + } + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "prime"); + tranParam.put("vendorTranKey", betKey); + tranParam.put("gameType", game.getString("type")); + tranParam.put("gameId", tableId); + tranParam.put("gameType", game.getString("type")); + tranParam.put("gameId", tableId); + tranParam.put("gameIdx", game.getString("title")); + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + tranParam.put("isCancel", "Y"); + if(isParsing) { + tranParam.put("isTie", "P"); + } else { + tranParam.put("isTie", "N"); + } + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + log.info(LOG_PREFIX + "-----INSERT_CANCEL_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_CANCEL_END-----"); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("betKey", betKey); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "prime"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", game.getString("title")); + callBackObj.put("gameId", tableId); + callBackObj.put("gameType", game.getString("type")); + callBackObj.put("tranType", "credit"); + callBackObj.put("debit", 0); + callBackObj.put("credit", amount); + callBackObj.put("isCancel", 1); + callBackObj.put("isBonus", 0); + if(isParsing) { + callBackObj.put("isData", "Y"); + } else { + callBackObj.put("isData", "N"); + } + callBackObj.put("requestAt", betDateTimeStr); + log.info(LOG_PREFIX + "SEND_CANCEL request body: " + callBackObj.toString()); + JSONObject resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + log.info(LOG_PREFIX + "SEND_CANCEL status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_CANCEL response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + response.setBalance(balance); + response.setBeforeBalance(balance-amount); + resEntity = new ResponseEntity(response, HttpStatus.OK); + + } else if(resData.getLong("result_code") == 98) { + int balance = resData.getInt("balance"); + response.setBalance(balance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + + } else { + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + log.error(LOG_PREFIX+ msg); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + return resEntity; + } + + + private static String makeEdate(String LOG_PREFIX, String paramDate, int flag) { + // TODO Auto-generated method stub + String eDate = ""; + SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + try { + Date date = sdf1.parse(paramDate); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + calendar.add(Calendar.MILLISECOND, flag); + Date date2 = calendar.getTime(); + eDate = sdf2.format(date2); + } catch(Exception e) { + log.error(LOG_PREFIX+ "makeEdate::Exception::"+e.getMessage()); + } + return eDate; + } +} diff --git a/src/main/java/com/bb/front/CallBackSplusCasinoController.java b/src/main/java/com/bb/front/CallBackSplusCasinoController.java new file mode 100644 index 0000000..5998a47 --- /dev/null +++ b/src/main/java/com/bb/front/CallBackSplusCasinoController.java @@ -0,0 +1,1491 @@ +package com.bb.front; + +import java.math.BigDecimal; +import java.net.URLDecoder; +import java.text.DecimalFormat; +import java.util.Date; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +import org.json.XML; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.reactive.function.client.WebClient; + +import com.bb.jwt.JwtManager; +import com.bb.model.Member; +import com.bb.service.SiteService; +import com.bb.service.SplusService; +import com.bb.util.StringUtils.StringBuilderPlus; +import com.google.gson.Gson; + +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import net.sf.json.JSONObject; + +@Slf4j +@Controller +@RequestMapping("/api/cb/splus") +@RequiredArgsConstructor +public class CallBackSplusCasinoController { + + @Autowired + private final JwtManager jwtManager; + + @Autowired + SiteService siteService; + + @Autowired + SplusService splusService; + + @Autowired + WebClient webClient; + + @CrossOrigin(origins = "*") + @GetMapping(value = "/js/refresh") + public @ResponseBody JSONObject refreshToken(HttpServletRequest request, ModelMap model) throws Exception { + log.info("#-splus::refreshToken::___________________Request____________________________"); + Enumeration params = request.getParameterNames(); + while (params.hasMoreElements()) { + String name = (String) params.nextElement(); + String value = request.getParameter(name); + log.info("#-splus::refreshToken::" + name + "=" + value); + } + log.info("#-splus::refreshToken::___________________Request____________________________"); + + StringBuilderPlus sp = new StringBuilderPlus(); + JSONObject resData = new JSONObject(); + + try { + String base64Token = URLDecoder.decode(request.getParameter("token"), "UTF-8"); + Map authParam = new HashMap(); + + if ("F0IjoxNTE2MjM5MDIyfQ".equals(base64Token)) { + authParam.put("memberId", "007maker1"); + authParam.put("siteId", "peanuts9"); + } else if ("F0IjoxNTE1MjM3MDIyfQ".equals(base64Token)) { + authParam.put("memberId", "00Dmat02"); + authParam.put("siteId", "aplus1"); + } else { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfo(base64Token); + authParam.put("memberId", tokenInfo.getMid()); + authParam.put("siteId", tokenInfo.getSid()); + } + + // 회사정보 + HashMap siteApiInfo = siteService.getSiteApiInfoByToken(authParam); + log.info("#-splus::refreshToken::::siteApiInfo {}", siteApiInfo); + + if ("F0IjoxNTE2MjM5MDIyfQ".equals(base64Token)) { + authParam.put("siteIdx", 87); + } else if ("F0IjoxNTE1MjM3MDIyfQ".equals(base64Token)) { + authParam.put("siteIdx", 12); + } else { + authParam.put("siteIdx", siteApiInfo.get("siteIdx")); + } + + // 회원정보 + Member member = siteService.getMemberByToken(authParam); + + int res = siteService.getSplusToken(base64Token); + + DecimalFormat formatter = new DecimalFormat("0"); + double balance = getBalnce("#-splus::refreshToken::", siteApiInfo.get("siteCbUrl").toString(), + authParam.get("memberId").toString()); + + resData.put("status", "success"); + resData.put("balance", "" + formatter.format(new BigDecimal(balance))); + + siteService.insertToken(base64Token); + + } catch (Exception e) { + log.error("#-splus::refreshToken::::Exception :" + e.getMessage()); + resData.put("status", "failure"); + resData.put("balance", "0.00"); + } + + return resData; + } + + @GetMapping(value = { "/validateToken", "/ValidateToken", "/validatetoken" }, produces = MediaType.TEXT_PLAIN_VALUE) + public @ResponseBody String validateToken(HttpServletRequest request, ModelMap model) throws Exception { + log.info("#-splus::validateToken::___________________Request____________________________"); + Enumeration params = request.getParameterNames(); + while (params.hasMoreElements()) { + String name = (String) params.nextElement(); + String value = request.getParameter(name); + log.info("#-splus::validateToken::" + name + "=" + value); + } + log.info("#-splus::validateToken::___________________Request____________________________"); + + StringBuilderPlus sp = new StringBuilderPlus(); + String base64Token = URLDecoder.decode(request.getParameter("auth_token"), "UTF-8"); + // JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfo(base64Token); + + DecimalFormat formatter = new DecimalFormat("0"); + String logUsername = ""; + Map authParam = new HashMap(); + if ("F0IjoxNTE2MjM5MDIyfQ".equals(base64Token)) { + authParam.put("memberId", "007maker1"); + authParam.put("siteId", "peanuts9"); + } else if ("F0IjoxNTE1MjM3MDIyfQ".equals(base64Token)) { + authParam.put("memberId", "00Dmat02"); + authParam.put("siteId", "aplus1"); + } else { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfo(base64Token); + authParam.put("memberId", tokenInfo.getMid()); + authParam.put("siteId", tokenInfo.getSid()); + logUsername = tokenInfo.getMid(); + } + + final String LOG_PREFIX = "#-splus::validateToken::" + logUsername + ":::"; + + // 회사정보 + HashMap siteApiInfo = siteService.getSiteApiInfoByToken(authParam); + log.info(LOG_PREFIX + "siteApiInfo {}", siteApiInfo); + + if ("F0IjoxNTE2MjM5MDIyfQ".equals(base64Token)) { + authParam.put("siteIdx", 87); + } else if ("F0IjoxNTE1MjM3MDIyfQ".equals(base64Token)) { + authParam.put("siteIdx", 12); + } else { + authParam.put("siteIdx", siteApiInfo.get("siteIdx")); + } + + // 회원정보 + Member member = siteService.getMemberByToken(authParam); + + if (member == null) { + log.error(LOG_PREFIX + "Not found member..."); + sp.appendLine("error_code=-3"); + sp.append("error_message=not validateToken"); + return sp.toString(); + } else { + log.info(LOG_PREFIX + "Callback Url : " + siteApiInfo.get("siteCbUrl") + "/balance/sports"); + JSONObject members = new JSONObject(); + members.put("userId", authParam.get("memberId").toString()); + + // 회원 머니 + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/json"); + header.add("Accept", "application/json"); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + + ResponseEntity responseEntity = webClient.post() + .uri(siteApiInfo.get("siteCbUrl") + "/balance/sports") + .headers(h -> h.addAll(header)) + .bodyValue(members.toString()) + .retrieve() + .toEntity(String.class) + .block(); + + log.info(LOG_PREFIX + "status code : {}", responseEntity.getStatusCode()); + log.info(LOG_PREFIX + "body: {}", responseEntity.getBody()); + + org.codehaus.jettison.json.JSONObject resData = new org.codehaus.jettison.json.JSONObject( + responseEntity.getBody()); + sp.appendLine("error_code=0"); + sp.appendLine("error_message=OK"); + // sp.appendLine("balance="+formatter.format(new + // BigDecimal(resData.getDouble("balance")*0.01))); + sp.appendLine("balance=" + formatter.format(new BigDecimal(resData.getDouble("balance")))); + sp.appendLine("cust_id=" + siteApiInfo.get("siteIdxHex").toString() + member.getMemberId()); + sp.appendLine("cust_login=" + member.getMemberNick()); + sp.appendLine("city=KR"); + sp.appendLine("country=KR"); + sp.append("currency_code=KRW"); + } + siteService.insertToken(base64Token); + // model.put("resultStr", returnString); + + log.info(LOG_PREFIX + "Response: " + sp.toString()); + return sp.toString(); + // 활용한 응답 생성; + } + + // 베팅 예약 크레딧 차람 + @RequestMapping(value = "/reserve", produces = MediaType.TEXT_PLAIN_VALUE) + public @ResponseBody String reserve(HttpServletRequest request, @RequestBody(required = false) String parambody) + throws Exception { + log.info("#-splus::reserve::___________________Request____________________________"); + Enumeration params = request.getParameterNames(); + while (params.hasMoreElements()) { + String name = (String) params.nextElement(); + String value = request.getParameter(name); + log.info("#-splus::reserve::" + name + "=" + value); + } + log.info("#-splus::reserve::___________________Request____________________________"); + + HashMap splusParam = new HashMap(); + + StringBuilderPlus sp = new StringBuilderPlus(); + String cust_id = URLDecoder.decode(request.getParameter("cust_id"), "UTF-8"); + String reserve_id = URLDecoder.decode(request.getParameter("reserve_id"), "UTF-8"); + String amountStr = URLDecoder.decode(request.getParameter("amount"), "UTF-8"); + String agent_id = URLDecoder.decode(request.getParameter("agent_id"), "UTF-8"); + String customer_id = URLDecoder.decode(request.getParameter("customer_id"), "UTF-8"); + String memberId = cust_id.substring(3, cust_id.length()); + final String LOG_PREFIX = "#-splus::reserve::" + memberId + ":::"; + + DecimalFormat formatter = new DecimalFormat("0"); + Map trxParam = new HashMap(); + trxParam.put("tranType", "reserve"); + trxParam.put("cust_id", cust_id); + trxParam.put("reserve_id", reserve_id); + trxParam.put("amount", amountStr); + trxParam.put("agent_id", agent_id); + trxParam.put("customer_id", cust_id); + + org.json.JSONObject paramjson = new org.json.JSONObject(); + + try { + log.info(LOG_PREFIX+ "parambody {}", parambody); + paramjson = XML.toJSONObject(parambody); + log.info(LOG_PREFIX+ "BF::parambody {}", paramjson.toString()); + + try { + // 한글 치환 + org.json.JSONObject bets = paramjson.getJSONObject("Bets"); + org.json.JSONObject bet = bets.getJSONObject("Bet"); + // 싱글 베팅 + if (bet.has("Lines")) { + org.json.JSONArray lines = bet.getJSONArray("Lines"); + for (int i = 0; i < lines.length(); i++) { + org.json.JSONObject line = lines.getJSONObject(i); + String homeTeam = line.getString("HomeTeam"); + String awayTeam = line.getString("AwayTeam"); + String leagueName = line.getString("LeagueName"); + + homeTeam = siteService.getKorName("T", homeTeam); + awayTeam = siteService.getKorName("T", awayTeam); + leagueName = siteService.getKorName("L", leagueName); + + line.put("HomeTeamKor", homeTeam); + line.put("AwayTeamKor", awayTeam); + line.put("LeagueNameKor", leagueName); + } + } else { + String homeTeam = bet.getString("HomeTeam"); + String awayTeam = bet.getString("AwayTeam"); + String leagueName = bet.getString("LeagueName"); + + homeTeam = siteService.getKorName("T", homeTeam); + awayTeam = siteService.getKorName("T", awayTeam); + leagueName = siteService.getKorName("L", leagueName); + + bet.put("HomeTeamKor", homeTeam); + bet.put("AwayTeamKor", awayTeam); + bet.put("LeagueNameKor", leagueName); + } + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::001"); + log.error(LOG_PREFIX+ "tranERR {}", e.toString()); + } + trxParam.put("data", paramjson.toString()); + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::002"); + log.error(LOG_PREFIX+ "error {}", e.getMessage()); + } + + log.info(LOG_PREFIX+ "AF::parambody {}", paramjson.toString()); + + // 사이트정보 + HashMap ssParam = new HashMap(); + ssParam.put("siteIdx", Integer.parseInt(cust_id.substring(0, 3), 16)); + ssParam.put("memberId", cust_id.substring(3, cust_id.length())); + HashMap siteApiInfo = siteService.getSiteApiInfo(ssParam); + + if (siteApiInfo == null) { + sp.appendLine("error_code=-2"); + sp.append("CustomerNotFound"); + return sp.toString(); + } + + String siteId = siteApiInfo.get("siteId").toString(); + + Map authParam = new HashMap(); + authParam.put("memberId", memberId); + authParam.put("siteId", siteId); + + // 회사정보 + + log.info(LOG_PREFIX+ "siteApiInfo {}", siteApiInfo); + authParam.put("siteIdx", siteApiInfo.get("siteIdx")); + + // 회원정보 + Member member = siteService.getMemberByToken(authParam); + if (member == null) { + log.error(LOG_PREFIX+ "Exception::Not found user"); + sp.appendLine("error_code=-2"); + sp.append("CustomerNotFound"); + return sp.toString(); + } + + int siteIdx = Integer.parseInt(siteApiInfo.get("siteIdx").toString()); + String refId = siteId + reserve_id; + Date dt = new Date(); + String trxId = "" + siteIdx + dt.getTime() + "0"; + trxParam.put("refId", refId); + trxParam.put("trx_id", trxId); + try { + siteService.insertSplusTran(trxParam); + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::003"); + log.error(LOG_PREFIX+ "reserve2 ERROR {}", e.getMessage()); + } + + double balance = getBalnce(LOG_PREFIX, siteApiInfo.get("siteCbUrl").toString(), memberId); + long targetSiteCredit = siteService.getSiteCredit(siteApiInfo.get("siteId").toString()); + double amount = Double.parseDouble(amountStr); + + log.info(LOG_PREFIX+ "targetSiteCredit < amount {}, {}", targetSiteCredit, amount); + if (targetSiteCredit < amount && amount > 0) { + log.error(LOG_PREFIX+ "Exception::크레딧 부족"); + sp.appendLine("error_code=-4"); + sp.appendLine("error_message=InsufficientFunds"); + return sp.toString(); + } + + if (balance < amount && amount > 0) { + log.error(LOG_PREFIX+ "Exception::유저잔액 부족"); + sp.appendLine("error_code=-4"); + sp.appendLine("error_message=InsufficientFunds"); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.appendLine("trx_id=" + trxId); + return sp.toString(); + } + + // 최대베팅액 (userMaxBet 우선 적용) + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", member.getMemberId()); + sParam.put("vendorIdx", 83); + long maxBet = siteService.getSiteMaxBet(sParam); + + // userMaxBet 조회 + long userMaxBet = 0; + Long userMaxBetObj = siteService.getUserMaxBet(sParam); + if(userMaxBetObj != null) { + userMaxBet = userMaxBetObj; + } + + // 최종 maxBet 결정: userMaxBet이 0이면 siteMaxBet 사용, 0이 아니면 userMaxBet 사용 + long finalMaxBet = (userMaxBet > 0) ? userMaxBet : maxBet; + log.info(LOG_PREFIX+ "MaxBet Info - siteMaxBet: " + maxBet + ", userMaxBet: " + userMaxBet + ", finalMaxBet: " + finalMaxBet); + + if (amount > finalMaxBet) { + log.error(LOG_PREFIX+ "Exception::최대 베팅금 초과 - finalMaxBet: " + finalMaxBet); + sp.appendLine("error_code=-10"); + sp.appendLine("error_message= max bet limit - overBet"); + return sp.toString(); + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", refId + "#R"); + tranParam.put("refId", refId); + tranParam.put("siteIdx", siteApiInfo.get("siteIdx")); + tranParam.put("siteId", siteId); + tranParam.put("completed", true); + tranParam.put("memberIdx", member.getMemberIdx()); + tranParam.put("memberId", member.getMemberId()); + tranParam.put("vendorCetegory", "SPORT"); + tranParam.put("vendorIdx", 83); + tranParam.put("vendorCode", "splus"); + tranParam.put("vendorTranKey", reserve_id + "#R"); + tranParam.put("gameType", ""); + tranParam.put("gameId", ""); + tranParam.put("gameIdx", ""); + tranParam.put("tranType", "debit"); + tranParam.put("depositAmt", amount); + tranParam.put("creditAmt", "0"); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", ""); + siteService.commonBetinsert(tranParam); + + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/json"); + header.add("Accept", "application/json"); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + JSONObject debit = new JSONObject(); + double fakeAmount = amount;// *100; + debit.put("betId", refId); + debit.put("tranId", refId + "#R"); + + debit.put("userId", member.getMemberId()); + debit.put("vendorIdx", 83); + debit.put("vendorKey", "SP2"); + debit.put("vendor", "splus"); + debit.put("gameIdx", 1); + debit.put("gameKey", ""); + debit.put("gameType", ""); + debit.put("gameId", ""); + debit.put("tranType", "debit"); + debit.put("debit", fakeAmount); + debit.put("credit", 0); + debit.put("isCancel", 0); + debit.put("isBonus", 0); + debit.put("decYn", "Y"); + + HashMap detailMap = new Gson().fromJson(paramjson.toString(), HashMap.class); + debit.put("status", "bet"); + debit.put("detail", detailMap); + + log.info(LOG_PREFIX+ "Callback Request: "+debit.toString()); + + ResponseEntity responseEntity = webClient.post() + .uri(siteApiInfo.get("siteCbUrl") + "/changebalance/sports") + .headers(h -> h.addAll(header)) + .bodyValue(debit.toString()) + .retrieve() + .toEntity(String.class) + .block(); + + org.codehaus.jettison.json.JSONObject resData = new org.codehaus.jettison.json.JSONObject( + responseEntity.getBody()); + + log.info(LOG_PREFIX+ "Callback Response: "+resData.toString()); + + if (resData.getLong("result_code") == 0) { + trxParam.put("tranId", tranParam.get("tranId").toString()); + trxParam.put("resData", resData.toString()); + trxParam.put("cbResultCode", resData.get("result_code").toString()); + siteService.updateSplusTran(trxParam); + + sp.appendLine("error_code=0"); + sp.appendLine("error_message=No Error "); + // sp.appendLine("balance="+formatter.format(new + // BigDecimal(resData.getDouble("balance") * 0.01))); + sp.appendLine("balance=" + formatter.format(new BigDecimal(resData.getDouble("balance")))); + sp.appendLine("trx_id=" + trxId); + tranParam.put("balance", resData.getDouble("balance")); + int res = siteService.updateCbApi(tranParam); + + splusService.insertSplus(tranParam, paramjson); + + } else { + log.info(LOG_PREFIX+ "Callback Error: "+resData.toString()); + sp.appendLine("error_code=-99"); + sp.appendLine("error_message=error"); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.appendLine("trx_id=" + trxId); + } + + log.info(LOG_PREFIX + "Response: " + sp.toString()); + return sp.toString(); // 활용한 응답 생성; + } + + // 베팅 예약 취소 크레딧 복구 + @GetMapping(value = { "/cancelReserve", "/cancelreserve" }, produces = MediaType.TEXT_PLAIN_VALUE) + public @ResponseBody String cancelReserve(HttpServletRequest request) throws Exception { + log.info("#-splus::cancelReserve::___________________Request____________________________"); + Enumeration params = request.getParameterNames(); + while (params.hasMoreElements()) { + String name = (String) params.nextElement(); + String value = request.getParameter(name); + log.info("#-splus::cancelReserve::" + name + "=" + value); + } + log.info("#-splus::cancelReserve::___________________Request____________________________"); + + DecimalFormat formatter = new DecimalFormat("0"); + StringBuilderPlus sp = new StringBuilderPlus(); + String cust_id = URLDecoder.decode(request.getParameter("cust_id"), "UTF-8"); + String reserve_id = URLDecoder.decode(request.getParameter("reserve_id"), "UTF-8"); + String agent_id = URLDecoder.decode(request.getParameter("agent_id"), "UTF-8"); + String customer_id = URLDecoder.decode(request.getParameter("customer_id"), "UTF-8"); + String memberId = cust_id.substring(3, cust_id.length()); + final String LOG_PREFIX = "#-splus::cancelReserve::" + memberId + ":::"; + + Map trxParam = new HashMap(); + + trxParam.put("tranType", "cancelReserve"); + trxParam.put("cust_id", cust_id); + trxParam.put("reserve_id", reserve_id); + trxParam.put("agent_id", agent_id); + trxParam.put("customer_id", customer_id); + + // 사이트정보 + HashMap ssParam = new HashMap(); + ssParam.put("siteIdx", Integer.parseInt(cust_id.substring(0, 3), 16)); + ssParam.put("memberId", cust_id.substring(3, cust_id.length())); + + HashMap siteApiInfo = siteService.getSiteApiInfo(ssParam); + if (siteApiInfo == null) { + log.error(LOG_PREFIX+ "Error:: siteApiInfo null"); + sp.appendLine("error_code=-2"); + sp.append("CustomerNotFound"); + return sp.toString(); + } + + String siteId = siteApiInfo.get("siteId").toString(); + Map authParam = new HashMap(); + authParam.put("memberId", memberId); + authParam.put("siteId", siteId); + + // 회사정보 + log.info(LOG_PREFIX+ "siteApiInfo {}", siteApiInfo); + authParam.put("siteIdx", siteApiInfo.get("siteIdx")); + + // 회원정보 + Member member = siteService.getMemberByToken(authParam); + if (member == null) { + log.error(LOG_PREFIX+ "Error:: Member null"); + sp.appendLine("error_code=-2"); + sp.append("CustomerNotFound"); + return sp.toString(); + } + int siteIdx = Integer.parseInt(siteApiInfo.get("siteIdx").toString()); + String refId = siteId + reserve_id; + Date dt = new Date(); + String trxId = "" + siteIdx + dt.getTime() + "9"; + trxParam.put("refId", refId); + trxParam.put("trx_id", trxId); + + double balance = getBalnce(LOG_PREFIX, siteApiInfo.get("siteCbUrl").toString(), memberId); + long targetSiteCredit = siteService.getSiteCredit(siteApiInfo.get("siteId").toString()); + + log.info(LOG_PREFIX+ "refId : "+refId + "#R"); + double amount = siteService.getBetDepositAmt(refId + "#R"); + log.info(LOG_PREFIX+ "amount :" + amount); + double amountCanceld = siteService.getBetDepositAmt(refId + "#C"); + trxParam.put("amount", amount); + siteService.insertSplusTran(trxParam); + + if (amount == 0) { + log.error(LOG_PREFIX+ "Error:: amount 0"); + sp.appendLine("error_code=0"); + sp.appendLine("error_message=ReserveID not exists"); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + return sp.toString(); + } + + if (amountCanceld > 0) { + log.error(LOG_PREFIX+ "Error:: amountCanceld > 0"); + sp.appendLine("error_code=0"); + sp.appendLine("error_message= alrealdy Canceld "); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + return sp.toString(); + } + + log.info(LOG_PREFIX+ "amount:{}, balance:{}", amount, balance); + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", refId + "#C"); + tranParam.put("refId", refId); + tranParam.put("siteIdx", siteApiInfo.get("siteIdx")); + tranParam.put("siteId", siteId); + tranParam.put("completed", true); + tranParam.put("memberIdx", member.getMemberIdx()); + tranParam.put("memberId", member.getMemberId()); + tranParam.put("vendorCetegory", "SPORT"); + tranParam.put("vendorIdx", 83); + tranParam.put("vendorCode", "splus"); + tranParam.put("vendorTranKey", reserve_id + "#C"); + tranParam.put("gameType", ""); + tranParam.put("gameId", ""); + tranParam.put("gameIdx", ""); + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + tranParam.put("isCancel", "Y"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", ""); + siteService.commonBetinsert(tranParam); + + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/json"); + header.add("Accept", "application/json"); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + JSONObject debit = new JSONObject(); + double fakeAmount = amount;// *100; + debit.put("betId", refId); + debit.put("tranId", refId + "#C"); + debit.put("userId", member.getMemberId()); + debit.put("vendorIdx", 83); + debit.put("vendorKey", "SP2"); + debit.put("vendor", "splus"); + debit.put("gameIdx", 1); + debit.put("gameKey", ""); + debit.put("gameType", ""); + debit.put("gameId", ""); + debit.put("tranType", "credit"); + debit.put("debit", 0); + debit.put("credit", fakeAmount); + debit.put("isCancel", 1); + debit.put("isBonus", 0); + debit.put("status", "betCancel"); + debit.put("decYn", "Y"); + + log.info(LOG_PREFIX+ "Callback Request: "+debit.toString()); + + ResponseEntity responseEntity = webClient.post() + .uri(siteApiInfo.get("siteCbUrl") + "/changebalance/sports") + .headers(h -> h.addAll(header)) + .bodyValue(debit.toString()) + .retrieve() + .toEntity(String.class) + .block(); + + org.codehaus.jettison.json.JSONObject resData = new org.codehaus.jettison.json.JSONObject( + responseEntity.getBody()); + log.info(LOG_PREFIX+ "Callback Response: "+resData.toString()); + + if (resData.getLong("result_code") == 0) { + sp.appendLine("error_code=0"); + sp.appendLine("error_message=No Error "); + // sp.appendLine("balance="+formatter.format(new + // BigDecimal(resData.getDouble("balance") * 0.01))); + sp.appendLine("balance=" + formatter.format(new BigDecimal(resData.getDouble("balance")))); + sp.appendLine("trx_id=" + trxId); + + tranParam.put("balance", resData.getDouble("balance")); + int res = siteService.updateCbApi(tranParam); + } else { + log.error(LOG_PREFIX+ "Callback Error::" + resData.toString()); + sp.appendLine("error_code=0"); + sp.appendLine("error_message=error"); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.appendLine("trx_id=" + trxId); + } + + trxParam.put("tranId", tranParam.get("tranId").toString()); + trxParam.put("resData", resData.toString()); + + siteService.updateSplusTran(trxParam); + splusService.cancelSplus(tranParam); + + log.info(LOG_PREFIX + "Response: " + sp.toString()); + return sp.toString(); // 활용한 응답 생성; + } + + + // 뭔지 잘 모르겠슴 + @GetMapping(value = { "/commitReserve", "/commitreserve" }, produces = MediaType.TEXT_PLAIN_VALUE) + public @ResponseBody String commitReserve(HttpServletRequest request) throws Exception { + log.info("#-splus::commitReserve::___________________Request____________________________"); + Enumeration params = request.getParameterNames(); + while (params.hasMoreElements()) { + String name = (String) params.nextElement(); + String value = request.getParameter(name); + log.info("#-splus::commitReserve::" + name + "=" + value); + } + log.info("#-splus::commitReserve::___________________Request____________________________"); + + DecimalFormat formatter = new DecimalFormat("0"); + StringBuilderPlus sp = new StringBuilderPlus(); + String cust_id = URLDecoder.decode(request.getParameter("cust_id"), "UTF-8"); + String reserve_id = URLDecoder.decode(request.getParameter("reserve_id"), "UTF-8"); + String agent_id = URLDecoder.decode(request.getParameter("agent_id"), "UTF-8"); + String customer_id = URLDecoder.decode(request.getParameter("customer_id"), "UTF-8"); + String purchase_id = URLDecoder.decode(request.getParameter("purchase_id"), "UTF-8"); + String memberId = cust_id.substring(3, cust_id.length()); + final String LOG_PREFIX = "#-splus::commitReserve::" + memberId + ":::"; + + Map trxParam = new HashMap(); + + trxParam.put("tranType", "commitReserve"); + trxParam.put("cust_id", cust_id); + trxParam.put("reserve_id", reserve_id); + trxParam.put("agent_id", agent_id); + trxParam.put("customer_id", customer_id); + trxParam.put("purchase_id", purchase_id); + + // 사이트정보 + HashMap ssParam = new HashMap(); + ssParam.put("siteIdx", Integer.parseInt(cust_id.substring(0, 3), 16)); + ssParam.put("memberId", cust_id.substring(3, cust_id.length())); + + HashMap siteApiInfo = siteService.getSiteApiInfo(ssParam); + if (siteApiInfo == null) { + log.error(LOG_PREFIX+ "Error:: siteApiInfo null"); + sp.appendLine("error_code=0"); + sp.append("CustomerNotFound"); + return sp.toString(); + } + + String siteId = siteApiInfo.get("siteId").toString(); + Map authParam = new HashMap(); + authParam.put("memberId", memberId); + authParam.put("siteId", siteId); + + // 회사정보 + log.info(LOG_PREFIX + "siteApiInfo {}", siteApiInfo); + authParam.put("siteIdx", siteApiInfo.get("siteIdx")); + + // 회원정보 + Member member = siteService.getMemberByToken(authParam); + if (member == null) { + log.error(LOG_PREFIX+ "Error:: member null"); + sp.appendLine("error_code=0"); + sp.append("CustomerNotFound"); + return sp.toString(); + } + + int siteIdx = Integer.parseInt(siteApiInfo.get("siteIdx").toString()); + String refId = siteId + reserve_id; + Date dt = new Date(); + String trxId = "" + siteIdx + dt.getTime() + "1"; + trxParam.put("refId", refId); + trxParam.put("trx_id", trxId); + + double amount = siteService.getBetDepositAmt(refId + "#R"); + double gap = siteService.getBetGapAmt(purchase_id); + double balance = getBalnce(LOG_PREFIX, siteApiInfo.get("siteCbUrl").toString(), memberId); + + if (amount == 0) { + log.error(LOG_PREFIX+ "Error:: amount 0"); + sp.appendLine("error_code=0"); + sp.appendLine("error_message=ReserveID not exists"); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + return sp.toString(); + } + + if (gap > 0 && gap < amount) { + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", refId + "#CR"); + tranParam.put("refId", refId); + tranParam.put("siteIdx", siteApiInfo.get("siteIdx")); + tranParam.put("siteId", siteId); + tranParam.put("completed", true); + tranParam.put("memberIdx", member.getMemberIdx()); + tranParam.put("memberId", member.getMemberId()); + tranParam.put("vendorCetegory", "SPORT"); + tranParam.put("vendorIdx", 83); + tranParam.put("vendorCode", "splus"); + tranParam.put("vendorTranKey", purchase_id + "#CR"); + tranParam.put("gameType", ""); + tranParam.put("gameId", ""); + tranParam.put("gameIdx", ""); + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", gap); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", ""); + siteService.commonBetinsert(tranParam); + + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/json"); + header.add("Accept", "application/json"); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + JSONObject debit = new JSONObject(); + double fakeAmount = gap;// *100; + debit.put("betId", refId); + debit.put("tranId", refId + "#CR"); + debit.put("userId", member.getMemberId()); + debit.put("vendorIdx", 83); + debit.put("vendorKey", "SP2"); + debit.put("vendor", "splus"); + debit.put("gameIdx", 1); + debit.put("gameKey", ""); + debit.put("gameType", ""); + debit.put("gameId", ""); + debit.put("tranType", "credit"); + debit.put("debit", 0); + debit.put("credit", fakeAmount); + debit.put("isCancel", 0); + debit.put("isBonus", 0); + debit.put("decYn", "Y"); + debit.put("status", "commitReserve"); + debit.put("detail", "commitReserve"); + + log.info(LOG_PREFIX+ "Callback Request: "+debit.toString()); + + ResponseEntity responseEntity = webClient.post() + .uri(siteApiInfo.get("siteCbUrl") + "/changebalance/sports") + .headers(h -> h.addAll(header)) + .bodyValue(debit.toString()) + .retrieve() + .toEntity(String.class) + .block(); + + org.codehaus.jettison.json.JSONObject resData = new org.codehaus.jettison.json.JSONObject( + responseEntity.getBody()); + log.info(LOG_PREFIX+ "Callback Response: "+resData.toString()); + + balance = resData.getDouble("balance");// *0.01; + + tranParam.put("balance", resData.getDouble("balance")); + int res = siteService.updateCbApi(tranParam); + + } + + trxParam.put("amount", gap); + siteService.insertSplusTran(trxParam); + + sp.appendLine("error_code=0"); + sp.appendLine("error_message=No Error "); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.appendLine("trx_id=" + trxId); + + log.info(LOG_PREFIX + "Response: " + sp.toString()); + return sp.toString(); // 활용한 응답 생성; + } + + // 뭔지 잘 모르겠슴 + @RequestMapping(value = { "/debitReserve", "/debitreserve" }, produces = MediaType.TEXT_PLAIN_VALUE) + public @ResponseBody String debitReserve(HttpServletRequest request, + @RequestBody(required = false) String parambody) throws Exception { + log.info("#-splus::debitReserve::___________________Request____________________________"); + Enumeration params = request.getParameterNames(); + while (params.hasMoreElements()) { + String name = (String) params.nextElement(); + String value = request.getParameter(name); + log.info("#-splus::debitReserve::" + name + "=" + value); + } + log.info("#-splus::debitReserve::___________________Request____________________________"); + + DecimalFormat formatter = new DecimalFormat("0"); + StringBuilderPlus sp = new StringBuilderPlus(); + String cust_id = URLDecoder.decode(request.getParameter("cust_id"), "UTF-8"); + String reserve_id = URLDecoder.decode(request.getParameter("reserve_id"), "UTF-8"); + String req_id = URLDecoder.decode(request.getParameter("req_id"), "UTF-8"); + String amountStr = URLDecoder.decode(request.getParameter("amount"), "UTF-8"); + String agent_id = URLDecoder.decode(request.getParameter("agent_id"), "UTF-8"); + String customer_id = URLDecoder.decode(request.getParameter("customer_id"), "UTF-8"); + String purchase_id = URLDecoder.decode(request.getParameter("purchase_id"), "UTF-8"); + String memberId = cust_id.substring(3, cust_id.length()); + final String LOG_PREFIX = "#-splus::debitReserve::" + memberId + ":::"; + + Map trxParam = new HashMap(); + trxParam.put("tranType", "debitReserve"); + trxParam.put("cust_id", cust_id); + trxParam.put("req_id", req_id); + trxParam.put("reserve_id", reserve_id); + trxParam.put("amount", amountStr); + trxParam.put("agent_id", agent_id); + trxParam.put("customer_id", customer_id); + trxParam.put("purchase_id", purchase_id); + try { + log.info(LOG_PREFIX+ "parambody {}", parambody); + org.json.JSONObject paramjson = XML.toJSONObject(parambody); + log.info(LOG_PREFIX+ "parambody {}", paramjson.toString()); + trxParam.put("data", paramjson.toString()); + } catch (Exception e) { + log.info(LOG_PREFIX+ "error {}", e.getMessage()); + } + + // 사이트정보 + HashMap ssParam = new HashMap(); + ssParam.put("siteIdx", Integer.parseInt(cust_id.substring(0, 3), 16)); + ssParam.put("memberId", cust_id.substring(3, cust_id.length())); + HashMap siteApiInfo = siteService.getSiteApiInfo(ssParam); + if (siteApiInfo == null) { + sp.appendLine("error_code=0"); + sp.append("CustomerNotFound"); + return sp.toString(); + } + + String siteId = siteApiInfo.get("siteId").toString(); + Map authParam = new HashMap(); + authParam.put("memberId", memberId); + authParam.put("siteId", siteId); + + // 회사정보 + log.info("siteApiInfo {}", siteApiInfo); + authParam.put("siteIdx", siteApiInfo.get("siteIdx")); + + // 회원정보 + Member member = siteService.getMemberByToken(authParam); + if (member == null) { + sp.appendLine("error_code=0"); + sp.append("CustomerNotFound"); + return sp.toString(); + } + + int siteIdx = Integer.parseInt(siteApiInfo.get("siteIdx").toString()); + String refId = siteId + reserve_id; + Date dt = new Date(); + String trxId = "" + siteIdx + dt.getTime() + "1"; + trxParam.put("refId", refId); + trxParam.put("trx_id", trxId); + + int deReverseCnt = splusService.getDeReverseCnt(trxParam); + if (deReverseCnt == 0) { + siteService.insertSplusTran(trxParam); + siteService.updatesPurchaseId(trxParam); + } + double balance = 0.0; + try { + String cbData = siteService.getCbData(reserve_id); + org.codehaus.jettison.json.JSONObject cbDataJson = new org.codehaus.jettison.json.JSONObject(cbData); + balance = cbDataJson.getDouble("balance");// *0.01; + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::001"); + log.error(LOG_PREFIX+ "Exception::" + e.getMessage()); + balance = getBalnce(LOG_PREFIX, siteApiInfo.get("siteCbUrl").toString(), memberId); + } + + + + // 구매아이디 보내주기 + try { + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/json"); + header.add("Accept", "application/json"); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + JSONObject debit = new JSONObject(); + + debit.put("betId", refId); + debit.put("purchaseId", purchase_id); + + log.info(LOG_PREFIX+ "Callback Request: "+debit.toString()); + + ResponseEntity responseEntity = webClient.post() + .uri(siteApiInfo.get("siteCbUrl") + "/purchaseId") + .headers(h -> h.addAll(header)) + .bodyValue(debit.toString()) + .retrieve() + .toEntity(String.class) + .block(); + + org.codehaus.jettison.json.JSONObject resData = new org.codehaus.jettison.json.JSONObject( + responseEntity.getBody()); + log.info(LOG_PREFIX+ "Callback Response: "+resData.toString()); + + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::002"); + log.error(LOG_PREFIX+ "Exception::" + e.getMessage()); + } + + sp.appendLine("error_code=0"); + sp.appendLine("error_message=No Error "); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.appendLine("trx_id=" + trxId); + + log.info(LOG_PREFIX + "Response: " + sp.toString()); + return sp.toString(); // 활용한 응답 생성; + } + + + // 베팅 예약 크레딧 차람 + @RequestMapping(value = { "/debitCustomer", "/debitcustomer" }, produces = MediaType.TEXT_PLAIN_VALUE) + public @ResponseBody String debitCustomer(HttpServletRequest request, + @RequestBody(required = false) String parambody) throws Exception { + log.info("#-splus::debitCustomer::___________________Request____________________________"); + Enumeration params = request.getParameterNames(); + while (params.hasMoreElements()) { + String name = (String) params.nextElement(); + String value = request.getParameter(name); + log.info("#-splus::debitCustomer::" + name + "=" + value); + } + log.info("#-splus::debitCustomer::___________________Request____________________________"); + + DecimalFormat formatter = new DecimalFormat("0"); + StringBuilderPlus sp = new StringBuilderPlus(); + String cust_id = URLDecoder.decode(request.getParameter("cust_id"), "UTF-8"); + String req_id = URLDecoder.decode(request.getParameter("req_id"), "UTF-8"); + String purchase_id = URLDecoder.decode(request.getParameter("purchase_id"), "UTF-8"); + String amountStr = URLDecoder.decode(request.getParameter("amount"), "UTF-8"); + String agent_id = URLDecoder.decode(request.getParameter("agent_id"), "UTF-8"); + String customer_id = URLDecoder.decode(request.getParameter("customer_id"), "UTF-8"); + String memberId = cust_id.substring(3, cust_id.length()); + final String LOG_PREFIX = "#-splus::debitCustomer::" + memberId + ":::"; + + Map trxParam = new HashMap(); + trxParam.put("tranType", "debitCustomer"); + trxParam.put("cust_id", cust_id); + trxParam.put("req_id", req_id); + trxParam.put("purchase_id", purchase_id); + trxParam.put("amount", amountStr); + trxParam.put("agent_id", agent_id); + trxParam.put("customer_id", cust_id); + + org.json.JSONObject paramjson = new org.json.JSONObject(); + try { + log.info(LOG_PREFIX+ "parambody {}", parambody); + paramjson = XML.toJSONObject(parambody); + log.info(LOG_PREFIX+ "BF::parambody {}", paramjson.toString()); + + try { + // 한글 치환 + org.json.JSONObject credits = paramjson.getJSONObject("Credit"); + org.json.JSONObject purchases = credits.getJSONObject("Purchases"); + org.json.JSONObject purchase = purchases.getJSONObject("Purchase"); + org.json.JSONObject selections = purchase.getJSONObject("Selections"); + // 싱글 베팅 + + org.json.JSONObject selection = selections.getJSONObject("Selection"); + if (selection == null) { + + org.json.JSONArray selectionArray = selections.getJSONArray("Selection"); + for (int i = 0; i < selectionArray.length(); i++) { + org.json.JSONObject line = selectionArray.getJSONObject(i); + String homeTeam = line.getString("HomeTeam"); + String awayTeam = line.getString("AwayTeam"); + String leagueName = line.getString("LeagueName"); + + homeTeam = siteService.getKorName("T", homeTeam); + awayTeam = siteService.getKorName("T", awayTeam); + leagueName = siteService.getKorName("L", leagueName); + + line.put("HomeTeamKor", homeTeam); + line.put("AwayTeamKor", awayTeam); + line.put("LeagueNameKor", leagueName); + } + + } else { + String homeTeam = selection.getString("HomeTeam"); + String awayTeam = selection.getString("AwayTeam"); + String leagueName = selection.getString("LeagueName"); + + homeTeam = siteService.getKorName("T", homeTeam); + awayTeam = siteService.getKorName("T", awayTeam); + leagueName = siteService.getKorName("L", leagueName); + + selection.put("HomeTeamKor", homeTeam); + selection.put("AwayTeamKor", awayTeam); + selection.put("LeagueNameKor", leagueName); + + } + + } catch (Exception e) { + log.error(LOG_PREFIX+ "tranERR"); + } + trxParam.put("data", paramjson.toString()); + log.info(LOG_PREFIX+ "AF::parambody {}", paramjson.toString()); + } catch (Exception e) { + log.info(LOG_PREFIX+ "error {}", e.getMessage()); + } + + // 사이트정보 + HashMap ssParam = new HashMap(); + ssParam.put("siteIdx", Integer.parseInt(cust_id.substring(0, 3), 16)); + ssParam.put("memberId", cust_id.substring(3, cust_id.length())); + HashMap siteApiInfo = siteService.getSiteApiInfo(ssParam); + if (siteApiInfo == null) { + sp.appendLine("error_code=0"); + sp.append("CustomerNotFound"); + return sp.toString(); + } + + String siteId = siteApiInfo.get("siteId").toString(); + Map authParam = new HashMap(); + authParam.put("memberId", memberId); + authParam.put("siteId", siteId); + + // 회사정보 + log.info(LOG_PREFIX+ "siteApiInfo {}", siteApiInfo); + authParam.put("siteIdx", siteApiInfo.get("siteIdx")); + + // 회원정보 + Member member = siteService.getMemberByToken(authParam); + if (member == null) { + sp.appendLine("error_code=0"); + sp.append("CustomerNotFound"); + return sp.toString(); + } + + int siteIdx = Integer.parseInt(siteApiInfo.get("siteIdx").toString()); + String reserveId = siteService.getRefIdByPurchaseId(purchase_id); + String refId = siteId + reserveId; + Date dt = new Date(); + String trxId = "" + siteIdx + dt.getTime() + "3"; + trxParam.put("trxId", trxId); + trxParam.put("refId", refId + "#DC"); + + siteService.insertSplusTran(trxParam); + if (member == null) { + sp.appendLine("error_code=-2"); + sp.append("error_message=not validateToken"); + + return sp.toString(); + } + double balance = getBalnce(LOG_PREFIX, siteApiInfo.get("siteCbUrl").toString(), memberId); + long targetSiteCredit = siteService.getSiteCredit(siteApiInfo.get("siteId").toString()); + double amount = Double.parseDouble(amountStr); + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", refId + "#DC"); + tranParam.put("refId", refId + "#DC"); + tranParam.put("siteIdx", siteApiInfo.get("siteIdx")); + tranParam.put("siteId", siteId); + tranParam.put("completed", true); + tranParam.put("memberIdx", member.getMemberIdx()); + tranParam.put("memberId", member.getMemberId()); + tranParam.put("vendorCetegory", "SPORT"); + tranParam.put("vendorIdx", 83); + tranParam.put("vendorCode", "splus"); + tranParam.put("vendorTranKey", purchase_id + "#DC"); + tranParam.put("gameType", ""); + tranParam.put("gameId", ""); + tranParam.put("gameIdx", ""); + tranParam.put("tranType", "debit"); + tranParam.put("depositAmt", amount); + tranParam.put("creditAmt", "0"); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", ""); + siteService.commonBetinsert(tranParam); + + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/json"); + header.add("Accept", "application/json"); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + JSONObject debit = new JSONObject(); + double fakeAmount = amount;// *100; + debit.put("betId", refId + "#DC"); + debit.put("tranId", refId + "#DC"); + debit.put("userId", member.getMemberId()); + debit.put("vendorIdx", 83); + debit.put("vendorKey", "SP2"); + debit.put("vendor", "splus"); + debit.put("gameIdx", 1); + debit.put("gameKey", ""); + debit.put("gameType", ""); + debit.put("gameId", ""); + debit.put("tranType", "debit"); + debit.put("debit", fakeAmount); + debit.put("credit", 0); + debit.put("isCancel", 0); + debit.put("isBonus", 0); + debit.put("minusBalanceYn", "Y"); + HashMap detailMap = new Gson().fromJson(paramjson.toString(), HashMap.class); + debit.put("status", "debitCustomer"); + debit.put("detail", detailMap); + + log.info(LOG_PREFIX+ "Callback Request: "+debit.toString()); + + ResponseEntity responseEntity = webClient.post() + .uri(siteApiInfo.get("siteCbUrl") + "/changebalance/sports") + .headers(h -> h.addAll(header)) + .bodyValue(debit.toString()) + .retrieve() + .toEntity(String.class) + .block(); + + org.codehaus.jettison.json.JSONObject resData = new org.codehaus.jettison.json.JSONObject( + responseEntity.getBody()); + log.info(LOG_PREFIX+ "Callback Response: "+resData.toString()); + + if (resData.getLong("result_code") == 0) { + sp.appendLine("error_code=0"); + sp.appendLine("error_message=No Error "); + // sp.appendLine("balance="+formatter.format(new + // BigDecimal(resData.getDouble("balance") * 0.01))); + sp.appendLine("balance=" + formatter.format(new BigDecimal(resData.getDouble("balance")))); + sp.appendLine("trx_id=" + trxId); + + tranParam.put("balance", resData.getDouble("balance")); + int res = siteService.updateCbApi(tranParam); + } else { + sp.appendLine("error_code=0"); + sp.appendLine("error_message=error"); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.appendLine("trx_id=" + trxId); + } + + trxParam.put("tranId", tranParam.get("tranId").toString()); + trxParam.put("resData", resData.toString()); + siteService.updateSplusTran(trxParam); + + log.info(LOG_PREFIX + "Response: " + sp.toString()); + return sp.toString(); // 활용한 응답 생성; + } + + private double getBalnce(String LOG_PREFIX, String cbUrl, String memId) { + LOG_PREFIX = LOG_PREFIX + "==> getBalnce::"; + double balance = 0L; + + try { + log.info(LOG_PREFIX + "Callback Url :" + cbUrl + "/balance/sports"); + JSONObject members = new JSONObject(); + members.put("userId", memId); + members.put("decYn", "Y"); + + // 회원 머니 + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/json"); + header.add("Accept", "application/json"); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + + ResponseEntity responseEntity = webClient.post() + .uri(cbUrl + "/balance/sports") + .headers(h -> h.addAll(header)) + .bodyValue(members.toString()) + .retrieve() + .toEntity(String.class) + .block(); + + log.info(LOG_PREFIX + "status code : {}", responseEntity.getStatusCode()); + log.info(LOG_PREFIX + "body: {}", responseEntity.getBody()); + org.codehaus.jettison.json.JSONObject resData = new org.codehaus.jettison.json.JSONObject( + responseEntity.getBody()); + balance = resData.getDouble("balance");// * 0.01; + + } catch (Exception e) { + log.error(LOG_PREFIX + "Exception :" + e.getMessage()); + } + + return balance; + } + + // 베팅 예약 크레딧 차람 + @RequestMapping(value = { "/creditCustomer", "/creditcustomer" }, produces = MediaType.TEXT_PLAIN_VALUE) + public @ResponseBody String creditCustomer(HttpServletRequest request, + @RequestBody(required = false) String parambody) throws Exception { + log.info("#-splus::creditCustomer::___________________Request____________________________"); + Enumeration params = request.getParameterNames(); + while (params.hasMoreElements()) { + String name = (String) params.nextElement(); + String value = request.getParameter(name); + log.info("#-splus::creditCustomer::" + name + "=" + value); + } + log.info("#-splus::creditCustomer::___________________Request____________________________"); + + StringBuilderPlus sp = new StringBuilderPlus(); + String cust_id = URLDecoder.decode(request.getParameter("cust_id"), "UTF-8"); + String purchase_id = URLDecoder.decode(request.getParameter("purchase_id"), "UTF-8"); + String req_id = URLDecoder.decode(request.getParameter("req_id"), "UTF-8"); + String amountStr = URLDecoder.decode(request.getParameter("amount"), "UTF-8"); + String agent_id = URLDecoder.decode(request.getParameter("agent_id"), "UTF-8"); + String customer_id = URLDecoder.decode(request.getParameter("customer_id"), "UTF-8"); + String memberId = cust_id.substring(3, cust_id.length()); + final String LOG_PREFIX = "#-splus::creditCustomer::" + memberId + ":::"; + + Map trxParam = new HashMap(); + trxParam.put("tranType", "creditCustomer"); + trxParam.put("cust_id", cust_id); + trxParam.put("req_id", req_id); + trxParam.put("purchase_id", purchase_id); + trxParam.put("amount", amountStr); + trxParam.put("agent_id", agent_id); + trxParam.put("customer_id", cust_id); + + org.json.JSONObject paramjson = new org.json.JSONObject(); + try { + log.info(LOG_PREFIX+ "parambody {}", parambody); + paramjson = XML.toJSONObject(parambody); + log.info(LOG_PREFIX+ "BF::parambody {}", paramjson.toString()); + + try { + // 한글 치환 + org.json.JSONObject credits = paramjson.getJSONObject("Credit"); + org.json.JSONObject purchases = credits.getJSONObject("Purchases"); + org.json.JSONObject purchase = purchases.getJSONObject("Purchase"); + org.json.JSONObject selections = purchase.getJSONObject("Selections"); + // 싱글 베팅 + + org.json.JSONObject selection = selections.getJSONObject("Selection"); + if (selection == null) { + + org.json.JSONArray selectionArray = selections.getJSONArray("Selection"); + for (int i = 0; i < selectionArray.length(); i++) { + org.json.JSONObject line = selectionArray.getJSONObject(i); + String homeTeam = line.getString("HomeTeam"); + String awayTeam = line.getString("AwayTeam"); + String leagueName = line.getString("LeagueName"); + + homeTeam = siteService.getKorName("T", homeTeam); + awayTeam = siteService.getKorName("T", awayTeam); + leagueName = siteService.getKorName("L", leagueName); + + line.put("HomeTeamKor", homeTeam); + line.put("AwayTeamKor", awayTeam); + line.put("LeagueNameKor", leagueName); + } + + } else { + String homeTeam = selection.getString("HomeTeam"); + String awayTeam = selection.getString("AwayTeam"); + String leagueName = selection.getString("LeagueName"); + + homeTeam = siteService.getKorName("T", homeTeam); + awayTeam = siteService.getKorName("T", awayTeam); + leagueName = siteService.getKorName("L", leagueName); + + selection.put("HomeTeamKor", homeTeam); + selection.put("AwayTeamKor", awayTeam); + selection.put("LeagueNameKor", leagueName); + + } + + } catch (Exception e) { + log.error(LOG_PREFIX+ "tranERR"); + } + + trxParam.put("data", paramjson.toString()); + log.info(LOG_PREFIX+ "AF::parambody {}", paramjson.toString()); + } catch (Exception e) { + log.info(LOG_PREFIX+ "error {}", e.getMessage()); + } + + // 사이트정보 + HashMap ssParam = new HashMap(); + ssParam.put("siteIdx", Integer.parseInt(cust_id.substring(0, 3), 16)); + ssParam.put("memberId", cust_id.substring(3, cust_id.length())); + HashMap siteApiInfo = siteService.getSiteApiInfo(ssParam); + if (siteApiInfo == null) { + sp.appendLine("error_code=0"); + sp.append("CustomerNotFound"); + return sp.toString(); + } + + String siteId = siteApiInfo.get("siteId").toString(); + Map authParam = new HashMap(); + authParam.put("memberId", memberId); + authParam.put("siteId", siteId); + + // 회사정보 + log.info(LOG_PREFIX+ "siteApiInfo {}", siteApiInfo); + authParam.put("siteIdx", siteApiInfo.get("siteIdx")); + + // 회원정보 + Member member = siteService.getMemberByToken(authParam); + if (member == null) { + sp.appendLine("error_code=0"); + sp.append("CustomerNotFound"); + return sp.toString(); + } + + int siteIdx = Integer.parseInt(siteApiInfo.get("siteIdx").toString()); + String reserveId = siteService.getRefIdByPurchaseId(purchase_id); + String refId = siteId + reserveId; + Date dt = new Date(); + String trxId = "" + dt.getTime() + "4"; + trxParam.put("trxId", trxId); + trxParam.put("refId", refId); + + double balance = getBalnce(LOG_PREFIX, siteApiInfo.get("siteCbUrl").toString(), memberId); + long targetSiteCredit = siteService.getSiteCredit(siteApiInfo.get("siteId").toString()); + double amount = Double.parseDouble(amountStr); + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", req_id + "#CC"); + tranParam.put("refId", refId); + tranParam.put("siteIdx", siteApiInfo.get("siteIdx")); + tranParam.put("siteId", siteId); + tranParam.put("completed", true); + tranParam.put("memberIdx", member.getMemberIdx()); + tranParam.put("memberId", member.getMemberId()); + tranParam.put("vendorCetegory", "SPORT"); + tranParam.put("vendorIdx", 83); + tranParam.put("vendorCode", "splus"); + tranParam.put("vendorTranKey", purchase_id + "#CC"); + tranParam.put("gameType", ""); + tranParam.put("gameId", ""); + tranParam.put("gameIdx", ""); + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", ""); + siteService.commonBetinsert(tranParam); + + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/json"); + header.add("Accept", "application/json"); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + JSONObject debit = new JSONObject(); + double fakeAmount = amount;// *100; + debit.put("betId", refId); + debit.put("tranId", req_id + "#CC"); + debit.put("userId", member.getMemberId()); + debit.put("vendorIdx", 83); + debit.put("vendorKey", "SP2"); + debit.put("vendor", "splus"); + debit.put("gameIdx", 1); + debit.put("gameKey", ""); + debit.put("gameType", ""); + debit.put("gameId", ""); + debit.put("tranType", "credit"); + debit.put("debit", 0); + debit.put("credit", fakeAmount); + debit.put("isCancel", 0); + debit.put("isBonus", 0); + debit.put("decYn", "Y"); + HashMap detailMap = new Gson().fromJson(paramjson.toString(), HashMap.class); + debit.put("status", "end"); + debit.put("detail", detailMap); + + log.info(LOG_PREFIX+ "Callback Request: "+debit.toString()); + + ResponseEntity responseEntity = webClient.post() + .uri(siteApiInfo.get("siteCbUrl") + "/changebalance/sports") + .headers(h -> h.addAll(header)) + .bodyValue(debit.toString()) + .retrieve() + .toEntity(String.class) + .block(); + + org.codehaus.jettison.json.JSONObject resData = new org.codehaus.jettison.json.JSONObject( + responseEntity.getBody()); + log.info(LOG_PREFIX+ "Callback Response: "+resData.toString()); + + log.info(LOG_PREFIX+ "status code : {}", responseEntity.getStatusCode()); + log.info(LOG_PREFIX+ "body: {}", responseEntity.getBody()); + + DecimalFormat formatter = new DecimalFormat("0"); + if (resData.getLong("result_code") == 0) { + sp.appendLine("error_code=0"); + sp.appendLine("error_message=No Error "); + // sp.appendLine("balance="+formatter.format(new + // BigDecimal(resData.getDouble("balance") * 0.01))); + sp.appendLine("balance=" + formatter.format(new BigDecimal(resData.getDouble("balance")))); + sp.appendLine("trx_id=" + trxId); + + tranParam.put("balance", resData.getDouble("balance")); + int res = siteService.updateCbApi(tranParam); + } else { + sp.appendLine("error_code=0"); + sp.appendLine("error_message=error"); + sp.appendLine("balance=" + formatter.format(new BigDecimal(balance))); + sp.appendLine("trx_id=" + trxId); + } + + trxParam.put("tranId", tranParam.get("tranId").toString()); + trxParam.put("resData", resData.toString()); + siteService.updateSplusTran(trxParam); + + splusService.updateSplus(tranParam, paramjson); + + log.info(LOG_PREFIX+ "Response: "+sp.toString()); + return sp.toString(); // 활용한 응답 생성; + } + + private String makeApiKey(String param) { + + int n = 20; // n자리 쿠폰 + char[] chs = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', + 'J', 'K', 'L', 'M', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'N', 'O', 'P', 'Q', + 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', + 'z' }; + + Random rd = new Random(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < n; i++) { + char ch = chs[rd.nextInt(chs.length)]; + sb.append(ch); + } + return param + sb.toString(); + + } + +} diff --git a/src/main/java/com/bb/front/CallBackSvendorController.java b/src/main/java/com/bb/front/CallBackSvendorController.java new file mode 100644 index 0000000..5db1b3e --- /dev/null +++ b/src/main/java/com/bb/front/CallBackSvendorController.java @@ -0,0 +1,827 @@ +package com.bb.front; + +import java.net.SocketTimeoutException; +import java.util.HashMap; + +import jakarta.servlet.http.HttpServletRequest; + +import org.apache.http.conn.ConnectTimeoutException; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.ResourceAccessException; + +import com.bb.model.SvendorResponse; +import com.bb.service.AsyncSiteService; +import com.bb.service.CallBackService; +import com.bb.service.SiteService; + +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@RequestMapping("/api/callback/svendor") +@RequiredArgsConstructor +@SecurityRequirement(name = "Authorization") +@EnableScheduling +@RestController +public class CallBackSvendorController { + + @Autowired + SiteService siteService; + + @Autowired + CallBackService callBackService; + + @Autowired + AsyncSiteService asyncCallBackService; + + + @ResponseBody + @PostMapping(path = "/balance") + public ResponseEntity balance(HttpServletRequest request, @RequestBody net.sf.json.JSONObject requestBody) throws Exception { + + SvendorResponse response = new SvendorResponse(); + String vendorUsername = requestBody.getString("userid"); + String uuid = vendorUsername; + + //사이트정보 + HashMap siteApiInfo = siteService.getNewSiteApiInfo(vendorUsername); + long siteIdx = 0L; + String memberId = ""; + if(siteApiInfo != null) { + siteIdx = Long.parseLong(siteApiInfo.get("siteIdx").toString()); + memberId = siteApiInfo.get("memberId").toString(); + } + + final String LOG_PREFIX = "#-CB::SVENDOR::"+memberId+"::balance:::"; + log.info(LOG_PREFIX+ "Request Body::" + requestBody.toString()); + + try { + if(siteApiInfo == null) { + log.error(LOG_PREFIX+ "Error Msg: NOT_FOUND_SITE_INFO"); + response.setBalance("0"); + response.setId(uuid); + log.info(LOG_PREFIX+ "Response::"+response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + + if(siteApiInfo.get("memberIdx") == null) { + log.error(LOG_PREFIX+ "Error Msg: NOT_FOUND_SITE_USER"); + response.setBalance("0"); + response.setId(uuid); + log.info(LOG_PREFIX+ "Response::"+response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + + // ##--isTransfer 처리-## + int balance = 0; + if("N".equals(siteApiInfo.get("isTransfer").toString())) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + JSONObject member = new JSONObject(); + member.put("userId", memberId); + log.info(LOG_PREFIX+ "balance Req ::"+ member.toString()); + JSONObject resData = callBackService.getBalance(siteApiInfo, member); + if(resData == null) { + log.error(LOG_PREFIX+ "Error Msg: BALANCE_CALLBACK_ERROR"); + response.setBalance("0"); + response.setId(uuid); + log.info(LOG_PREFIX+ "Response::"+response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + log.info(LOG_PREFIX+ "balance Res ::"+ resData.toString()); + balance = resData.getInt("balance"); + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + balance = siteService.getUserBalance(balanceMap); + + if(siteApiInfo.get("siteCbUrl") != null && !"".equals(siteApiInfo.get("siteCbUrl").toString())) { + JSONObject member = new JSONObject(); + member.put("userId", memberId); + member.put("balance", balance); + asyncCallBackService.asyncBalance(LOG_PREFIX, siteApiInfo, member); + } + } + + response.setBalance(Integer.toString(balance)); + response.setId(uuid); + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + log.error(LOG_PREFIX+ "Error Msg: RESOURCE_ACCESS_ERROR"); + response.setBalance("0"); + response.setId(uuid); + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + + log.error(LOG_PREFIX+ "Error Msg: UNKNOWN_SERVER_ERROR"); + response.setBalance("0"); + response.setId(uuid); + } + + log.info(LOG_PREFIX+ "Response::"+response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + + + @ResponseBody + @PostMapping(path = "/bet") + public ResponseEntity callBet(HttpServletRequest request, @RequestBody net.sf.json.JSONObject requestBody) throws Exception { + + SvendorResponse response = new SvendorResponse(); + String vendorUsername = requestBody.getString("userid"); + String uuid = vendorUsername; + String vendorGameCode = requestBody.getString("vendor"); + + //사이트정보 + HashMap sParam = new HashMap<>(); + sParam.put("vendorUsername", vendorUsername); + sParam.put("vendor", "svendor"); + sParam.put("vendorGameCode", vendorGameCode); + HashMap siteVendorInfo = siteService.getNewSiteVendorInfo(sParam); + long siteIdx = 0L; + String memberId = ""; + if(siteVendorInfo != null) { + siteIdx = Long.parseLong(siteVendorInfo.get("siteIdx").toString()); + memberId = siteVendorInfo.get("memberId").toString(); + } + + final String LOG_PREFIX = "#-CB::SVENDOR::"+memberId+"::BET::"+requestBody.getString("tr_id")+":::"; + log.info(LOG_PREFIX+ "Request Body::" + requestBody.toString()); + + // ##--isTransfer 처리-## + final String IS_TRANSFER = siteVendorInfo.get("isTransfer").toString(); + + // 배팅 고유ID + String transactionId = requestBody.getString("tr_id"); + log.info(LOG_PREFIX+ "transactionId::"+transactionId); + // 베팅 참조ID + String referenceId = requestBody.getString("ref_id"); + log.info(LOG_PREFIX+ "referenceId"+referenceId); + // 라운드 고유ID + String roundId = requestBody.getString("round"); + log.info(LOG_PREFIX+ "roundId::"+roundId); + String tranId = transactionId; + //String betId = referenceId; + String betId = roundId+"#"+vendorUsername; + // 베팅 시각 + String betDateTimeStr = requestBody.getString("processed_at"); + + // 게임타입 + String gameType = requestBody.getString("game_type").replaceAll(" ", "").toLowerCase(); + // 게임테이블 아이디 (optional) + String gameId = ""; + if(requestBody.has("game_code")) gameId = requestBody.getString("game_code"); + String targetTableId = gameId.replaceAll(" ", "").toLowerCase(); + String gameName = ""; + if(requestBody.has("title")) gameName = requestBody.getString("title"); + // 배팅액 + String amountS = requestBody.getString("amount"); + int amount = 0; + Double amountD = Double.parseDouble(amountS); + amount = amountD.intValue(); + + try { + if(siteVendorInfo == null) { + log.error(LOG_PREFIX+ "Error Msg: NOT_FOUND_SITE_INFO"); + response.setBalance("0"); + response.setId(uuid); + response.setStatuscode(1); + response.setStatus("NOT_FOUND_SITE_INFO"); + log.info(LOG_PREFIX+ "Response::"+response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + + String banGameType = siteVendorInfo.get("banGameType").toString().replaceAll(" ", "").toLowerCase(); + String banGameId = siteVendorInfo.get("banGameId").toString().replaceAll(" ", "").toLowerCase(); + + if(!"".equals(gameType) && !"".equals(banGameType) && banGameType.contains(gameType+"|")) { + // Ban Game Type Exception + HashMap logParam = new HashMap(); + logParam.put("siteIdx", siteIdx); + logParam.put("memberIdx", memberIdx); + logParam.put("vendorIdx", vendorIdx); + logParam.put("statusCode", 501L); + logParam.put("callBackType", "debit"); + logParam.put("tranId", tranId); + logParam.put("callBackReqBody", "gameType:"+gameType+"이 블락설정"); + logParam.put("callBackResBody", ""); + logParam.put("errorCode", "BLOCK_GAME_TYPE"); + logParam.put("errorMsg", "gameType:"+gameType+"이 블락설정"); + long startTimestamp = System.currentTimeMillis(); + logParam.put("regDate", startTimestamp); + logParam.put("updDate", startTimestamp); + callBackService.insertCallBackErrLog(logParam); + log.error(LOG_PREFIX+ "Ban Game Type : " + gameType); + + response.setBalance("0"); + response.setId(uuid); + response.setStatuscode(1); + response.setStatus("BAN_GAME_TYPE_" + gameType); + log.info(LOG_PREFIX+ "Response::"+response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + + if(!"".equals(targetTableId) && !"".equals(banGameId) && banGameId.contains(targetTableId+"|")) { + // Ban Game Id Exception + HashMap logParam = new HashMap(); + logParam.put("siteIdx", siteIdx); + logParam.put("memberIdx", memberIdx); + logParam.put("vendorIdx", vendorIdx); + logParam.put("statusCode", 502L); + logParam.put("callBackType", "debit"); + logParam.put("tranId", tranId); + logParam.put("callBackReqBody", "gameId:"+gameId+"("+gameName+")이 블락설정"); + logParam.put("callBackResBody", ""); + logParam.put("errorCode", "BLOCK_GAME_ID"); + logParam.put("errorMsg", "gameId:"+gameId+"("+gameName+")이 블락설정"); + long startTimestamp = System.currentTimeMillis(); + logParam.put("regDate", startTimestamp); + logParam.put("updDate", startTimestamp); + callBackService.insertCallBackErrLog(logParam); + log.error(LOG_PREFIX+ "Ban Game Id : " + gameId); + + response.setBalance("0"); + response.setId(uuid); + response.setStatuscode(1); + response.setStatus("BAN_GAME_ID_" + gameId); + log.info(LOG_PREFIX+ "Response::"+response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + + if(siteVendorInfo.get("lastInVendorIdx")==null || "0".equals(siteVendorInfo.get("lastInVendorIdx").toString())) { + HashMap memParam = new HashMap<>(); + memParam.put("siteIdx", siteIdx); + memParam.put("memberIdx", memberIdx); + memParam.put("lastInVendorIdx", Integer.parseInt(siteVendorInfo.get("vendorIdx").toString())); + int updResult = siteService.updMemLastVendorIdx(memParam); + } else { + int lastInVendorIdx = Integer.parseInt(siteVendorInfo.get("lastInVendorIdx").toString()); + if(lastInVendorIdx != vendorIdx) { + log.error(LOG_PREFIX+ "VendorIdx doesn't match"); + response.setBalance("0"); + response.setId(uuid); + response.setStatuscode(1); + response.setStatus("ACCESS_VENDOR_MISSMATCH_"+lastInVendorIdx); + log.info(LOG_PREFIX+ "Response::"+response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + } + + long siteCredit = Long.parseLong(siteVendorInfo.get("credit").toString()); + // ##--isTransfer 처리-## + if(siteCredit < amount && IS_TRANSFER.equals("N")) { + log.error(LOG_PREFIX+ "NO_SITE_CREDIT"); + response.setBalance("0"); + response.setId(uuid); + response.setStatuscode(1); + response.setStatus("NO_SITE_CREDIT"); + log.info(LOG_PREFIX+ "Response::"+response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + + // 최대 베팅 금액 처리 (userMaxBet 우선 적용) + long siteMaxBet = Long.parseLong(siteVendorInfo.get("siteMaxBet").toString()); + long userMaxBet = 0; + if(siteVendorInfo.get("userMaxBet") != null && !siteVendorInfo.get("userMaxBet").toString().isEmpty()) { + try { + userMaxBet = Long.parseLong(siteVendorInfo.get("userMaxBet").toString()); + } catch (NumberFormatException e) { + userMaxBet = 0; + } + } + + // 최종 maxBet 결정: userMaxBet이 0이면 siteMaxBet 사용, 0이 아니면 userMaxBet 사용 + long finalMaxBet = (userMaxBet > 0) ? userMaxBet : siteMaxBet; + log.info(LOG_PREFIX+ "MaxBet Info - siteMaxBet: " + siteMaxBet + ", userMaxBet: " + userMaxBet + ", finalMaxBet: " + finalMaxBet); + + if(finalMaxBet < amount) { + log.error(LOG_PREFIX+ "MAX_BET_AMOUNT_OVER"); + log.error(LOG_PREFIX+ "finalMaxBet : " + finalMaxBet +", amount : " + amount); + response.setBalance("0"); + response.setId(uuid); + response.setStatuscode(1); + response.setStatus("MAX_BET_AMOUNT_OVER"); + log.info(LOG_PREFIX+ "Response::"+response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("Y")) { + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(tranId); + if(cntTr > 0) { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + response.setBalance(Integer.toString(balance)); + response.setId(uuid); + response.setStatuscode(0); + response.setStatus("OK"); + log.error(LOG_PREFIX+ "중복요청::Response::" + response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "svendor"); + tranParam.put("vendorTranKey", referenceId); + tranParam.put("gameType", gameType); + tranParam.put("gameId", gameId); + tranParam.put("gameIdx", gameName); + tranParam.put("tranType", "debit"); + tranParam.put("depositAmt", amount); + tranParam.put("creditAmt", "0"); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("betKey", referenceId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "svendor"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", gameName); + callBackObj.put("gameId", gameId); + callBackObj.put("gameType", gameType); + callBackObj.put("tranType", "debit"); + callBackObj.put("debit", amount); + callBackObj.put("credit", 0); + callBackObj.put("isCancel", 0); + callBackObj.put("isBonus", 0); + callBackObj.put("requestAt", betDateTimeStr); + log.info(LOG_PREFIX + "SEND_BET request body: " + callBackObj.toString()); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("N")) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + log.info(LOG_PREFIX + "-----INSERT_BET_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_BET_END-----"); + + JSONObject resData = null; + if(vendorCetegory.equals("SLOT")) { + resData = callBackService.changeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } else { + resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } + log.info(LOG_PREFIX + "SEND_BET status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_BET response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + // 성공 + tranParam.put("balance", resData.getInt("balance")); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + response.setBalance(Integer.toString(balance)); + response.setId(uuid); + response.setStatuscode(0); + response.setStatus("OK"); + } else if(resData.getLong("result_code") == 98) { + // 중복 + int balance = resData.getInt("balance"); + response.setBalance(Integer.toString(balance)); + response.setId(uuid); + response.setStatuscode(0); + response.setStatus("OK"); + } else if(resData.getLong("result_code") == 80) { + // 중복 + int balance = resData.getInt("balance"); + response.setBalance(Integer.toString(balance)); + response.setId(uuid); + response.setStatuscode(0); + response.setStatus("OK"); + } else { + // 실패 + log.error(LOG_PREFIX+ "CALLBACK_ERROR"); + response.setBalance("0"); + response.setId(uuid); + response.setStatuscode(1); + response.setStatus("CALLBACK_ERROR"); + } + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + int afBalance = balance - amount; + + if(balance < amount) { + response.setBalance(Integer.toString(balance)); + response.setId(uuid); + response.setStatuscode(0); + response.setStatus("OK"); + log.error(LOG_PREFIX+ "잔액부족::Response::" + response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + + log.info(LOG_PREFIX + "-----INSERT_BET_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_BET_END-----"); + + tranParam.put("balance", afBalance); + tranParam.put("preBalance", balance); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + response.setBalance(Integer.toString(afBalance)); + response.setId(uuid); + response.setStatuscode(0); + response.setStatus("OK"); + + if(siteVendorInfo.get("siteCbUrl") != null && !"".equals(siteVendorInfo.get("siteCbUrl").toString())) { + callBackObj.put("balance", afBalance); + if(vendorCetegory.equals("SLOT")) { + asyncCallBackService.asyncChangeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } else { + asyncCallBackService.asyncChangeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } + } + + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + log.error(LOG_PREFIX+ "Error Msg: RESOURCE_ACCESS_ERROR"); + response.setBalance("0"); + response.setId(uuid); + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + + log.error(LOG_PREFIX+ "Error Msg: UNKNOWN_SERVER_ERROR"); + response.setBalance("0"); + response.setId(uuid); + } + + log.info(LOG_PREFIX+ "Response::"+response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + + + @ResponseBody + @PostMapping(value = { "/win", "/cancel", "/promo"} ) + public ResponseEntity callResult(HttpServletRequest request, @RequestBody net.sf.json.JSONObject requestBody) throws Exception { + + SvendorResponse response = new SvendorResponse(); + String vendorUsername = requestBody.getString("userid"); + String uuid = vendorUsername; + String vendorGameCode = requestBody.getString("vendor"); + String callbackType = requestBody.getString("type"); + + //사이트정보 + HashMap sParam = new HashMap<>(); + sParam.put("vendorUsername", vendorUsername); + sParam.put("vendor", "svendor"); + sParam.put("vendorGameCode", vendorGameCode); + HashMap siteVendorInfo = siteService.getNewSiteVendorInfo(sParam); + long siteIdx = 0L; + String memberId = ""; + if(siteVendorInfo != null) { + siteIdx = Long.parseLong(siteVendorInfo.get("siteIdx").toString()); + memberId = siteVendorInfo.get("memberId").toString(); + } + + final String LOG_PREFIX = "#-CB::SVENDOR::"+memberId+"::"+callbackType.toUpperCase()+"::"+requestBody.getString("tr_id")+":::"; + log.info(LOG_PREFIX+ "Request Body::" + requestBody.toString()); + + // ##--isTransfer 처리-## + final String IS_TRANSFER = siteVendorInfo.get("isTransfer").toString(); + + // 배팅 고유ID + String transactionId = requestBody.getString("tr_id"); + log.info(LOG_PREFIX+ "transactionId::"+transactionId); + // 베팅 참조ID + String referenceId = requestBody.getString("ref_id"); + log.info(LOG_PREFIX+ "referenceId"+referenceId); + // 라운드 고유ID + String roundId = requestBody.getString("round"); + log.info(LOG_PREFIX+ "roundId::"+roundId); + String tranId = transactionId; + //String betId = referenceId; + String betId = roundId+"#"+vendorUsername; + // 베팅 시각 + String betDateTimeStr = requestBody.getString("processed_at"); + + // 게임타입 + String gameType = requestBody.getString("game_type").replaceAll(" ", "").toLowerCase(); + // 게임테이블 아이디 (optional) + String gameId = ""; + if(requestBody.has("game_code")) gameId = requestBody.getString("game_code"); + // 게임코드 + if("promo".equals(callbackType)) { + gameId = callbackType; + } + + // 게임타이틀 + String gameName = "" ; + if(requestBody.has("title")) gameName = requestBody.getString("title"); + if("promo".equals(callbackType)) { + gameName =callbackType; + } + // 배팅액 + String amountS = requestBody.getString("amount"); + int amount = 0; + Double amountD = Double.parseDouble(amountS); + amount = amountD.intValue(); + + try { + if(siteVendorInfo == null) { + log.error(LOG_PREFIX+ "Error Msg: NOT_FOUND_SITE_INFO"); + response.setBalance("0"); + response.setId(uuid); + response.setStatuscode(1); + response.setStatus("NOT_FOUND_SITE_INFO"); + log.info(LOG_PREFIX+ "Response::"+response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("Y")) { + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(tranId); + if(cntTr > 0) { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + response.setBalance(Integer.toString(balance)); + response.setId(uuid); + response.setStatuscode(0); + response.setStatus("OK"); + log.error(LOG_PREFIX+ "중복요청::Response::" + response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + + // 베팅 체크 + int cntBet = siteService.getBetIdCheck2(betId); + if(cntBet == 0) { + log.error(LOG_PREFIX+ "Error Msg: NOT_FOUND_BET_INFO"); + response.setBalance("0"); + response.setId(uuid); + response.setStatuscode(1); + response.setStatus("NOT_FOUND_BET_INFO"); + log.info(LOG_PREFIX+ "Response::"+response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + } else { + //베팅여부체크 + if("cancel".equals(callbackType)) { //베팅없으면 에러 + int checkBet = siteService.getSuccDebitCnt(betId); + if(checkBet==0) { + log.error(LOG_PREFIX+ "Error Msg: NOT_FOUND_BET_INFO"); + response.setBalance("0"); + response.setId(uuid); + response.setStatuscode(1); + response.setStatus("NOT_FOUND_BET_INFO"); + log.info(LOG_PREFIX+ "Response::"+response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + } + } + + //초과베팅 체크 + int overCreditAmt = 0; + if(vendorCetegory.equals("SLOT") && "win".equals(callbackType)) { + int siteMaxWin = Integer.parseInt(siteVendorInfo.get("siteMaxWin").toString()); + if(siteMaxWin < amount && siteMaxWin != 0) { + log.error(LOG_PREFIX+ "MAX_WIN_AMOUNT_OVER"); + log.error(LOG_PREFIX+ "siteMaxWin : " + siteMaxWin +", amount : " + amount); + overCreditAmt = amount - siteMaxWin; + amount = siteMaxWin; + log.error(LOG_PREFIX+ "Change amount : " + amount +", overCreditAmt : " + overCreditAmt); + } + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "svendor"); + tranParam.put("vendorTranKey", referenceId); + tranParam.put("gameType", gameType); + tranParam.put("gameId", gameId); + tranParam.put("gameIdx", gameName); + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + tranParam.put("overCreditAmt", overCreditAmt); + if("cancel".equals(callbackType)) { + tranParam.put("isCancel", "Y"); + } else { + tranParam.put("isCancel", "N"); + } + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("betKey", referenceId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "svendor"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", gameName); + callBackObj.put("gameId", gameId); + callBackObj.put("gameType", gameType); + callBackObj.put("tranType", "credit"); + callBackObj.put("debit", 0); + callBackObj.put("credit", amount); + if("cancel".equals(callbackType)) { + callBackObj.put("isCancel", 1); + } else { + callBackObj.put("isCancel", 0); + } + if("promo".equals(callbackType)) { + callBackObj.put("isBonus", 1); + } else { + callBackObj.put("isBonus", 0); + } + callBackObj.put("requestAt", betDateTimeStr); + log.info(LOG_PREFIX + "SEND_RESULT request body: " + callBackObj.toString()); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("N")) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + log.info(LOG_PREFIX + "-----INSERT_RESULT_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_RESULT_END-----"); + + JSONObject resData = null; + if(vendorCetegory.equals("SLOT")) { + resData = callBackService.changeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } else { + resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } + log.info(LOG_PREFIX + "SEND_RESULT status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_RESULT response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + // 성공 + tranParam.put("balance", resData.getInt("balance")); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + response.setBalance(Integer.toString(balance)); + response.setId(uuid); + response.setStatuscode(0); + response.setStatus("OK"); + } else if(resData.getLong("result_code") == 98) { + // 중복 + int balance = resData.getInt("balance"); + response.setBalance(Integer.toString(balance)); + response.setId(uuid); + response.setStatuscode(0); + response.setStatus("OK"); + } else { + // 실패 + log.error(LOG_PREFIX+ "CALLBACK_ERROR"); + response.setBalance("0"); + response.setId(uuid); + response.setStatuscode(1); + response.setStatus("CALLBACK_ERROR"); + } + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + int afBalance = balance + amount; + + log.info(LOG_PREFIX + "-----INSERT_RESULT_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_RESULT_END-----"); + + tranParam.put("balance", afBalance); + tranParam.put("preBalance", balance); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + response.setBalance(Integer.toString(afBalance)); + response.setId(uuid); + response.setStatuscode(0); + response.setStatus("OK"); + + if(siteVendorInfo.get("siteCbUrl") != null && !"".equals(siteVendorInfo.get("siteCbUrl").toString())) { + callBackObj.put("balance", afBalance); + if(vendorCetegory.equals("SLOT")) { + asyncCallBackService.asyncChangeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } else { + asyncCallBackService.asyncChangeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } + } + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + log.error(LOG_PREFIX+ "Error Msg: RESOURCE_ACCESS_ERROR"); + response.setBalance("0"); + response.setId(uuid); + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + + log.error(LOG_PREFIX+ "Error Msg: UNKNOWN_SERVER_ERROR"); + response.setBalance("0"); + response.setId(uuid); + } + + log.info(LOG_PREFIX+ "Response::"+response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + +} + diff --git a/src/main/java/com/bb/front/CallBackTheaController.java b/src/main/java/com/bb/front/CallBackTheaController.java new file mode 100644 index 0000000..bd86254 --- /dev/null +++ b/src/main/java/com/bb/front/CallBackTheaController.java @@ -0,0 +1,650 @@ +package com.bb.front; + +import java.net.SocketTimeoutException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; + +import jakarta.servlet.http.HttpServletRequest; + +import org.apache.http.conn.ConnectTimeoutException; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.ResourceAccessException; + +import com.bb.model.TheaResponse; +import com.bb.service.CallBackService; +import com.bb.service.SiteService; + +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@RequestMapping("/api/callback/thea") +@RequiredArgsConstructor +@SecurityRequirement(name = "Authorization") +@EnableScheduling +@RestController +public class CallBackTheaController { + + @Autowired + SiteService siteService; + + @Autowired + CallBackService callBackService; + + @ResponseBody + @RequestMapping(path = "/balance") + public ResponseEntity balance(HttpServletRequest request, @RequestParam("username") String theaUsername) throws Exception { + TheaResponse response = null; + + long siteIdx = Long.parseLong(theaUsername.substring(0, 3), 16); + String memberId = theaUsername.substring(3, theaUsername.length()); + final String LOG_PREFIX = "#-CB::THEA::"+memberId+"::balance:::"; + log.info(LOG_PREFIX+ "Request::" + theaUsername); + + try { + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + log.info(LOG_PREFIX + "SITE_API_INFO_PARAM::"+sParam.toString()); + HashMap siteApiInfo = siteService.getSiteApiInfo(sParam); + if(siteApiInfo == null) { + log.error(LOG_PREFIX+ "Error Msg: NOT_FOUND_SITE_INFO"); + response = new TheaResponse(); + response.setBalance(0); + return new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + if(siteApiInfo.get("memberIdx") == null) { + log.error(LOG_PREFIX+ "존재하지 않는 회원"); + response = new TheaResponse(); + response.setBalance(0); + return new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + JSONObject member = new JSONObject(); + member.put("userId", memberId); + log.info(LOG_PREFIX+ "balance Req ::"+ member.toString()); + JSONObject resData = callBackService.getBalance(siteApiInfo, member); + log.info(LOG_PREFIX+ "balance Res ::"+ resData.toString()); + int balance = resData.getInt("balance"); + + response = new TheaResponse(); + response.setBalance(balance); + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + response = new TheaResponse(); + response.setBalance(0); + return new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + response = new TheaResponse(); + response.setBalance(0); + return new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + ResponseEntity res = new ResponseEntity(response, HttpStatus.OK); + log.info(LOG_PREFIX+ "Response::" + response.toString()); + + return res; + } + + + @ResponseBody + @RequestMapping(path = "/changeBalance") + public ResponseEntity changeBalance(HttpServletRequest request, @RequestBody net.sf.json.JSONObject requestBody) throws Exception { + ResponseEntity resEntity = null; + + String theaUsername = requestBody.getString("username"); + long siteIdx = Long.parseLong(theaUsername.substring(0, 3), 16); + String memberId = theaUsername.substring(3, theaUsername.length()); + net.sf.json.JSONObject transaction = requestBody.getJSONObject("transaction"); + net.sf.json.JSONObject game = transaction.getJSONObject("details").getJSONObject("game"); + String transactionId = transaction.getString("id"); + String transactionType = transaction.getString("type"); + + final String LOG_PREFIX = "#-CB::THEA::"+memberId+"::"+transactionId+"::"+transactionType+"::changeBalance::"; + log.info(LOG_PREFIX+ "Request::" + requestBody.toString()); + + try { + // "processed_at":"2025-01-16T09:25:23.000000Z" + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS"); + String betDateTimeStr = transaction.getString("processed_at"); + log.info(LOG_PREFIX+ "========== BF_betDateTimeStr::" + betDateTimeStr); + betDateTimeStr = betDateTimeStr.substring(0, 19); + betDateTimeStr = betDateTimeStr.replace("T", " "); + log.info(LOG_PREFIX+ "========== MF_betDateTimeStr::" + betDateTimeStr); + betDateTimeStr = makeEdate(LOG_PREFIX, betDateTimeStr, 32400000); + log.info(LOG_PREFIX+ "========== AF_betDateTimeStr::" + betDateTimeStr); + + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "thea"); + sParam.put("vendorGameCode", game.getString("vendor")); + log.info(LOG_PREFIX + "getSiteVendorInfo::"+sParam.toString()); + HashMap siteVendorInfo = siteService.getSiteVendorInfo(sParam); + if(siteVendorInfo == null) { + log.error(LOG_PREFIX+ "존재하지 않는 회원입니다"); + TheaResponse response = new TheaResponse(); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + return resEntity; + } + + if(transactionType.equals("bet")) { + int amount = Math.abs(requestBody.getInt("amount")); + resEntity = callBet(LOG_PREFIX, siteIdx, memberId, transaction, betDateTimeStr, siteVendorInfo, amount); + } else if(transactionType.equals("win")) { + int amount = Math.abs(requestBody.getInt("amount")); + resEntity = callWin(LOG_PREFIX, siteIdx, memberId, transaction, betDateTimeStr, siteVendorInfo, amount); + } else if(transactionType.equals("cancel")) { + int amount = requestBody.getInt("amount"); + resEntity = callCancel(LOG_PREFIX, siteIdx, memberId, transaction, betDateTimeStr, siteVendorInfo, amount); + } else { + log.error(LOG_PREFIX+ "unknown_transaction_type"); + TheaResponse response = new TheaResponse(); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + return resEntity; + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + TheaResponse response = new TheaResponse(); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + return resEntity; + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + TheaResponse response = new TheaResponse(); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + return resEntity; + } + + log.info(LOG_PREFIX+ "Response::" + resEntity.toString()); + + return resEntity; + } + + private ResponseEntity callBet(String LOG_PREFIX, long siteIdx, String memberId, + net.sf.json.JSONObject transaction, String betDateTimeStr, HashMap siteVendorInfo, int amount) { + + LOG_PREFIX = LOG_PREFIX + "callBet:::"; + ResponseEntity resEntity = null; + TheaResponse response = new TheaResponse(); + net.sf.json.JSONObject target = transaction.getJSONObject("target"); + net.sf.json.JSONObject details = transaction.getJSONObject("details"); + net.sf.json.JSONObject game = details.getJSONObject("game"); + + String gameType = game.getString("type").replaceAll(" ", "").toLowerCase(); + String gameId = game.getString("code").replaceAll(" ", "").toLowerCase(); + String gameName = game.getString("title"); + + String banGameType = siteVendorInfo.get("banGameType").toString().replaceAll(" ", "").toLowerCase(); + String banGameId = siteVendorInfo.get("banGameId").toString().replaceAll(" ", "").toLowerCase(); + + if(!"".equals(gameType) && !"".equals(banGameType) && banGameType.contains(gameType+"|")) { + log.error(LOG_PREFIX+ "Ban Game Type : " + gameType); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); // 501 + return resEntity; + } + + if(!"".equals(gameId) && !"".equals(banGameId) && banGameId.contains(gameId+"|")) { + log.error(LOG_PREFIX+ "Ban Game Id : " + gameId); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); // 502 + return resEntity; + } + + try { + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + String vendorTranKey = transaction.getString("id"); + String tranId = transaction.getString("id"); + String betId = tranId; + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + + if(siteVendorInfo.get("lastInVendorIdx")==null || "0".equals(siteVendorInfo.get("lastInVendorIdx").toString())) { + HashMap memParam = new HashMap<>(); + memParam.put("siteIdx", siteIdx); + memParam.put("memberIdx", memberIdx); + memParam.put("lastInVendorIdx", Integer.parseInt(siteVendorInfo.get("vendorIdx").toString())); + int updResult = siteService.updMemLastVendorIdx(memParam); + } else { + int lastInVendorIdx = Integer.parseInt(siteVendorInfo.get("lastInVendorIdx").toString()); + if(lastInVendorIdx != vendorIdx) { + log.error(LOG_PREFIX+ "VendorIdx doesn't match"); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + return resEntity; + } + } + + long siteCredit = Long.parseLong(siteVendorInfo.get("credit").toString()); + if(siteCredit < amount) { + log.error(LOG_PREFIX+ "NO_SITE_CREDIT"); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + return resEntity; + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "thea"); + tranParam.put("vendorTranKey", vendorTranKey); + tranParam.put("gameType", game.getString("type")); + tranParam.put("gameId", game.getString("code")); + tranParam.put("gameIdx", gameName); + tranParam.put("tranType", "debit"); + tranParam.put("depositAmt", amount); + tranParam.put("creditAmt", "0"); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + log.info(LOG_PREFIX + "-----INSERT_BET_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_BET_END-----"); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "thea"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", gameName); + callBackObj.put("gameId", game.getString("code")); + callBackObj.put("gameType", game.getString("type")); + callBackObj.put("tranType", "debit"); + callBackObj.put("debit", amount); + callBackObj.put("credit", 0); + callBackObj.put("isCancel", 0); + callBackObj.put("isBonus", 0); + callBackObj.put("requestAt", betDateTimeStr); + log.info(LOG_PREFIX + "SEND_BET request body: " + callBackObj.toString()); + JSONObject resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + log.info(LOG_PREFIX + "SEND_BET status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_BET response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + response.setBalance(balance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + } else if(resData.getLong("result_code") == 98) { + int balance = resData.getInt("balance"); + response.setBalance(balance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + } else if(resData.getLong("result_code") == 80) { + int balance = resData.getInt("balance"); + response.setBalance(balance); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } else { + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + log.error(LOG_PREFIX+ msg); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + return resEntity; + } + + + private ResponseEntity callWin(String LOG_PREFIX, long siteIdx, String memberId, + net.sf.json.JSONObject transaction, String betDateTimeStr, HashMap siteVendorInfo, int amount) { + + LOG_PREFIX = LOG_PREFIX + "callWin:::"; + ResponseEntity resEntity = null; + TheaResponse response = new TheaResponse(); + net.sf.json.JSONObject target = transaction.getJSONObject("target"); + net.sf.json.JSONObject details = transaction.getJSONObject("details"); + net.sf.json.JSONObject game = details.getJSONObject("game"); + + try { + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + String vendorTranKey = transaction.getString("id"); + String tranId = transaction.getString("id"); + String betId = transaction.getString("referer_id"); + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "thea"); + tranParam.put("vendorTranKey", vendorTranKey); + tranParam.put("gameType", game.getString("type")); + tranParam.put("gameId", game.getString("code")); + tranParam.put("gameIdx", game.getString("title")); + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + log.info(LOG_PREFIX + "-----INSERT_RESULT_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_RESULT_END-----"); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "thea"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", game.getString("title")); + callBackObj.put("gameId", game.getString("code")); + callBackObj.put("gameType", game.getString("type")); + callBackObj.put("tranType", "credit"); + callBackObj.put("debit", 0); + callBackObj.put("credit", amount); + callBackObj.put("isCancel", 0); + callBackObj.put("isBonus", 0); + callBackObj.put("requestAt", betDateTimeStr); + log.info(LOG_PREFIX + "SEND_RESULT request body: " + callBackObj.toString()); + JSONObject resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + log.info(LOG_PREFIX + "SEND_RESULT status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_RESULT response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + // Insert transaction.id for bet detail + try { + if(vendorIdx == 1) { + HashMap detailParam = new HashMap(); + detailParam.put("transactionId", transaction.getString("referer_id")); + detailParam.put("siteIdx", siteIdx); + log.info(LOG_PREFIX + "INSERT_THE_A_EVO_DETAIL dParam::" + detailParam.toString()); + int result = siteService.insertTheaTrxId(detailParam); + log.info(LOG_PREFIX + "INSERT_THE_A_EVO_DETAIL result::"+result); + } + } catch (Exception e) { + log.error(LOG_PREFIX+ "[insertTheaTrxId Exception]"+e.getMessage()); + } + + int balance = resData.getInt("balance"); + response.setBalance(balance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + + } else if(resData.getLong("result_code") == 98) { + int balance = resData.getInt("balance"); + response.setBalance(balance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + + } else { + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + log.error(LOG_PREFIX+ msg); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + return resEntity; + } + + + private ResponseEntity callCancel(String LOG_PREFIX, long siteIdx, String memberId, + net.sf.json.JSONObject transaction, String betDateTimeStr, HashMap siteVendorInfo, int amount) { + + ResponseEntity resEntity = null; + TheaResponse response = new TheaResponse(); + net.sf.json.JSONObject target = transaction.getJSONObject("target"); + net.sf.json.JSONObject details = transaction.getJSONObject("details"); + net.sf.json.JSONObject game = details.getJSONObject("game"); + + try { + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + String vendorTranKey = transaction.getString("id"); + String tranId = transaction.getString("id"); + String betId = transaction.getString("referer_id"); + if(amount > 0) { + // 배팅 취소 + tranId = tranId + "#DC"; + vendorTranKey = vendorTranKey + "#DC"; + LOG_PREFIX = LOG_PREFIX + "callCancelDebit:::"; + } else { + // 당첨 취소 + tranId = tranId + "#CC"; + vendorTranKey = vendorTranKey + "#CC"; + LOG_PREFIX = LOG_PREFIX + "callCancelCredit:::"; + } + + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "thea"); + tranParam.put("vendorTranKey", vendorTranKey); + tranParam.put("gameType", game.getString("type")); + tranParam.put("gameId", game.getString("code")); + tranParam.put("gameIdx", game.getString("title")); + if(amount > 0) { + // 배팅 취소 + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", Math.abs(amount)); + } else { + // 당첨 취소 + tranParam.put("tranType", "debit"); + tranParam.put("depositAmt", Math.abs(amount)); + tranParam.put("creditAmt", "0"); + } + tranParam.put("isCancel", "Y"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + log.info(LOG_PREFIX + "-----INSERT_CANCEL_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_CANCEL_END-----"); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "thea"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", game.getString("title")); + callBackObj.put("gameId", game.getString("code")); + callBackObj.put("gameType", game.getString("type")); + if(amount > 0) { + // 배팅 취소 + callBackObj.put("tranType", "credit"); + callBackObj.put("debit", 0); + callBackObj.put("credit", Math.abs(amount)); + } else { + // 당첨 취소 + callBackObj.put("tranType", "debit"); + callBackObj.put("debit", Math.abs(amount)); + callBackObj.put("credit", 0); + } + callBackObj.put("isCancel", 1); + callBackObj.put("isBonus", 0); + callBackObj.put("requestAt", betDateTimeStr); + log.info(LOG_PREFIX + "SEND_CANCEL request body: " + callBackObj.toString()); + JSONObject resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + log.info(LOG_PREFIX + "SEND_CANCEL status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_CANCEL response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + response.setBalance(balance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + + } else if(resData.getLong("result_code") == 98) { + int balance = resData.getInt("balance"); + response.setBalance(balance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + + } else { + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + log.error(LOG_PREFIX+ msg); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + return resEntity; + } + + + private static String makeEdate(String LOG_PREFIX, String paramDate, int flag) { + // TODO Auto-generated method stub + String eDate = ""; + SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + try { + Date date = sdf1.parse(paramDate); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + calendar.add(Calendar.MILLISECOND, flag); + Date date2 = calendar.getTime(); + eDate = sdf2.format(date2); + } catch(Exception e) { + log.error(LOG_PREFIX+ "makeEdate::Exception::"+e.getMessage()); + } + return eDate; + } +} diff --git a/src/main/java/com/bb/front/CallBackThenutController.java b/src/main/java/com/bb/front/CallBackThenutController.java new file mode 100644 index 0000000..611fc76 --- /dev/null +++ b/src/main/java/com/bb/front/CallBackThenutController.java @@ -0,0 +1,767 @@ +package com.bb.front; + +import java.net.SocketTimeoutException; +import java.text.SimpleDateFormat; +import java.util.HashMap; + +import org.apache.http.conn.ConnectTimeoutException; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.ResourceAccessException; + +import com.bb.model.ThenutResponse; +import com.bb.service.AsyncSiteService; +import com.bb.service.CallBackService; +import com.bb.service.SiteService; + +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@RequestMapping("/api/cb/thenut") +@RequiredArgsConstructor +@SecurityRequirement(name = "Authorization") +@EnableScheduling +@RestController +public class CallBackThenutController { + + @Autowired + SiteService siteService; + + @Autowired + CallBackService callBackService; + + @Autowired + AsyncSiteService asyncCallBackService; + + + @ResponseBody + @RequestMapping(path = "/balance") + public ResponseEntity balance(HttpServletRequest request, @RequestParam("username") String thenutUsername) throws Exception { + ThenutResponse response = null; + + long siteIdx = 0L; + try { + siteIdx = Long.parseLong(thenutUsername.substring(0, 3), 16); + } catch (NumberFormatException e) { + log.error("#-CB::THENUT::balance::Invalid username format (hex expected): {}", thenutUsername); + response = new ThenutResponse(); + response.setBalance(0); + response.setErrorCode(-1); + response.setMessage("Invalid username format (hex expected)"); + return new ResponseEntity(response, HttpStatus.OK); + } + String memberId = thenutUsername.substring(3, thenutUsername.length()); + final String LOG_PREFIX = "#-CB::THENUT::balance::"+memberId+":::"; + log.info(LOG_PREFIX+ "Request::" + thenutUsername); + + try { + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + log.info(LOG_PREFIX + "SITE_API_INFO_PARAM::"+sParam.toString()); + HashMap siteApiInfo = siteService.getSiteApiInfo(sParam); + if(siteApiInfo == null) { + log.error(LOG_PREFIX+ "Error Msg: NOT_FOUND_SITE_INFO"); + response = new ThenutResponse(); + response.setBalance(0); + response.setErrorCode(-1); + response.setMessage("NOT_FOUND_SITE_INFO"); + return new ResponseEntity(response, HttpStatus.OK); + } + + if(siteApiInfo.get("memberIdx") == null) { + log.error(LOG_PREFIX+ "존재하지 않는 회원"); + response = new ThenutResponse(); + response.setBalance(0); + response.setErrorCode(-1); + response.setMessage("존재하지 않는 회원"); + return new ResponseEntity(response, HttpStatus.OK); + } + + // ##--isTransfer 처리-## + int balance = 0; + if("N".equals(siteApiInfo.get("isTransfer").toString())) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + JSONObject member = new JSONObject(); + member.put("userId", memberId); + log.info(LOG_PREFIX+ "balance Req ::"+ member.toString()); + JSONObject resData = callBackService.getBalance(siteApiInfo, member); + if(resData == null) { + log.error(LOG_PREFIX+ "Error Msg: BALANCE_CALLBACK_ERROR"); + response = new ThenutResponse(); + response.setBalance(0); + response.setErrorCode(-1); + response.setMessage("BALANCE_CALLBACK_ERROR"); + return new ResponseEntity(response, HttpStatus.OK); + } + log.info(LOG_PREFIX+ "balance Res ::"+ resData.toString()); + balance = resData.getInt("balance"); + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + balance = siteService.getUserBalance(balanceMap); + + if(siteApiInfo.get("siteCbUrl") != null && !"".equals(siteApiInfo.get("siteCbUrl").toString())) { + JSONObject member = new JSONObject(); + member.put("userId", memberId); + member.put("balance", balance); + asyncCallBackService.asyncBalance(LOG_PREFIX, siteApiInfo, member); + } + } + + response = new ThenutResponse(); + response.setBalance(balance); + response.setErrorCode(0); + response.setMessage("SUCCESS"); + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + response = new ThenutResponse(); + response.setBalance(0); + response.setErrorCode(-1); + response.setMessage("TIMEOUT_ERROR"); + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + response = new ThenutResponse(); + response.setBalance(0); + response.setErrorCode(-9); + response.setMessage("BALANCE_SERVER_ERROR"); + } + + ResponseEntity res = new ResponseEntity(response, HttpStatus.OK); + log.info(LOG_PREFIX+ "Response::" + response.toString()); + + return res; + } + + + @ResponseBody + @RequestMapping(path = "/bet") + public ResponseEntity callBet(HttpServletRequest request, @RequestBody net.sf.json.JSONObject requestBody) throws Exception { + ThenutResponse response = null; + HttpStatus httpStatus = null; + + String thenutUsername = requestBody.getString("username"); + long siteIdx = 0L; + try { + siteIdx = Long.parseLong(thenutUsername.substring(0, 3), 16); + } catch (NumberFormatException e) { + log.error("#-CB::THENUT::callBet::Invalid username format (hex expected): {}", thenutUsername); + response = new ThenutResponse(); + response.setBalance(0); + response.setErrorCode(-1); + response.setMessage("Invalid username format (hex expected)"); + return new ResponseEntity(response, HttpStatus.OK); + } + String memberId = thenutUsername.substring(3, thenutUsername.length()); + long transactionId = requestBody.getLong("transactionId"); + String transactionType = requestBody.getString("transactionType"); + + final String LOG_PREFIX = "#-CB::THENUT::callBet::"+memberId+"::"+transactionId+"::"+transactionType+":::"; + log.info(LOG_PREFIX+ "Request::" + requestBody.toString()); + + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "thenut"); + sParam.put("vendorGameCode", requestBody.getString("vendorCode")); + log.info(LOG_PREFIX + "getSiteVendorInfo::"+sParam.toString()); + HashMap siteVendorInfo = siteService.getSiteVendorInfo(sParam); + if(siteVendorInfo == null) { + response = new ThenutResponse(); + response.setErrorCode(-1); + response.setMessage("존재하지 않는 회원입니다."); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX + "Response Body: " + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + // ##--isTransfer 처리-## + final String IS_TRANSFER = siteVendorInfo.get("isTransfer").toString(); + + try { + // "processed_at":"2025-01-16T09:25:23.000000Z" + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS"); + String betDateTimeStr = requestBody.getString("betAt"); + log.info(LOG_PREFIX+ "========== BF_betDateTimeStr::" + betDateTimeStr); + betDateTimeStr = betDateTimeStr.substring(0, 19); + betDateTimeStr = betDateTimeStr.replace("T", " "); + log.info(LOG_PREFIX+ "========== AF_betDateTimeStr::" + betDateTimeStr); + + int amount = requestBody.getInt("amount"); + String gameType = requestBody.getString("gameType"); + String gameId = requestBody.getString("gameCode"); + String gameName = requestBody.getString("gameTitle"); + + String targetTableId = gameId.replaceAll(" ", "").toLowerCase(); + String banGameId = siteVendorInfo.get("banGameId").toString().replaceAll(" ", "").toLowerCase(); + if(!"".equals(targetTableId) && !"".equals(banGameId) && banGameId.contains(targetTableId+"|")) { + log.error(LOG_PREFIX+ "Ban Game Id : " + banGameId); + response = new ThenutResponse(); + response.setErrorCode(100); + response.setMessage("Ban Game Id : " + banGameId); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX + "Response Body: " + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + String tranId = Long.toString(transactionId); + String betId = tranId; + String betKey = requestBody.getString("gameRound")+requestBody.getString("gameCode")+requestBody.getString("vendorCode")+requestBody.getString("username"); + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("Y")) { + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(tranId); + if(cntTr > 0) { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + response = new ThenutResponse(); + response.setBalance(balance); + response.setErrorCode(101); + response.setMessage("이미 존재하는 트랜잭션"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX + "Response Body: " + response.toString()); + return new ResponseEntity(response, httpStatus); + } + } + + if(siteVendorInfo.get("lastInVendorIdx")==null || "0".equals(siteVendorInfo.get("lastInVendorIdx").toString())) { + HashMap memParam = new HashMap<>(); + memParam.put("siteIdx", siteIdx); + memParam.put("memberIdx", memberIdx); + memParam.put("lastInVendorIdx", Integer.parseInt(siteVendorInfo.get("vendorIdx").toString())); + int updResult = siteService.updMemLastVendorIdx(memParam); + } else { + int lastInVendorIdx = Integer.parseInt(siteVendorInfo.get("lastInVendorIdx").toString()); + if(lastInVendorIdx != vendorIdx) { + log.error(LOG_PREFIX+ "VendorIdx doesn't match"); + response = new ThenutResponse(); + response.setErrorCode(-1); + response.setMessage("VendorIdx doesn't match"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX + "Response Body: " + response.toString()); + return new ResponseEntity(response, httpStatus); + } + } + + + long siteCredit = Long.parseLong(siteVendorInfo.get("credit").toString()); + // ##--isTransfer 처리-## + if(siteCredit < amount && IS_TRANSFER.equals("N")) { + response = new ThenutResponse(); + response.setErrorCode(-9); + response.setMessage("NO_SITE_CREDIT"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX + "Response Body: " + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + // 최대 베팅 금액 처리 (userMaxBet 우선 적용) + long siteMaxBet = Long.parseLong(siteVendorInfo.get("siteMaxBet").toString()); + long userMaxBet = 0; + if(siteVendorInfo.get("userMaxBet") != null && !siteVendorInfo.get("userMaxBet").toString().isEmpty()) { + try { + userMaxBet = Long.parseLong(siteVendorInfo.get("userMaxBet").toString()); + } catch (NumberFormatException e) { + userMaxBet = 0; + } + } + + // 최종 maxBet 결정: userMaxBet이 0이면 siteMaxBet 사용, 0이 아니면 userMaxBet 사용 + long finalMaxBet = (userMaxBet > 0) ? userMaxBet : siteMaxBet; + log.info(LOG_PREFIX+ "MaxBet Info - siteMaxBet: " + siteMaxBet + ", userMaxBet: " + userMaxBet + ", finalMaxBet: " + finalMaxBet); + + if(finalMaxBet < amount) { + log.error(LOG_PREFIX+ "MAX_BET_AMOUNT_OVER"); + log.error(LOG_PREFIX+ "finalMaxBet : " + finalMaxBet +", amount : " + amount); + response = new ThenutResponse(); + response.setErrorCode(-1); + response.setMessage("MAX_BET_AMOUNT_OVER"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX + "Response Body: " + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "thenut"); + tranParam.put("vendorTranKey", betKey); + tranParam.put("gameType", gameType); + tranParam.put("gameId", gameId); + tranParam.put("gameIdx", gameName); + tranParam.put("tranType", "debit"); + tranParam.put("depositAmt", amount); + tranParam.put("creditAmt", "0"); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("betKey", betKey); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "thenut"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", gameName); + callBackObj.put("gameId", gameId); + callBackObj.put("gameType", gameType); + callBackObj.put("tranType", "debit"); + callBackObj.put("debit", amount); + callBackObj.put("credit", 0); + callBackObj.put("isCancel", 0); + callBackObj.put("isBonus", 0); + callBackObj.put("isData", "N"); + callBackObj.put("requestAt", betDateTimeStr); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("N")) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + log.info(LOG_PREFIX + "-----INSERT_BET_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_BET_END-----"); + + log.info(LOG_PREFIX + "SEND_BET request body: " + callBackObj.toString()); + JSONObject resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + log.info(LOG_PREFIX + "SEND_BET status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_BET response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + response = new ThenutResponse(); + response.setBalance(balance); + response.setErrorCode(0); + response.setMessage("SUCCESS"); + httpStatus = HttpStatus.OK; + } else if(resData.getLong("result_code") == 98) { + int balance = resData.getInt("balance"); + response = new ThenutResponse(); + response.setBalance(balance); + response.setErrorCode(101); + response.setMessage("이미 존재하는 트랜잭션"); + httpStatus = HttpStatus.OK; + } else if(resData.getLong("result_code") == 80) { + int balance = resData.getInt("balance"); + response = new ThenutResponse(); + response.setBalance(balance); + response.setErrorCode(102); + response.setMessage("잔고 부족"); + httpStatus = HttpStatus.OK; + } else { + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + log.error(LOG_PREFIX+ msg); + response = new ThenutResponse(); + response.setErrorCode(500); + response.setMessage("알수없는 에러"); + httpStatus = HttpStatus.OK; + } + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + int afBalance = balance - amount; + + if(balance < amount) { + response.setBalance(balance); + response.setErrorCode(102); + response.setMessage("잔고 부족"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "Response::금액을 확인하여 주세요::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + log.info(LOG_PREFIX + "-----INSERT_BET_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_BET_END-----"); + + tranParam.put("balance", afBalance); + tranParam.put("preBalance", balance); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + response.setBalance(afBalance); + response.setErrorCode(0); + response.setMessage("SUCCESS"); + httpStatus = HttpStatus.OK; + + if(siteVendorInfo.get("siteCbUrl") != null && !"".equals(siteVendorInfo.get("siteCbUrl").toString())) { + callBackObj.put("balance", afBalance); + asyncCallBackService.asyncChangeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX + "ConnectTimeoutException: " + rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX + "SocketTimeoutException: " + rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX + "InterruptedException: " + rae.getMessage()); + } + + response = new ThenutResponse(); + response.setErrorCode(-1); + response.setMessage("TIMEOUT_ERROR"); + httpStatus = HttpStatus.OK; + + } catch (Exception e) { + log.error(LOG_PREFIX + "Exception: " + e.getMessage()); + response = new ThenutResponse(); + response.setErrorCode(-9); + response.setMessage("BALANCE_SERVER_ERROR"); + httpStatus = HttpStatus.OK; + } + + ResponseEntity res = new ResponseEntity(response, httpStatus); + log.error(LOG_PREFIX + "Response Body: " + response.toString()); + + return res; + } + + + @ResponseBody + @RequestMapping(path = "/result") + public ResponseEntity callResult(HttpServletRequest request, @RequestBody net.sf.json.JSONObject requestBody) throws Exception { + ThenutResponse response = null; + HttpStatus httpStatus = null; + + String thenutUsername = requestBody.getString("username"); + long siteIdx = 0L; + try { + siteIdx = Long.parseLong(thenutUsername.substring(0, 3), 16); + } catch (NumberFormatException e) { + log.error("#-CB::THENUT::callResult::Invalid username format (hex expected): {}", thenutUsername); + response = new ThenutResponse(); + response.setBalance(0); + response.setErrorCode(-1); + response.setMessage("Invalid username format (hex expected)"); + return new ResponseEntity(response, HttpStatus.OK); + } + String memberId = thenutUsername.substring(3, thenutUsername.length()); + long transactionId = requestBody.getLong("transactionId"); + long refererId = requestBody.getLong("refererId"); + String transactionType = requestBody.getString("transactionType"); + + final String LOG_PREFIX = "#-CB::THENUT::callResult::"+memberId+"::"+transactionId+"::"+transactionType+":::"; + log.info(LOG_PREFIX+ "Request::" + requestBody.toString()); + + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "thenut"); + sParam.put("vendorGameCode", requestBody.getString("vendorCode")); + log.info(LOG_PREFIX + "getSiteVendorInfo::"+sParam.toString()); + HashMap siteVendorInfo = siteService.getSiteVendorInfo(sParam); + if(siteVendorInfo == null) { + response = new ThenutResponse(); + response.setErrorCode(-1); + response.setMessage("존재하지 않는 회원입니다."); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX + "Response Body: " + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + // ##--isTransfer 처리-## + final String IS_TRANSFER = siteVendorInfo.get("isTransfer").toString(); + + try { + // "processed_at":"2025-01-16T09:25:23.000000Z" + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS"); + String betDateTimeStr = requestBody.getString("betAt"); + log.info(LOG_PREFIX+ "========== BF_betDateTimeStr::" + betDateTimeStr); + betDateTimeStr = betDateTimeStr.substring(0, 19); + betDateTimeStr = betDateTimeStr.replace("T", " "); + log.info(LOG_PREFIX+ "========== AF_betDateTimeStr::" + betDateTimeStr); + + int amount = requestBody.getInt("amount"); + String gameType = requestBody.getString("gameType"); + String gameId = requestBody.getString("gameCode"); + String gameName = requestBody.getString("gameTitle"); + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + String tranId = Long.toString(transactionId); + String betId = Long.toString(refererId); + String betKey = requestBody.getString("gameRound")+requestBody.getString("gameCode")+requestBody.getString("vendorCode")+requestBody.getString("username"); + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("Y")) { + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(tranId); + if(cntTr > 0) { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + response = new ThenutResponse(); + response.setBalance(balance); + response.setErrorCode(101); + response.setMessage("이미 존재하는 트랜잭션"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX + "Response Body: " + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + // 베팅 체크 + int cntBet = siteService.getBetIdCheck2(betId); + if(cntBet == 0) { + // 처리한 베팅 존재X + log.error(LOG_PREFIX+ "처리한 베팅 존재X"); + response = new ThenutResponse(); + response.setErrorCode(101); + response.setMessage("처리한 베팅 존재X"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX + "Response Body: " + response.toString()); + return new ResponseEntity(response, httpStatus); + } + } + + if(siteVendorInfo.get("lastInVendorIdx")==null || "0".equals(siteVendorInfo.get("lastInVendorIdx").toString())) { + HashMap memParam = new HashMap<>(); + memParam.put("siteIdx", siteIdx); + memParam.put("memberIdx", memberIdx); + memParam.put("lastInVendorIdx", Integer.parseInt(siteVendorInfo.get("vendorIdx").toString())); + int updResult = siteService.updMemLastVendorIdx(memParam); + } else { + int lastInVendorIdx = Integer.parseInt(siteVendorInfo.get("lastInVendorIdx").toString()); + if(lastInVendorIdx != vendorIdx) { + log.error(LOG_PREFIX+ "VendorIdx doesn't match"); + response = new ThenutResponse(); + response.setErrorCode(-1); + response.setMessage("VendorIdx doesn't match"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX + "Response Body: " + response.toString()); + return new ResponseEntity(response, httpStatus); + } + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "thenut"); + tranParam.put("vendorTranKey", betKey); + tranParam.put("gameType", gameType); + tranParam.put("gameId", gameId); + if(transactionType.equals("PROMO_WIN")) { + tranParam.put("gameIdx", "TheNut Promo"); + } else { + tranParam.put("gameIdx", gameName); + } + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + if(transactionType.equals("CANCEL")) { + tranParam.put("isCancel", "Y"); + } else { + tranParam.put("isCancel", "N"); + } + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("betKey", betKey); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "thenut"); + callBackObj.put("gameIdx", vendorIdx); + if(transactionType.equals("PROMO_WIN")) { + callBackObj.put("gameKey", "TheNut Promo"); + } else { + callBackObj.put("gameIdx", gameName); + } + callBackObj.put("gameId", gameId); + callBackObj.put("gameType", gameType); + callBackObj.put("tranType", "credit"); + callBackObj.put("debit", 0); + callBackObj.put("credit", amount); + if(transactionType.equals("CANCEL")) { + callBackObj.put("isCancel", 1); + } else { + callBackObj.put("isCancel", 0); + } + if(transactionType.equals("PROMO_WIN")) { + callBackObj.put("isBonus", 1); + } else { + callBackObj.put("isBonus", 0); + } + callBackObj.put("isData", "N"); + callBackObj.put("requestAt", betDateTimeStr); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("N")) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + log.info(LOG_PREFIX + "-----INSERT_RESULT_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_RESULT_END-----"); + + log.info(LOG_PREFIX + "SEND_RESULT request body: " + callBackObj.toString()); + JSONObject resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + log.info(LOG_PREFIX + "SEND_RESULT status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_RESULT response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + response = new ThenutResponse(); + response.setBalance(balance); + response.setErrorCode(0); + response.setMessage("SUCCESS"); + httpStatus = HttpStatus.OK; + } else if(resData.getLong("result_code") == 98) { + int balance = resData.getInt("balance"); + response = new ThenutResponse(); + response.setBalance(balance); + response.setErrorCode(101); + response.setMessage("이미 존재하는 트랜잭션"); + httpStatus = HttpStatus.OK; + } else { + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + log.error(LOG_PREFIX+ msg); + response = new ThenutResponse(); + response.setErrorCode(500); + response.setMessage("알수없는 에러"); + httpStatus = HttpStatus.OK; + } + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + int afBalance = balance + amount; + + log.info(LOG_PREFIX + "-----INSERT_RESULT_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_RESULT_END-----"); + + tranParam.put("balance", afBalance); + tranParam.put("preBalance", balance); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + response.setBalance(afBalance); + response.setErrorCode(0); + response.setMessage("SUCCESS"); + httpStatus = HttpStatus.OK; + + if(siteVendorInfo.get("siteCbUrl") != null && !"".equals(siteVendorInfo.get("siteCbUrl").toString())) { + callBackObj.put("balance", afBalance); + asyncCallBackService.asyncChangeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX + "ConnectTimeoutException: " + rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX + "SocketTimeoutException: " + rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX + "InterruptedException: " + rae.getMessage()); + } + + response = new ThenutResponse(); + response.setErrorCode(-1); + response.setMessage("TIMEOUT_ERROR"); + httpStatus = HttpStatus.OK; + + } catch (Exception e) { + log.error(LOG_PREFIX + "Exception: " + e.getMessage()); + response = new ThenutResponse(); + response.setErrorCode(-9); + response.setMessage("BALANCE_SERVER_ERROR"); + httpStatus = HttpStatus.OK; + } + + ResponseEntity res = new ResponseEntity(response, httpStatus); + log.error(LOG_PREFIX + "Response Body: " + response.toString()); + + return res; + } +} diff --git a/src/main/java/com/bb/front/CallBackTowerController.java b/src/main/java/com/bb/front/CallBackTowerController.java new file mode 100644 index 0000000..fe36fa2 --- /dev/null +++ b/src/main/java/com/bb/front/CallBackTowerController.java @@ -0,0 +1,531 @@ +package com.bb.front; + +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Random; + +import jakarta.servlet.http.HttpServletRequest; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +import com.bb.jwt.JwtManager; +import com.bb.service.CallBackService; +import com.bb.service.SiteService; + +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import net.sf.json.JSONObject; + +@RestController +@Slf4j +@RequestMapping("/api/callback/tower") +@RequiredArgsConstructor +@SecurityRequirement(name = "Authorization") +public class CallBackTowerController { + + @Autowired + private final JwtManager jwtManager; + + @Autowired + SiteService siteService; + + @Autowired + CallBackService callBackService; + + + + @GetMapping(value = "/api/balance" ) + public @ResponseBody String balance(HttpServletRequest request, ModelMap model) throws Exception { + + String userId = request.getParameter("user_id"); + int siteIdx = Integer.parseInt(userId.substring(0, 3), 16); + String memberId = userId.substring(3, userId.length()); + String authorization = request.getHeader("Authorization").toString(); + final String LOG_PREFIX = "#-CB::tower::"+memberId+"::balance:::"; + log.info("#callback::tower::"+ "SITE_IDX: "+siteIdx+", USER INFO: " + memberId); + + + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "tower"); + sParam.put("callbackKey", authorization); + + HashMap siteApiInfo = siteService.getSiteApiInfoByCallbackKey(sParam); + + if(siteApiInfo == null) { + log.error(LOG_PREFIX+ "Callback Key 불일치"); + + return "E1"; + } + + if(siteApiInfo.get("memberIdx") == null) { + log.error(LOG_PREFIX+ "존재하지 않는 회원"); + return "E2"; + } + + org.codehaus.jettison.json.JSONObject member = new org.codehaus.jettison.json.JSONObject(); + member.put("userId", memberId); + org.codehaus.jettison.json.JSONObject resData = callBackService.getBalance(siteApiInfo, member); + if(resData == null) { + log.error(LOG_PREFIX+ "BALANCE_CALLBACK_ERROR"); + return "E3"; + } + String balance = resData.getString("balance"); + + + try { + + }catch(Exception e) { + log.error(LOG_PREFIX + "ERROR {}", e.toString()); + } + log.info(LOG_PREFIX+ "balance {}", balance); + return balance; + } + + + @GetMapping(value = "/api/bet" ) + public @ResponseBody JSONObject bet(HttpServletRequest request, ModelMap model) throws Exception { + + JSONObject res = new JSONObject(); + // 회원ID + String userId = request.getParameter("user_id"); + + + int siteIdx = Integer.parseInt(userId.substring(0, 3), 16); + String memberId = userId.substring(3, userId.length()); + String authorization = request.getHeader("Authorization").toString(); + final String LOG_PREFIX = "#-CB::tower::"+memberId+"::"+request.getParameter("transaction_id")+"::BET:::"; + log.info(LOG_PREFIX+ "#callback::tower::"+ "SITE_IDX: "+siteIdx+", USER INFO: " + memberId); + log.info(LOG_PREFIX+ "request: " + request.toString()); + + + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "tower"); + sParam.put("callbackKey", authorization); + /* + * CAST(si.siteIdx AS CHAR) AS siteIdx, + si.siteId, + CAST(sm.memberIdx AS CHAR) AS memberIdx, + sm.memberId, + si.siteCbUrl, + IFNULL(sa.vendorApiId, vi.vendorApiId) AS vendorApiId + */ + + HashMap siteApiInfo = siteService.getSiteApiInfoByCallbackKey(sParam); + + if(siteApiInfo == null) { + log.error(LOG_PREFIX+ "Callback Key 불일치"); + res.put("status", "error") ; + return res; + } + + if(siteApiInfo.get("memberIdx") == null) { + log.error(LOG_PREFIX+ "존재하지 않는 회원"); + res.put("status", "error") ; + return res; + } + + + sParam.put("vendorGameCode", request.getParameter("vendorCode")); + log.info(LOG_PREFIX + "getSiteVendorInfo::"+sParam.toString()); + HashMap siteVendorInfo = siteService.getSiteVendorInfo(sParam); + if(siteVendorInfo.get("vendorIdx") == null) { + log.error(LOG_PREFIX+ "존재하지 않는 벤더코드"); + res.put("status", "error") ; + return res; + } + + + // 배팅의 고유ID + String transactionId = request.getParameter("transaction_id"); + + // 게임ID (optional) + String gameId = request.getParameter("game_id"); + + // 벤더코드 + String vendorCode = request.getParameter("vendorCode"); + + // 게임코드 + String gameCode = request.getParameter("gameCode"); + + // 게임타이틀 + String gameTitle = gameCode; + Enumeration params = request.getParameterNames(); + while (params.hasMoreElements()) { + String paramName = (String) params.nextElement(); + if(paramName.equals("gameTitle")) { + gameTitle = request.getParameter(paramName); + } + } + + + // 배팅액 + String amountS = request.getParameter("amount"); + long amount = 0; + Double rrr = Double.parseDouble(amountS); + amount = rrr.longValue(); + + try { + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + long siteCredit = Long.parseLong(siteVendorInfo.get("credit").toString()); + if(siteCredit < amount) { + log.error(LOG_PREFIX+ "NO_SITE_CREDIT"); + res.put("status", "error") ; + return res; + } + + // 최대 베팅 금액 처리 (userMaxBet 우선 적용) + long siteMaxBet = Long.parseLong(siteVendorInfo.get("siteMaxBet").toString()); + long userMaxBet = 0; + if(siteVendorInfo.get("userMaxBet") != null && !siteVendorInfo.get("userMaxBet").toString().isEmpty()) { + try { + userMaxBet = Long.parseLong(siteVendorInfo.get("userMaxBet").toString()); + } catch (NumberFormatException e) { + userMaxBet = 0; + } + } + + // 최종 maxBet 결정: userMaxBet이 0이면 siteMaxBet 사용, 0이 아니면 userMaxBet 사용 + long finalMaxBet = (userMaxBet > 0) ? userMaxBet : siteMaxBet; + log.info(LOG_PREFIX+ "MaxBet Info - siteMaxBet: " + siteMaxBet + ", userMaxBet: " + userMaxBet + ", finalMaxBet: " + finalMaxBet); + + if(finalMaxBet < amount) { + log.error(LOG_PREFIX+ "MAX_BET_AMOUNT_OVER - finalMaxBet: " + finalMaxBet); + res.put("status", "error") ; + return res; + } + + String vendorTranKey = transactionId; + String tranId = transactionId; + String betId = transactionId; + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + String gameName = gameTitle; + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "tower"); + tranParam.put("vendorTranKey", vendorTranKey); + tranParam.put("gameType", "slot"); + tranParam.put("gameId", gameCode); + tranParam.put("gameIdx", gameName); + tranParam.put("tranType", "debit"); + tranParam.put("depositAmt", amount); + tranParam.put("creditAmt", "0"); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + log.info(LOG_PREFIX + "-----INSERT_BET_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_BET_END-----"); + + org.codehaus.jettison.json.JSONObject callBackObj = new org.codehaus.jettison.json.JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "tower"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", gameName); + callBackObj.put("gameId", gameCode); + callBackObj.put("gameType", "slot"); + callBackObj.put("tranType", "debit"); + callBackObj.put("debit", amount); + callBackObj.put("credit", 0); + callBackObj.put("isCancel", 0); + callBackObj.put("isBonus", 0); + // callBackObj.put("requestAt", betDateTimeStr); + log.info(LOG_PREFIX + "SEND_BET request body: " + callBackObj.toString()); + org.codehaus.jettison.json.JSONObject resData = callBackService.changeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + log.info(LOG_PREFIX + "SEND_BET status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_BET response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + int rescreditUpdate = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + String balance = resData.getString("balance"); + res.put("status", "OK"); + res.put("balance", balance); + + + } else if(resData.getLong("result_code") == 98) { + String balance = resData.getString("balance"); + res.put("status", "OK"); + res.put("balance", balance); + } else if(resData.getLong("result_code") == 80) { + String balance = resData.getString("balance"); + res.put("status", "error"); + res.put("balance", balance); + } else { + res.put("status", "error"); + } + + + + log.info("res {}", res); + }catch(Exception e) { + log.error(LOG_PREFIX + "ERROR: " + e.toString()); + } + return res; + } + + + @GetMapping(value = "/api/result" ) + public @ResponseBody JSONObject result(HttpServletRequest request, ModelMap model) throws Exception { + + JSONObject res = new JSONObject(); + // 회원ID + String userId = request.getParameter("user_id"); + + // 거래 유형 + String transactionType = request.getParameter("transaction_type"); + + // 배팅의 고유ID + String transactionId = request.getParameter("transaction_id"); + + // 게임ID (optional) + String gameId = request.getParameter("game_id"); + + // 벤더코드 + String vendorCode = request.getParameter("vendorCode"); + + // 게임코드 + String gameCode = request.getParameter("gameCode"); + + // 게임타이틀 + String gameTitle = gameCode; + Enumeration params = request.getParameterNames(); + while (params.hasMoreElements()) { + String paramName = (String) params.nextElement(); + if(paramName.equals("gameTitle")) { + gameTitle = request.getParameter(paramName); + } + } + + // 금액 + String amountS = request.getParameter("amount"); + long amount = 0; + Double rrr = Double.parseDouble(amountS); + amount = rrr.longValue(); + + // 거래의 고유ID + String reference = request.getParameter("reference"); + + // 취소할 reference (CANCEL_WIN 시에만 전송) + String referenceForCancel = request.getParameter("reference_for_cancel"); + + // 배팅상세내역 JSON (optional) + String bettingData = request.getParameter("betting_data"); + + + int siteIdx = Integer.parseInt(userId.substring(0, 3), 16); + String memberId = userId.substring(3, userId.length()); + String authorization = request.getHeader("Authorization").toString(); + final String LOG_PREFIX = "#-CB::tower::"+memberId+"::"+request.getParameter("transaction_id")+"::RESULT:::"; + log.info(LOG_PREFIX+ "#callback::tower::"+ "SITE_IDX: "+siteIdx+", USER INFO: " + memberId); + log.info(LOG_PREFIX+ "request: " + request.toString()); + + + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "tower"); + sParam.put("callbackKey", authorization); + /* + * CAST(si.siteIdx AS CHAR) AS siteIdx, + si.siteId, + CAST(sm.memberIdx AS CHAR) AS memberIdx, + sm.memberId, + si.siteCbUrl, + IFNULL(sa.vendorApiId, vi.vendorApiId) AS vendorApiId + */ + + HashMap siteApiInfo = siteService.getSiteApiInfoByCallbackKey(sParam); + + if(siteApiInfo == null) { + log.error(LOG_PREFIX+ "Callback Key 불일치"); + res.put("status", "error") ; + return res; + } + + if(siteApiInfo.get("memberIdx") == null) { + log.error(LOG_PREFIX+ "존재하지 않는 회원"); + res.put("status", "error") ; + return res; + } + + + sParam.put("vendorGameCode", request.getParameter("vendorCode")); + log.info(LOG_PREFIX + "getSiteVendorInfo::"+sParam.toString()); + HashMap siteVendorInfo = siteService.getSiteVendorInfo(sParam); + if(siteVendorInfo.get("vendorIdx") == null) { + log.error(LOG_PREFIX+ "존재하지 않는 벤더코드"); + res.put("status", "error") ; + return res; + } + + + try { + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + + String vendorTranKey = transactionId+transactionType; + String tranId = transactionId +transactionType; + String betId = transactionId; + + if(reference != null && !"".equals(reference)) { + // betId = reference; + } + + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + String gameName = gameTitle; + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "tower"); + tranParam.put("vendorTranKey", vendorTranKey); + tranParam.put("gameType", "slot"); + tranParam.put("gameId", gameCode); + tranParam.put("gameIdx", gameName); + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt","0" ); + tranParam.put("creditAmt", amount); + + if("CANCEL".equals(transactionType) || "CANCEL_WIN".equals(transactionType)) { + tranParam.put("isCancel", "Y"); + }else { + tranParam.put("isCancel", "N"); + } + + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + log.info(LOG_PREFIX + "-----INSERT_RESULT_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_RESULT_END-----"); + + org.codehaus.jettison.json.JSONObject callBackObj = new org.codehaus.jettison.json.JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "tower"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", gameName); + callBackObj.put("gameId", gameCode); + callBackObj.put("gameType", "slot"); + callBackObj.put("tranType", "credit"); + callBackObj.put("debit",0 ); + callBackObj.put("credit", amount); + if("CANCEL".equals(transactionType) || "CANCEL_WIN".equals(transactionType)) { + callBackObj.put("isCancel", 1); + }else { + callBackObj.put("isCancel", 0); + } + if("PROMO_WIN".equals(transactionType) ) { + callBackObj.put("isBonus", 1); + }else { + callBackObj.put("isBonus", 0); + } + // callBackObj.put("requestAt", betDateTimeStr); + log.info(LOG_PREFIX + "SEND_RESULT request body: " + callBackObj.toString()); + org.codehaus.jettison.json.JSONObject resData = callBackService.changeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + log.info(LOG_PREFIX + "SEND_RESULT status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_RESULT response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + int rescreditUpdate = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + String balance = resData.getString("balance"); + res.put("status", "OK"); + res.put("balance", balance); + + + } else if(resData.getLong("result_code") == 98) { + String balance = resData.getString("balance"); + res.put("status", "OK"); + res.put("balance", balance); + } else if(resData.getLong("result_code") == 80) { + String balance = resData.getString("balance"); + res.put("status", "error"); + res.put("balance", balance); + } else { + res.put("status", "error"); + } + + + + log.info("res {}", res); + }catch(Exception e) { + log.error(LOG_PREFIX + "ERROR: " + e.toString()); + } + return res; + } + + + + private String makeApiKey(String param) { + + int n = 20; // n자리 쿠폰 + char[] chs = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' ,'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; + + + Random rd = new Random(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < n; i++) { + char ch = chs[rd.nextInt(chs.length)]; + sb.append(ch); + } + return param + sb.toString(); + + + } + + +} + diff --git a/src/main/java/com/bb/front/CallBackTplusController.java b/src/main/java/com/bb/front/CallBackTplusController.java new file mode 100644 index 0000000..79cffa1 --- /dev/null +++ b/src/main/java/com/bb/front/CallBackTplusController.java @@ -0,0 +1,1092 @@ +package com.bb.front; + +import java.net.SocketTimeoutException; +import java.text.SimpleDateFormat; +import java.util.HashMap; +import java.util.Random; + +import org.apache.http.conn.ConnectTimeoutException; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.ResourceAccessException; +import org.springframework.web.reactive.function.client.WebClient; + +import com.bb.jwt.JwtManager; +import com.bb.model.ApiResponse; +import com.bb.model.TplusCBData; +import com.bb.model.TplusCBRequest; +import com.bb.model.TplusData; +import com.bb.model.TplusResponse; +import com.bb.service.CallBackService; +import com.bb.service.SiteService; + +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@RestController +@Slf4j +@RequestMapping("/api/callback/tplus") +@RequiredArgsConstructor +@SecurityRequirement(name = "Authorization") +public class CallBackTplusController { + + @Autowired + private final JwtManager jwtManager; + + @Autowired + SiteService siteService; + + @Autowired + CallBackService callBackService; + + @Autowired + WebClient webClient; + + + @ResponseBody + @RequestMapping(path = "/auth") + public ResponseEntity callAuth(HttpServletRequest request, @RequestBody net.sf.json.JSONObject requestBody) throws Exception { + TplusResponse response = null; + TplusData data = null; + HttpStatus httpStatus = null; + + String apiKey = requestBody.getString("api_key"); + net.sf.json.JSONObject params = requestBody.getJSONObject("params"); + String siteUsername = params.getString("user_name"); + + if(siteUsername == null || siteUsername.equals("") || siteUsername.equals("invalid-user")) { + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("존재하지 않는 회원입니다."); + httpStatus = HttpStatus.OK; + return new ResponseEntity(response, httpStatus); + } + + long siteIdx = Long.parseLong(siteUsername.substring(0, 3), 16); + String memberId = siteUsername.substring(3, siteUsername.length()); + final String LOG_PREFIX = "#-CB::TPLUS::"+memberId+"::callAuth:::"; + log.info(LOG_PREFIX+ "Request::" + requestBody.toString()); + + try { + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "tplus"); + sParam.put("apiKey", apiKey); + log.info(LOG_PREFIX + "getSiteVendorInfo::"+sParam.toString()); + HashMap siteApiInfo = siteService.getSiteApiInfoByApiKey(sParam); + if(siteApiInfo == null) { + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("API키가 일치하지 않습니다."); + httpStatus = HttpStatus.OK; + return new ResponseEntity(response, httpStatus); + } + + if(siteApiInfo.get("memberIdx") == null) { + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("존재하지 않는 회원입니다."); + httpStatus = HttpStatus.OK; + return new ResponseEntity(response, httpStatus); + } + + data = new TplusData(); + data.setUserName(siteUsername); + response = new TplusResponse(); + response.setCode(0); + response.setData(data); + httpStatus = HttpStatus.OK; + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("ResourceAccessException"); + httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("Exception"); + httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; + } + + ResponseEntity res = new ResponseEntity(response, httpStatus); + log.info(LOG_PREFIX+ "Response::" + response.toString()); + + return res; + } + + + @ResponseBody + @RequestMapping(path = "/balance") + public ResponseEntity callBalance(HttpServletRequest request, @RequestBody net.sf.json.JSONObject requestBody) throws Exception { + TplusResponse response = null; + TplusData data = null; + HttpStatus httpStatus = null; + + String apiKey = requestBody.getString("api_key"); + net.sf.json.JSONObject params = requestBody.getJSONObject("params"); + String siteUsername = params.getString("user_name"); + + if(siteUsername == null || siteUsername.equals("") || siteUsername.equals("invalid-user")) { + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("존재하지 않는 회원입니다."); + httpStatus = HttpStatus.OK; + return new ResponseEntity(response, httpStatus); + } + + long siteIdx = Long.parseLong(siteUsername.substring(0, 3), 16); + String memberId = siteUsername.substring(3, siteUsername.length()); + final String LOG_PREFIX = "#-CB::TPLUS::"+memberId+"::callBalance:::"; + log.info(LOG_PREFIX+ "Request::" + requestBody.toString()); + + try { + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "tplus"); + sParam.put("apiKey", apiKey); + log.info(LOG_PREFIX + "getSiteVendorInfo::"+sParam.toString()); + HashMap siteApiInfo = siteService.getSiteApiInfoByApiKey(sParam); + if(siteApiInfo == null) { + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("API키가 일치하지 않습니다."); + httpStatus = HttpStatus.OK; + return new ResponseEntity(response, httpStatus); + } + + if(siteApiInfo.get("memberIdx") == null) { + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("존재하지 않는 회원입니다."); + httpStatus = HttpStatus.OK; + return new ResponseEntity(response, httpStatus); + } + + JSONObject member = new JSONObject(); + member.put("userId", memberId); + JSONObject resData = callBackService.getBalance(siteApiInfo, member); + if(resData == null) { + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("BALANCE_CALLBACK_ERROR"); + httpStatus = HttpStatus.OK; + return new ResponseEntity(response, httpStatus); + } + log.info(LOG_PREFIX + "resData::"+resData.toString()); + int balance = resData.getInt("balance"); + + data = new TplusData(); + data.setBalance((double) balance); + data.setCurrency("KRW"); + response = new TplusResponse(); + response.setCode(0); + response.setData(data); + httpStatus = HttpStatus.OK; + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("ResourceAccessException"); + httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("Exception"); + httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; + } + + ResponseEntity res = new ResponseEntity(response, httpStatus); + log.info(LOG_PREFIX+ "Response::" + response.toString()); + + return res; + } + + + @ResponseBody + @RequestMapping(path = "/bet") + public ResponseEntity callBet(HttpServletRequest request, @RequestBody TplusCBRequest requestBody) throws Exception { + TplusResponse response = null; + TplusData data = null; + HttpStatus httpStatus = null; + + String apiKey = requestBody.getApiKey(); + TplusCBData param = requestBody.getParam(); + String siteUsername = param.getUserName(); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + String betDateTimeStr = param.getProcessedAt(); + if(betDateTimeStr == null || betDateTimeStr.equals("")) { + betDateTimeStr = sdf.format(System.currentTimeMillis()); + } else { + betDateTimeStr = betDateTimeStr.replace("T", " ").replace("Z", ""); + } + param.setProcessedAt(betDateTimeStr); + + if(siteUsername == null || siteUsername.equals("") || siteUsername.equals("invalid-user")) { + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("존재하지 않는 회원입니다."); + httpStatus = HttpStatus.OK; + return new ResponseEntity(response, httpStatus); + } + + long siteIdx = Long.parseLong(siteUsername.substring(0, 3), 16); + String memberId = siteUsername.substring(3, siteUsername.length()); + String vendorTranKey = param.getTransactionKey(); + String tranId = param.getTransactionKey(); + String betId = param.getPairTransactionKey(); + if(betId == null || betId.equals("")) { + betId = param.getTransactionKey(); + } + + final String LOG_PREFIX = "#-CB::TPLUS::"+memberId+"::"+tranId+"::callBet:::"; + log.info(LOG_PREFIX+ "Request::" + requestBody.toString()); + + try { + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "tplus"); + sParam.put("vendorGameCode", param.getThirdParty()); + log.info(LOG_PREFIX + "getSiteVendorInfo::"+sParam.toString()); + HashMap siteVendorInfo = siteService.getSiteVendorInfo(sParam); + if(siteVendorInfo == null) { + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("존재하지 않는 회원입니다"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "존재하지 않는 회원입니다::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + if(!apiKey.equals(siteVendorInfo.get("vendorApiKey").toString())) { + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("API키가 일치하지 않습니다"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "API키가 일치하지 않습니다::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + if(siteVendorInfo.get("lastInVendorIdx")==null || "0".equals(siteVendorInfo.get("lastInVendorIdx").toString())) { + HashMap memParam = new HashMap<>(); + memParam.put("siteIdx", siteIdx); + memParam.put("memberIdx", memberIdx); + memParam.put("lastInVendorIdx", Integer.parseInt(siteVendorInfo.get("vendorIdx").toString())); + int updResult = siteService.updMemLastVendorIdx(memParam); + } else { + Long lastInVendorIdx = Long.parseLong(siteVendorInfo.get("lastInVendorIdx").toString()); + Long vendorIdx = Long.parseLong(siteVendorInfo.get("vendorIdx").toString()); + if(lastInVendorIdx.longValue() != vendorIdx.longValue()) { + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("VendorIdx doesn't match"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "VendorIdx doesn't match::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + } + + Double amountD = param.getAmount(); + if(amountD.intValue() < 0) { + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("금액이 올바르지 않습니다"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "금액이 올바르지 않습니다::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + int amount = Math.abs(amountD.intValue()); + + long siteCredit = Long.parseLong(siteVendorInfo.get("credit").toString()); + if(siteCredit < amount) { + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("NO_SITE_CREDIT"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "NO_SITE_CREDIT::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + // 최대 베팅 금액 처리 (userMaxBet 우선 적용) + long siteMaxBet = Long.parseLong(siteVendorInfo.get("siteMaxBet").toString()); + long userMaxBet = 0; + if(siteVendorInfo.get("userMaxBet") != null && !siteVendorInfo.get("userMaxBet").toString().isEmpty()) { + try { + userMaxBet = Long.parseLong(siteVendorInfo.get("userMaxBet").toString()); + } catch (NumberFormatException e) { + userMaxBet = 0; + } + } + + // 최종 maxBet 결정: userMaxBet이 0이면 siteMaxBet 사용, 0이 아니면 userMaxBet 사용 + long finalMaxBet = (userMaxBet > 0) ? userMaxBet : siteMaxBet; + log.info(LOG_PREFIX+ "MaxBet Info - siteMaxBet: " + siteMaxBet + ", userMaxBet: " + userMaxBet + ", finalMaxBet: " + finalMaxBet); + + if(finalMaxBet < amount) { + log.error(LOG_PREFIX+ "MAX_BET_AMOUNT_OVER"); + log.error(LOG_PREFIX+ "finalMaxBet : " + finalMaxBet +", amount : " + amount); + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("MAX_BET_AMOUNT_OVER"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "MAX_BET_AMOUNT_OVER::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + String gameName = param.getGameName(); + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "tplus"); + tranParam.put("vendorTranKey", vendorTranKey); + tranParam.put("gameType", "slot"); + tranParam.put("gameId", param.getGameSymbol()); + tranParam.put("gameIdx", gameName); + tranParam.put("tranType", "debit"); + tranParam.put("depositAmt", amount); + tranParam.put("creditAmt", "0"); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + log.info(LOG_PREFIX + "-----INSERT_BET_START-----"); + long startTime = System.currentTimeMillis(); + siteService.commonBetinsert(tranParam); + long endTime = System.currentTimeMillis(); // 코드 실행 후에 시간 받아오기 + double diffTime = (startTime - endTime)/1000.0; //두 시간에 차 계산 + if(diffTime < -1.0) { + log.error(LOG_PREFIX + "commonBetinsert::배팅 쓰기지연::"+diffTime+"초 지연발생"); + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("BET_TIMEOUT_ERROR"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "BET_TIMEOUT_ERROR::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + log.info(LOG_PREFIX + "-----INSERT_BET_END-----"); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "tplus"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", gameName); + callBackObj.put("gameType", "slot"); + callBackObj.put("gameId", param.getGameSymbol()); + callBackObj.put("tranType", "debit"); + callBackObj.put("debit", amount); + callBackObj.put("credit", 0); + callBackObj.put("isCancel", 0); + callBackObj.put("isBonus", 0); + callBackObj.put("requestAt", param.getProcessedAt()); + log.info(LOG_PREFIX + "SEND_BET request body: " + callBackObj.toString()); + JSONObject resData = callBackService.changeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + log.info(LOG_PREFIX + "SEND_BET resData::"+resData.toString()); + log.info(LOG_PREFIX + "SEND_BET status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_BET response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + data = new TplusData(); + data.setBalance((double) balance); + data.setBeforeBalance((double) (balance + amount)); + data.setCurrency("KRW"); + response = new TplusResponse(); + response.setCode(0); + response.setData(data); + httpStatus = HttpStatus.OK; + } else if(resData.getLong("result_code") == 80) { + // 보유금액 초과 + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("금액을 확인하여 주세요"); + httpStatus = HttpStatus.OK; + } else if(resData.getLong("result_code") == 98) { + // 중복자료 + int balance = resData.getInt("balance"); + data = new TplusData(); + data.setBalance((double) balance); + data.setBeforeBalance((double) (balance + amount)); + data.setCurrency("KRW"); + response = new TplusResponse(); + response.setCode(0); + response.setData(data); + httpStatus = HttpStatus.OK; + } else { + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("UNKNOWN_ERROR"); + httpStatus = HttpStatus.OK; + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("TIMEOUT_ERROR"); + httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("BET_SERVER_ERROR"); + httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; + } + + ResponseEntity res = new ResponseEntity(response, httpStatus); + log.info(LOG_PREFIX+ "Response::" + response.toString()); + + return res; + } + + + @ResponseBody + @RequestMapping(path = "/win") + public ResponseEntity callWin(HttpServletRequest request, @RequestBody TplusCBRequest requestBody) throws Exception { + TplusResponse response = null; + TplusData data = null; + HttpStatus httpStatus = null; + + String apiKey = requestBody.getApiKey(); + TplusCBData param = requestBody.getParam(); + String siteUsername = param.getUserName(); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + String betDateTimeStr = param.getProcessedAt(); + if(betDateTimeStr == null || betDateTimeStr.equals("")) { + betDateTimeStr = sdf.format(System.currentTimeMillis()); + } else { + betDateTimeStr = betDateTimeStr.replace("T", " ").replace("Z", ""); + } + param.setProcessedAt(betDateTimeStr); + + if(siteUsername == null || siteUsername.equals("") || siteUsername.equals("invalid-user")) { + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("존재하지 않는 회원입니다."); + httpStatus = HttpStatus.OK; + return new ResponseEntity(response, httpStatus); + } + + long siteIdx = Long.parseLong(siteUsername.substring(0, 3), 16); + String memberId = siteUsername.substring(3, siteUsername.length()); + String tranId = param.getTransactionKey(); + String betId = param.getPairTransactionKey(); + if(betId == null || betId.equals("")) { + betId = param.getTransactionKey(); + } + + final String LOG_PREFIX = "#-CB::TPLUS::"+memberId+"::"+tranId+"::callWin:::"; + log.info(LOG_PREFIX+ "Request::" + requestBody.toString()); + + try { + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "tplus"); + sParam.put("vendorGameCode", param.getThirdParty()); + log.info(LOG_PREFIX + "getSiteVendorInfo::"+sParam.toString()); + HashMap siteVendorInfo = siteService.getSiteVendorInfo(sParam); + if(siteVendorInfo == null) { + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("존재하지 않는 회원입니다"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "존재하지 않는 회원입니다::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + if(!apiKey.equals(siteVendorInfo.get("vendorApiKey").toString())) { + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("API키가 일치하지 않습니다"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "API키가 일치하지 않습니다::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + Double amountD = param.getAmount(); + if(amountD.intValue() < 0) { + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("금액이 올바르지 않습니다"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "금액이 올바르지 않습니다::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + int amount = Math.abs(amountD.intValue()); + + String vendorTranKey = param.getTransactionKey(); + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + String gameName = param.getGameName(); + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "tplus"); + tranParam.put("vendorTranKey", vendorTranKey); + tranParam.put("gameType", "slot"); + tranParam.put("gameId", param.getGameSymbol()); + tranParam.put("gameIdx", gameName); + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + log.info(LOG_PREFIX + "-----INSERT_RESULT_START-----"); + long startTime = System.currentTimeMillis(); + siteService.commonBetinsert(tranParam); + long endTime = System.currentTimeMillis(); // 코드 실행 후에 시간 받아오기 + double diffTime = (startTime - endTime)/1000.0; //두 시간에 차 계산 + if(diffTime < -1.0) { + log.error(LOG_PREFIX + "commonBetinsert::배팅 쓰기지연::"+diffTime+"초 지연발생"); + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("BET_TIMEOUT_ERROR"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "BET_TIMEOUT_ERROR::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + log.info(LOG_PREFIX + "-----INSERT_RESULT_END-----"); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "tplus"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", gameName); + callBackObj.put("gameType", "slot"); + callBackObj.put("gameId", param.getGameSymbol()); + callBackObj.put("tranType", "credit"); + callBackObj.put("debit", 0); + callBackObj.put("credit", amount); + callBackObj.put("isCancel", 0); + callBackObj.put("isBonus", 0); + callBackObj.put("requestAt", param.getProcessedAt()); + log.info(LOG_PREFIX + "SEND_RESULT request body: " + callBackObj.toString()); + JSONObject resData = callBackService.changeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + log.info(LOG_PREFIX + "SEND_RESULT resData::"+resData.toString()); + log.info(LOG_PREFIX + "SEND_RESULT status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_RESULT response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + data = new TplusData(); + data.setBalance((double) balance); + data.setBeforeBalance((double) (balance - amount)); + data.setCurrency("KRW"); + response = new TplusResponse(); + response.setCode(0); + response.setData(data); + httpStatus = HttpStatus.OK; + } else if(resData.getLong("result_code") == 98) { + int balance = resData.getInt("balance"); + data = new TplusData(); + data.setBalance((double) balance); + data.setBeforeBalance((double) (balance - amount)); + data.setCurrency("KRW"); + response = new TplusResponse(); + response.setCode(0); + response.setData(data); + httpStatus = HttpStatus.OK; + } else { + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("UNKNOWN_ERROR"); + httpStatus = HttpStatus.OK; + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("TIMEOUT_ERROR"); + httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("BET_SERVER_ERROR"); + httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; + } + + ResponseEntity res = new ResponseEntity(response, httpStatus); + log.info(LOG_PREFIX+ "Response::" + response.toString()); + + return res; + } + + + @ResponseBody + @RequestMapping(path = "/cancel") + public ResponseEntity callCancel(HttpServletRequest request, @RequestBody TplusCBRequest requestBody) throws Exception { + TplusResponse response = null; + TplusData data = null; + HttpStatus httpStatus = null; + + String apiKey = requestBody.getApiKey(); + TplusCBData param = requestBody.getParam(); + String siteUsername = param.getUserName(); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + String betDateTimeStr = param.getProcessedAt(); + if(betDateTimeStr == null || betDateTimeStr.equals("")) { + betDateTimeStr = sdf.format(System.currentTimeMillis()); + } else { + betDateTimeStr = betDateTimeStr.replace("T", " ").replace("Z", ""); + } + param.setProcessedAt(betDateTimeStr); + + if(siteUsername == null || siteUsername.equals("") || siteUsername.equals("invalid-user")) { + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("존재하지 않는 회원입니다."); + httpStatus = HttpStatus.OK; + return new ResponseEntity(response, httpStatus); + } + + long siteIdx = Long.parseLong(siteUsername.substring(0, 3), 16); + String memberId = siteUsername.substring(3, siteUsername.length()); + String tranId = param.getTransactionKey(); + String betId = param.getPairTransactionKey(); + if(betId == null || betId.equals("")) { + betId = param.getTransactionKey(); + } + + final String LOG_PREFIX = "#-CB::TPLUS::"+memberId+"::"+tranId+"::callCancel:::"; + log.info(LOG_PREFIX+ "Request::" + requestBody.toString()); + + try { + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "tplus"); + sParam.put("vendorGameCode", param.getThirdParty()); + log.info(LOG_PREFIX + "getSiteVendorInfo::"+sParam.toString()); + HashMap siteVendorInfo = siteService.getSiteVendorInfo(sParam); + if(siteVendorInfo == null) { + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("존재하지 않는 회원입니다"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "존재하지 않는 회원입니다::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + if(!apiKey.equals(siteVendorInfo.get("vendorApiKey").toString())) { + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("API키가 일치하지 않습니다"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "API키가 일치하지 않습니다::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + Double amountD = param.getAmount(); + if(amountD.intValue() < 0) { + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("금액이 올바르지 않습니다"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "금액이 올바르지 않습니다::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + int amount = Math.abs(amountD.intValue()); + + String vendorTranKey = param.getTransactionKey(); + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + String gameName = param.getGameName(); + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "tplus"); + tranParam.put("vendorTranKey", vendorTranKey); + tranParam.put("gameType", "slot"); + tranParam.put("gameId", param.getGameSymbol()); + tranParam.put("gameIdx", gameName); + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + tranParam.put("isCancel", "Y"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + log.info(LOG_PREFIX + "-----INSERT_CANCEL_START-----"); + long startTime = System.currentTimeMillis(); + siteService.commonBetinsert(tranParam); + long endTime = System.currentTimeMillis(); // 코드 실행 후에 시간 받아오기 + double diffTime = (startTime - endTime)/1000.0; //두 시간에 차 계산 + if(diffTime < -1.0) { + log.error(LOG_PREFIX + "commonBetinsert::배팅 쓰기지연::"+diffTime+"초 지연발생"); + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("BET_TIMEOUT_ERROR"); + httpStatus = HttpStatus.OK; + log.error(LOG_PREFIX+ "BET_TIMEOUT_ERROR::Response::" + response.toString()); + return new ResponseEntity(response, httpStatus); + } + log.info(LOG_PREFIX + "-----INSERT_CANCEL_START-----"); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "tplus"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", gameName); + callBackObj.put("gameType", "slot"); + callBackObj.put("gameId", param.getGameSymbol()); + callBackObj.put("tranType", "credit"); + callBackObj.put("debit", 0); + callBackObj.put("credit", amount); + callBackObj.put("isCancel", 1); + callBackObj.put("isBonus", 0); + callBackObj.put("requestAt", param.getProcessedAt()); + log.info(LOG_PREFIX + "SEND_CANCEL request body: " + callBackObj.toString()); + JSONObject resData = callBackService.changeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + log.info(LOG_PREFIX + "SEND_CANCEL resData::"+resData.toString()); + log.info(LOG_PREFIX + "SEND_CANCEL status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_CANCEL response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + data = new TplusData(); + data.setBalance((double) balance); + data.setBeforeBalance((double) (balance - amount)); + data.setCurrency("KRW"); + response = new TplusResponse(); + response.setCode(0); + response.setData(data); + httpStatus = HttpStatus.OK; + } else if(resData.getLong("result_code") == 98) { + int balance = resData.getInt("balance"); + data = new TplusData(); + data.setBalance((double) balance); + data.setBeforeBalance((double) (balance - amount)); + data.setCurrency("KRW"); + response = new TplusResponse(); + response.setCode(0); + response.setData(data); + httpStatus = HttpStatus.OK; + } else { + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("UNKNOWN_ERROR"); + httpStatus = HttpStatus.OK; + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("TIMEOUT_ERROR"); + httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + response = new TplusResponse(); + response.setCode(-1); + response.setMsg("BET_SERVER_ERROR"); + httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; + } + + ResponseEntity res = new ResponseEntity(response, httpStatus); + log.info(LOG_PREFIX+ "Response::" + response.toString()); + + return res; + } + + + @ResponseBody + @RequestMapping(value={"/newChangeBalance"}) + public ResponseEntity newChangeBalance(HttpServletRequest request) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + HttpHeaders headers = new HttpHeaders(); + + int renturnCode = 200; + + try { + //사이트정보 + HashMap sParam = new HashMap(); + long siteIdx = Long.parseLong(request.getParameter("username").toString().substring(0, 3), 16); + sParam.put("siteIdx", siteIdx); + String memberId =request.getParameter("username").toString().substring(3, request.getParameter("username").toString().length()); + sParam.put("memberId", memberId); + HashMap siteApiInfo = siteService.getSiteApiInfo(sParam); + if(siteApiInfo==null) { + renturnCode = 500; + log.error("#-tplus::newChangeBalance::"+siteIdx+"::"+ request.getQueryString()); + return new ResponseEntity(apiResponse, headers, HttpStatus.valueOf(renturnCode)); // ResponseEntity를 활용한 응답 생성; + } + + String siteId = siteApiInfo.get("siteId").toString(); + long memberIdx = (long) siteApiInfo.get("memberIdx"); + + String tranId = (siteId+request.getParameter("transaction_key").toString()).trim(); + final String LOG_PREFIX = "#-tplus::newChangeBalance::"+siteIdx+"::"+memberIdx+"::"+tranId+"::::"; + + String tranType = ""; + String vendorApiId = request.getParameter("agent_name").toString(); + String vendorApiKey = request.getParameter("api_key").toString(); + + String balanceStr = request.getParameter("balance").toString(); + log.debug(LOG_PREFIX+ "balanceStr() : " + balanceStr); + + Double balanceD = Double.parseDouble(balanceStr); + log.debug(LOG_PREFIX+ "balanceD() : " + balanceD); + + int balance = balanceD.intValue(); + log.info(LOG_PREFIX+ "balance() : " +balance); + + String amountStr = request.getParameter("amount").toString(); + log.debug(LOG_PREFIX+ "amountStr() : " + amountStr); + + Double amountD = Double.parseDouble(amountStr); + log.debug(LOG_PREFIX+ "amountD() : " + amountD); + + long amount = amountD.longValue(); + log.info(LOG_PREFIX+ "amount() : " +amount); + + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/json"); + header.add("Accept", "application/json"); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + + JSONObject debit = new JSONObject(); + debit.put("tranId", tranId); + debit.put("userId", memberId); + debit.put("vendor", "tplus"); + if("BET".equals(request.getParameter("type").toString())) { + tranType = "debit"; + debit.put("tranType", "debit"); + debit.put("amount", amount); + debit.put("balance", balance); + } else if("WIN".equals(request.getParameter("type").toString())) { + tranType = "credit"; + debit.put("tranType", "credit"); + debit.put("amount", amount); + debit.put("balance", balance); + } else { + if("deposit".equals(request.getParameter("type").toString())) { + tranType = "deposit"; + } else { + tranType = "withdraw"; + } + + renturnCode = 200; + return new ResponseEntity(apiResponse, headers, HttpStatus.valueOf(renturnCode)); // ResponseEntity를 활용한 응답 생성; + } + + log.info(LOG_PREFIX+ "/syncBalance param: " + debit.toString()); + + ResponseEntity responseEntity = webClient.post() + .uri(siteApiInfo.get("siteCbUrl")+"/changebalance/syncBalance") + .headers(h -> h.addAll(header)) + .bodyValue(debit.toString()) + .retrieve() + .toEntity(String.class) + .block(); + + log.info(LOG_PREFIX+ "/syncBalance status code : " + responseEntity.getStatusCode()); + log.info(LOG_PREFIX+ "body: " + responseEntity.getBody()); + + org.codehaus.jettison.json.JSONObject resData = new org.codehaus.jettison.json.JSONObject(responseEntity.getBody()); + log.info(LOG_PREFIX+ "result_code: " + resData.getInt("result_code")); + + if(resData.getLong("result_code") == 0) { + log.info(LOG_PREFIX+ "SUCC"); + renturnCode = 200; + } else { + log.error(LOG_PREFIX+ "FAIL"); + renturnCode = 500; + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error("#-tplus::newChangeBalance::::["+request.getParameter("transaction_key").toString()+"]"+"::[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error("#-tplus::newChangeBalance::::["+request.getParameter("transaction_key").toString()+"]"+"::[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error("#-tplus::newChangeBalance::::["+request.getParameter("transaction_key").toString()+"]"+"::[InterruptedException]"+rae.getMessage()); + } + + renturnCode = 200; + log.error("#-tplus::newChangeBalance::::["+request.getParameter("transaction_key").toString()+"]"+"::[ResourceAccessException]"+rae.getMessage()); + } catch (Exception e) { + System.out.println(e.toString()); + e.printStackTrace(); + renturnCode = 500; + log.error("#-tplus::newChangeBalance::::["+request.getParameter("transaction_key").toString()+"]"+"::[Exception]"+e.getMessage()); + } + + log.info("#-tplus::newChangeBalance::::["+request.getParameter("transaction_key").toString()+"]::"+"::apiResponse: " + apiResponse.toString()); + return new ResponseEntity(apiResponse, headers, HttpStatus.valueOf(renturnCode)); // ResponseEntity를 활용한 응답 생성; + } + + + private String makeApiKey(String param) { + + int n = 20; // n자리 쿠폰 + char[] chs = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' ,'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; + + Random rd = new Random(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < n; i++) { + char ch = chs[rd.nextInt(chs.length)]; + sb.append(ch); + } + return param + sb.toString(); + } + +} + diff --git a/src/main/java/com/bb/front/CallbackBetRadarController.java b/src/main/java/com/bb/front/CallbackBetRadarController.java new file mode 100644 index 0000000..a93d584 --- /dev/null +++ b/src/main/java/com/bb/front/CallbackBetRadarController.java @@ -0,0 +1,674 @@ +package com.bb.front; + +import java.io.IOException; +import java.net.SocketTimeoutException; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.util.HashMap; + +import jakarta.servlet.http.HttpServletRequest; + +import org.apache.http.conn.ConnectTimeoutException; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.ResourceAccessException; +import org.springframework.web.util.ContentCachingRequestWrapper; +import org.springframework.web.util.WebUtils; + +import com.bb.model.BetRadarResponse; +import com.bb.service.AsyncSiteService; +import com.bb.service.CallBackService; +import com.bb.service.SiteService; +import com.bb.util.HmacUtils; + +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@RequestMapping("/api/callback/betradar") +@RequiredArgsConstructor +@SecurityRequirement(name = "Authorization") +@EnableScheduling +@RestController +public class CallbackBetRadarController { + + @Autowired + SiteService siteService; + + @Autowired + CallBackService callBackService; + + @Autowired + AsyncSiteService asyncCallBackService; + + @ResponseBody + @RequestMapping(path = "/balance") + public ResponseEntity balance( + HttpServletRequest request, + @RequestHeader("timestamp") String timestamp, + @RequestHeader("signature") String signature, + @RequestBody net.sf.json.JSONObject requestBody) throws Exception { + BetRadarResponse response = null; + + String username = requestBody.getString("username"); + String target = ""; + int idx = username.indexOf('_'); + if (idx >= 0 && idx < username.length() - 1) { + target = username.substring(idx + 1); + } else { + target = username; + } + long siteIdx = Long.parseLong(target.substring(0, 3), 16); + String memberId = target.substring(3, target.length()); + final String LOG_PREFIX = "#-CB::BET_RADAR::"+memberId+"::balance:::"; + log.info(LOG_PREFIX+ "Request::" + requestBody); + + try { + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "bet_radar"); + HashMap siteApiInfo = siteService.getSiteApiInfo2(sParam); + if(siteApiInfo == null) { + log.error(LOG_PREFIX+ "Error Msg: NOT_FOUND_USER"); + response = new BetRadarResponse(); + response.setBalance(0); + response.setError(1); + return new ResponseEntity(response, HttpStatus.OK); + } + /* + // ===== Signature 검증 (여기서!) ===== + String apiKey = siteApiInfo.get("vendorApiKey").toString(); + String rawPayload = getRawBody(request); + + if (!verifySignature(timestamp, rawPayload, signature, apiKey)) { + log.error(LOG_PREFIX + "INVALID_SIGNATURE"); + + response = new BetRadarResponse(); + response.setBalance(0); + response.setError(1); + return new ResponseEntity<>(response, HttpStatus.OK); + } + // ================================== + */ + + // ===== Signature 검증 (관찰 모드) ===== + try { + String apiKey = siteApiInfo.get("vendorApiKey").toString(); + String rawPayload = getRawBody(request); + + boolean valid = verifySignature(timestamp, rawPayload, signature, apiKey); + + if (!valid) { + log.error(LOG_PREFIX + "SIGNATURE_MISMATCH"); + log.error(LOG_PREFIX + "timestamp=" + timestamp); + log.error(LOG_PREFIX + "payload(raw)=" + rawPayload); + log.error(LOG_PREFIX + "signature(received)=" + signature); + + String calculated = HmacUtils.hmacSha256Hex(apiKey, timestamp + rawPayload); + log.error(LOG_PREFIX + "signature(calculated)=" + calculated); + } else { + log.info(LOG_PREFIX + "SIGNATURE_OK"); + } + + } catch (Exception e) { + log.error(LOG_PREFIX + "SIGNATURE_EXCEPTION", e); + } + // ====================================== + + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + org.codehaus.jettison.json.JSONObject member = new org.codehaus.jettison.json.JSONObject(); + member.put("userId", memberId); + log.info(LOG_PREFIX+ "Callback URL::" + siteApiInfo.get("siteCbUrl")+"/balance"); + log.info(LOG_PREFIX+ "Callback Param::" + member.toString()); + + member.put("userId", memberId); + org.codehaus.jettison.json.JSONObject resBalancedData = callBackService.getBalance(siteApiInfo, member); + if(resBalancedData == null) { + log.error(LOG_PREFIX+ "Error Msg: BALANCE_CALLBACK_ERROR"); + response = new BetRadarResponse(); + response.setBalance(0); + response.setError(1); + return new ResponseEntity(response, HttpStatus.OK); + } + + int balance = resBalancedData.getInt("balance"); + response = new BetRadarResponse(); + response.setBalance(balance); + response.setError(0); + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + response = new BetRadarResponse(); + response.setBalance(0); + response.setError(1); + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + response = new BetRadarResponse(); + response.setBalance(0); + response.setError(1); + } + + ResponseEntity res = new ResponseEntity(response, HttpStatus.OK); + log.info(LOG_PREFIX+ "Response::" + response.toString()); + + return res; + } + + @ResponseBody + @RequestMapping(path = "/bet") + private ResponseEntity bet(HttpServletRequest request, @RequestBody net.sf.json.JSONObject requestBody) { + BetRadarResponse response = null; + + String username = requestBody.getString("username"); + String target = ""; + int idx = username.indexOf('_'); + if (idx >= 0 && idx < username.length() - 1) { + target = username.substring(idx + 1); + } else { + target = username; + } + net.sf.json.JSONObject transactionObj = requestBody.getJSONObject("transaction"); + net.sf.json.JSONObject gameObj = transactionObj.getJSONObject("details").getJSONObject("game"); + net.sf.json.JSONArray betInfoArr = transactionObj.getJSONObject("details").getJSONArray("bet_info"); + String type = transactionObj.getString("type"); + String betId = gameObj.getString("id"); + String tranId = betId+"#"+type; + String vendorTranKey = tranId; + String betTitle = type + " | " + gameObj.getString("type") + " | " + gameObj.getString("odds"); + long siteIdx = Long.parseLong(target.substring(0, 3), 16); + String memberId = target.substring(3, target.length()); + final String LOG_PREFIX = "#-CB::BET_RADAR::"+memberId+"::bet::"+betId+":::"; + log.info(LOG_PREFIX+ "Request::" + requestBody); + + try { + // "date":"2025-05-21T08:05:32.925Z" => "2025-05-21 08:05:32" + String betDateTimeStr = transactionObj.getString("processed_at"); + log.info(LOG_PREFIX+ "========== BF_betDateTimeStr::" + betDateTimeStr); + betDateTimeStr = betDateTimeStr.substring(0, 19); + betDateTimeStr = betDateTimeStr.replace("T", " "); + log.info(LOG_PREFIX+ "========== AF_betDateTimeStr::" + betDateTimeStr); + + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "bet_radar"); + sParam.put("vendorGameCode", "SKSPORTS"); + log.info(LOG_PREFIX + "getSiteVendorInfo::"+sParam.toString()); + HashMap siteVendorInfo = siteService.getSiteVendorInfo(sParam); + if(siteVendorInfo == null) { + log.error(LOG_PREFIX+ "Error Msg: NOT_FOUND_SITE_INFO"); + response = new BetRadarResponse(); + response.setBalance(0); + response.setError(1); + return new ResponseEntity(response, HttpStatus.OK); + } + + if(siteVendorInfo.get("memberIdx") == null) { + log.error(LOG_PREFIX+ "Error Msg: NOT_FOUND_USER"); + response = new BetRadarResponse(); + response.setBalance(0); + response.setError(1); + return new ResponseEntity(response, HttpStatus.OK); + } + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + int amount = requestBody.getInt("amount"); + + if(siteVendorInfo.get("lastInVendorIdx")==null || "0".equals(siteVendorInfo.get("lastInVendorIdx").toString())) { + HashMap memParam = new HashMap<>(); + memParam.put("siteIdx", siteIdx); + memParam.put("memberIdx", memberIdx); + memParam.put("lastInVendorIdx", Integer.parseInt(siteVendorInfo.get("vendorIdx").toString())); + int updResult = siteService.updMemLastVendorIdx(memParam); + } else { + int lastInVendorIdx = Integer.parseInt(siteVendorInfo.get("lastInVendorIdx").toString()); + if(lastInVendorIdx != vendorIdx) { + log.error(LOG_PREFIX+ "VendorIdx doesn't match"); + response = new BetRadarResponse(); + response.setBalance(0); + response.setError(1); + return new ResponseEntity(response, HttpStatus.OK); + } + } + + long siteCredit = Long.parseLong(siteVendorInfo.get("credit").toString()); + if(siteCredit < amount) { + log.error(LOG_PREFIX+ "NO_SITE_CREDIT"); + response = new BetRadarResponse(); + response.setBalance(0); + response.setError(1); + return new ResponseEntity(response, HttpStatus.OK); + } + + long siteMaxBet = Long.parseLong(siteVendorInfo.get("siteMaxBet").toString()); + if(siteMaxBet < amount) { + log.error(LOG_PREFIX+ "MAX_BET_AMOUNT_OVER"); + response = new BetRadarResponse(); + response.setBalance(0); + response.setError(1); + return new ResponseEntity(response, HttpStatus.OK); + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "bet_radar"); + tranParam.put("vendorTranKey", vendorTranKey); + tranParam.put("gameType", "SKSPORTS"); + tranParam.put("gameId", ""); + tranParam.put("gameIdx", betTitle); + tranParam.put("tranType", "debit"); + tranParam.put("depositAmt", amount); + tranParam.put("creditAmt", "0"); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + log.info(LOG_PREFIX + "-----INSERT_BET_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_BET_END-----"); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "bet_radar"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", betTitle); + callBackObj.put("gameId", ""); + callBackObj.put("gameType", "SKSPORTS"); + callBackObj.put("tranType", "debit"); + callBackObj.put("debit", amount); + callBackObj.put("credit", 0); + callBackObj.put("isCancel", 0); + callBackObj.put("isBonus", 0); + callBackObj.put("isData", "N"); + callBackObj.put("requestAt", betDateTimeStr); + String detailJsonStr = transactionObj.getJSONObject("details").toString(); + JSONObject detailObj = new JSONObject(detailJsonStr); + callBackObj.put("detail", detailObj); + log.info(LOG_PREFIX + "SEND_BET request body: " + callBackObj.toString()); + JSONObject resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + log.info(LOG_PREFIX + "SEND_BET status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_BET response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + asyncCallBackService.asyncSportsRadarProc(LOG_PREFIX, tranParam, requestBody); + + int balance = resData.getInt("balance"); + response = new BetRadarResponse(); + response.setBalance(balance); + response.setError(0); + } else if(resData.getLong("result_code") == 98) { + log.error(LOG_PREFIX + "중복요청"); + int balance = resData.getInt("balance"); + response = new BetRadarResponse(); + response.setBalance(balance); + response.setError(0); + } else if(resData.getLong("result_code") == 80) { + log.error(LOG_PREFIX + "잔액부족"); + int balance = resData.getInt("balance"); + response = new BetRadarResponse(); + response.setBalance(0); + response.setError(1); + } else { + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + log.error(LOG_PREFIX+ msg); + response = new BetRadarResponse(); + response.setBalance(0); + response.setError(1); + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + response = new BetRadarResponse(); + response.setBalance(0); + response.setError(1); + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + response = new BetRadarResponse(); + response.setBalance(0); + response.setError(1); + } + + ResponseEntity res = new ResponseEntity(response, HttpStatus.OK); + log.info(LOG_PREFIX+ "Response::" + response.toString()); + + return res; + } + + /** + * + * @param request + * @param requestBody + * + * > requestBody.transaction.type + * - bet 베팅 + * - win 당첨 + * - lose 낙첨 + * - push 적특 + * - cancle 취소 + * + * > requestBody.transaction.rollback + * - 0 : 정상 처리 + * - 1 : 롤백 처리 + * @return + */ + @ResponseBody + @RequestMapping(path = "/result") + private ResponseEntity result(HttpServletRequest request, @RequestBody net.sf.json.JSONObject requestBody) { + BetRadarResponse response = null; + + String username = requestBody.getString("username"); + String target = ""; + int idx = username.indexOf('_'); + if (idx >= 0 && idx < username.length() - 1) { + target = username.substring(idx + 1); + } else { + target = username; + } + net.sf.json.JSONObject transactionObj = requestBody.getJSONObject("transaction"); + net.sf.json.JSONObject gameObj = transactionObj.getJSONObject("details").getJSONObject("game"); + net.sf.json.JSONArray betResultInfoArr = transactionObj.getJSONObject("details").getJSONArray("bet_result_info"); + String type = transactionObj.getString("type"); + int rollback = transactionObj.getInt("rollback"); // rollback=1 이면 롤백. 이전 상태와 type이변경 + String betId = gameObj.getString("id"); + String tranId = betId+"#"+type; + String vendorTranKey = tranId; + String betTitle = type + " | " + gameObj.getString("type"); + long siteIdx = Long.parseLong(target.substring(0, 3), 16); + String memberId = target.substring(3, target.length()); + final String LOG_PREFIX = "#-CB::BET_RADAR::"+memberId+"::"+type+"::"+betId+":::"; + log.info(LOG_PREFIX+ "Request::" + requestBody); + + try { + // "date":"2025-05-21T08:05:32.925Z" => "2025-05-21 08:05:32" + String betDateTimeStr = transactionObj.getString("processed_at"); + log.info(LOG_PREFIX+ "========== BF_betDateTimeStr::" + betDateTimeStr); + betDateTimeStr = betDateTimeStr.substring(0, 19); + betDateTimeStr = betDateTimeStr.replace("T", " "); + log.info(LOG_PREFIX+ "========== AF_betDateTimeStr::" + betDateTimeStr); + + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "bet_radar"); + sParam.put("vendorGameCode", "SKSPORTS"); + log.info(LOG_PREFIX + "getSiteVendorInfo::"+sParam.toString()); + HashMap siteVendorInfo = siteService.getSiteVendorInfo(sParam); + if(siteVendorInfo == null) { + log.error(LOG_PREFIX+ "Error Msg: NOT_FOUND_SITE_INFO"); + response = new BetRadarResponse(); + response.setBalance(0); + response.setError(1); + return new ResponseEntity(response, HttpStatus.OK); + } + + if(siteVendorInfo.get("memberIdx") == null) { + log.error(LOG_PREFIX+ "Error Msg: NOT_FOUND_USER"); + response = new BetRadarResponse(); + response.setBalance(0); + response.setError(1); + return new ResponseEntity(response, HttpStatus.OK); + } + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + int amount = requestBody.getInt("amount"); + + HashMap tranParam = new HashMap(); + JSONObject callBackObj = new JSONObject(); + if(rollback == 1) { + // 이전 결과 콜백 조회 및 롤백 처리 + tranId = tranId + "#rb"; + tranParam.put("tranId", tranId); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "bet_radar"); + tranParam.put("vendorTranKey", vendorTranKey); + tranParam.put("gameType", "SKSPORTS"); + tranParam.put("gameId", ""); + tranParam.put("gameIdx", "#Rollback-"+betTitle); + if(amount > 0) { + // 롤백 - 유저 잔액 증가 + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", Math.abs(amount)); + } else { + // 롤백 - 유저 잔액 감소 + tranParam.put("tranType", "debit"); + tranParam.put("depositAmt", Math.abs(amount)); + tranParam.put("creditAmt", "0"); + } + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + log.info(LOG_PREFIX + "-----INSERT_RESULT_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_RESULT_END-----"); + + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "bet_radar"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", "#Rollback-"+betTitle); + callBackObj.put("gameId", ""); + callBackObj.put("gameType", "SKSPORTS"); + callBackObj.put("tranType", "adjust"); + if(amount > 0) { + // 롤백 - 유저 잔액 증가 + callBackObj.put("debit", 0); + callBackObj.put("credit", Math.abs(amount)); + } else { + // 롤백 - 유저 잔액 감소 + callBackObj.put("debit", Math.abs(amount)); + callBackObj.put("credit", 0); + } + callBackObj.put("isCancel", 0); + callBackObj.put("isBonus", 0); + callBackObj.put("isData", "N"); + callBackObj.put("requestAt", betDateTimeStr); + } else { + // rollback == 0 > 기본 결과 콜백 + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "bet_radar"); + tranParam.put("vendorTranKey", vendorTranKey); + tranParam.put("gameType", "SKSPORTS"); + tranParam.put("gameId", ""); + tranParam.put("gameIdx", betTitle); + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + if("cancel".equals(type)) { + tranParam.put("isCancel", "Y"); + } else { + tranParam.put("isCancel", "N"); + } + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + log.info(LOG_PREFIX + "-----INSERT_RESULT_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_RESULT_END-----"); + + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "bet_radar"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", betTitle); + callBackObj.put("gameId", ""); + callBackObj.put("gameType", "SKSPORTS"); + callBackObj.put("tranType", "credit"); + callBackObj.put("debit", 0); + callBackObj.put("credit", amount); + if("cancel".equals(type)) { + callBackObj.put("isCancel", 1); + } else { + callBackObj.put("isCancel", 0); + } + callBackObj.put("isBonus", 0); + callBackObj.put("isData", "N"); + callBackObj.put("requestAt", betDateTimeStr); + } + + String detailJsonStr = transactionObj.getJSONObject("details").toString(); + JSONObject detailObj = new JSONObject(detailJsonStr); + callBackObj.put("detail", detailObj); + + log.info(LOG_PREFIX + "SEND_RESULT request body: " + callBackObj.toString()); + JSONObject resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + log.info(LOG_PREFIX + "SEND_RESULT status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_RESULT response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + asyncCallBackService.asyncSportsRadarProc(LOG_PREFIX, tranParam, requestBody); + + int balance = resData.getInt("balance"); + response = new BetRadarResponse(); + response.setBalance(balance); + response.setError(0); + } else if(resData.getLong("result_code") == 98) { + log.error(LOG_PREFIX + "중복요청"); + int balance = resData.getInt("balance"); + response = new BetRadarResponse(); + response.setBalance(balance); + response.setError(0); + } else { + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + log.error(LOG_PREFIX+ msg); + response = new BetRadarResponse(); + response.setBalance(0); + response.setError(1); + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + response = new BetRadarResponse(); + response.setBalance(0); + response.setError(1); + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + response = new BetRadarResponse(); + response.setBalance(0); + response.setError(1); + } + + ResponseEntity res = new ResponseEntity(response, HttpStatus.OK); + return res; + } + + private boolean verifySignature(String timestamp, String payload, String receivedSignature, String apiKey) { + + String message = timestamp + payload; + String calculated = HmacUtils.hmacSha256Hex(apiKey, message); + + return MessageDigest.isEqual( + calculated.getBytes(StandardCharsets.UTF_8), + receivedSignature.getBytes(StandardCharsets.UTF_8) + ); + } + + private String getRawBody(HttpServletRequest request) throws IOException { + + ContentCachingRequestWrapper wrapper = WebUtils.getNativeRequest(request, ContentCachingRequestWrapper.class); + + if (wrapper == null) { + throw new IllegalStateException("Request not wrapped"); + } + + byte[] buf = wrapper.getContentAsByteArray(); + return new String(buf, StandardCharsets.UTF_8); + } + + +} diff --git a/src/main/java/com/bb/front/CallbackGrandController.java b/src/main/java/com/bb/front/CallbackGrandController.java new file mode 100644 index 0000000..33665ca --- /dev/null +++ b/src/main/java/com/bb/front/CallbackGrandController.java @@ -0,0 +1,402 @@ +package com.bb.front; + +import java.net.SocketTimeoutException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; + +import jakarta.servlet.http.HttpServletRequest; + +import org.apache.http.conn.ConnectTimeoutException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.ResourceAccessException; + +import com.bb.service.CallBackService; +import com.bb.service.SiteService; + +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import net.sf.json.JSONObject; + +@Slf4j +@RequestMapping("/api/cb/grand") +@RequiredArgsConstructor +@SecurityRequirement(name = "Authorization") +@EnableScheduling +@RestController +public class CallbackGrandController { + + @Autowired + SiteService siteService; + + @Autowired + CallBackService callBackService; + + // https://oprvender.com/api/cb/gsoft/syncBalance + // https://oprvender.com/api/cb/gsoft/balance + // https://oprvender.com/api/cb/gsoft/changeBalance + + @ResponseBody + @GetMapping(path = "/balance", produces = "application/json") // JSON만 생산 + public ResponseEntity balance(HttpServletRequest request, @RequestParam("username") String grandUserId) throws Exception { + JSONObject resData = new JSONObject(); + HttpStatus httpStatus = null; + + long siteIdx = Long.parseLong(grandUserId.substring(0, 3), 16); + String memberId = grandUserId.substring(3, grandUserId.length()); + final String LOG_PREFIX = "#-CB::GRAND::balance::"+memberId+":::"; + + try { + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + + HashMap siteApiInfo = siteService.getSiteApiInfo(sParam); + if(siteApiInfo==null) { + log.error(LOG_PREFIX+ "Error Msg: NOT_FOUND_SITE_INFO"); + return new ResponseEntity(resData, HttpStatus.INTERNAL_SERVER_ERROR); + } + + org.codehaus.jettison.json.JSONObject member = new org.codehaus.jettison.json.JSONObject(); + member.put("userId", memberId); + log.info(LOG_PREFIX+ "Callback URL::" + siteApiInfo.get("siteCbUrl")+"/balance"); + log.info(LOG_PREFIX+ "Callback Param::" + member.toString()); + + member.put("userId", memberId); + org.codehaus.jettison.json.JSONObject resBalancedData = callBackService.getBalance(siteApiInfo, member); + if(resBalancedData == null) { + log.error(LOG_PREFIX+ "Error Msg: BALANCE_CALLBACK_ERROR"); + return new ResponseEntity(resData, HttpStatus.INTERNAL_SERVER_ERROR); + } + int balance = resBalancedData.getInt("balance"); + + resData.put("balance", balance); + httpStatus = HttpStatus.OK; + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + log.error(LOG_PREFIX+ "[ResourceAccessException]"+rae.getMessage()); + + httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.getMessage()); + + httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; + } + + ResponseEntity res = new ResponseEntity(resData, httpStatus); + log.info(LOG_PREFIX+ "Response: "+resData.toString()); + + return new ResponseEntity(resData, HttpStatus.OK); + } + + + @ResponseBody + @PostMapping(path = "/change-balance", produces = "application/json") // JSON만 생산 + public ResponseEntity changebalance(HttpServletRequest request, @RequestBody net.sf.json.JSONObject requestBody) throws Exception { + + String grandUserId = requestBody.getString("username"); + JSONObject transaction = requestBody.getJSONObject("transaction"); + String tranType = transaction.getString("type"); + long siteIdx = Long.parseLong(grandUserId.substring(0, 3), 16); + String memberId = grandUserId.substring(3, grandUserId.length()); + final String LOG_PREFIX = "#-CB::GRAND::changeBalance::"+memberId+"::"+transaction.getString("id")+"::"+tranType+":::"; + log.info(LOG_PREFIX+ "Request Body: "+requestBody.toString()); + + JSONObject resData = new JSONObject(); + HttpStatus httpStatus = null; + + try { + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "grand"); + sParam.put("vendorGameCode", "pragmatic_slot"); + HashMap siteApiInfo = siteService.getSiteVendorInfo(sParam); + if(siteApiInfo==null) { + log.error(LOG_PREFIX+ "siteApiInfo is null "+tranType+" "+grandUserId+"::"+ "Error Msg: NOT_FOUND_SITE_INFO"); + return new ResponseEntity(resData, HttpStatus.INTERNAL_SERVER_ERROR); + } + + long amount = requestBody.getLong("amount"); + long overAmount =requestBody.getLong("over_amount"); + long memberIdx = Long.parseLong(siteApiInfo.get("memberIdx").toString()); + long vendorIdx = Long.parseLong(siteApiInfo.get("vendorIdx").toString()); + + String siteId = siteApiInfo.get("siteId").toString(); + String vendorApiId = siteApiInfo.get("vendorApiId").toString(); + String vendorKey = siteApiInfo.get("vendorKey").toString(); + + // 2025-06-10T07:12:54.355000Z + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS"); + String betDateTimeStr = transaction.getString("processed_at"); + log.info(LOG_PREFIX+ "========== BF_betDateTimeStr::" + betDateTimeStr); + betDateTimeStr = betDateTimeStr.substring(0, 23); + betDateTimeStr = betDateTimeStr.replace("T", " "); + log.info(LOG_PREFIX+ "========== MF_betDateTimeStr::" + betDateTimeStr); + betDateTimeStr = makeEdate(LOG_PREFIX, betDateTimeStr, 32400000); + log.info(LOG_PREFIX+ "========== AF_betDateTimeStr::" + betDateTimeStr); + + if(amount < 0) { + long siteCredit = Long.parseLong(siteApiInfo.get("credit").toString()); + if(siteCredit < amount) { + log.error(LOG_PREFIX+ "SITE_IDX: "+siteIdx+" NO_SITE_CREDIT"); + return new ResponseEntity(resData, HttpStatus.INTERNAL_SERVER_ERROR); + } + + long siteMaxBet = Long.parseLong(siteApiInfo.get("siteMaxBet").toString()); + if(siteMaxBet < amount) { + log.error(LOG_PREFIX+ "SITE_IDX: "+siteIdx+"MAX_BET_AMOUNT_OVER"); + return new ResponseEntity(resData, HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + String tranId = siteId+transaction.getString("id")+tranType; + String betId = ""; + //String vendorTranKey = transaction.getString("id"); + String vendorTranKey = ""; + + String gameName = ""; + String gameId = ""; + String gameType = "slot"; + try { + JSONObject gameDetail = transaction.getJSONObject("details"); + JSONObject gameJson = gameDetail.getJSONObject("game"); + try { + gameId = gameJson.getString("game"); + gameName = gameJson.getString("game_name"); + vendorTranKey = gameJson.getString("round"); + } catch(Exception e){ + log.error(LOG_PREFIX+ "gameName is empty"); + gameName = gameId; + } + + if("bet".equals(tranType)) { + betId = siteId + transaction.getString("id")+memberIdx; + } else if("win".equals(tranType) || "adjust".equals(tranType)) { + betId = siteId + transaction.getString("referer_id")+memberIdx; + } else { + betId = siteId + transaction.getString("id")+memberIdx; + } + + } catch(Exception e) { + if("bet".equals(tranType)) { + betId = siteId + transaction.getString("id")+memberIdx; + } else if("win".equals(tranType) || "adjust".equals(tranType)) { + betId = siteId + transaction.getString("referer_id")+memberIdx; + } else { + betId = siteId + transaction.getString("id")+memberIdx; + } + log.error(LOG_PREFIX+ "gameDetail is empty"); + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", "SLOT"); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "grand"); + tranParam.put("vendorTranKey", vendorTranKey); + tranParam.put("gameType", gameType); + tranParam.put("gameId", gameId); + tranParam.put("gameIdx", gameName); + if(amount <0) { + tranParam.put("tranType", "debit"); + tranParam.put("depositAmt", Math.abs(amount)); + tranParam.put("creditAmt", "0"); + } else { + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", 0); + tranParam.put("creditAmt", amount-overAmount); + } + //tranParam.put("isCancel", "N"); + if("cancel".equals(tranType)) { + tranParam.put("isCancel", "Y"); + }else { + tranParam.put("isCancel", "N"); + } + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + log.info(LOG_PREFIX+ "-----INSERT_BET_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX+ "-----INSERT_BET_END-----"); + + org.codehaus.jettison.json.JSONObject callBackObj = new org.codehaus.jettison.json.JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "grand"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", gameName); + callBackObj.put("gameId", gameId); + callBackObj.put("gameType", gameType); + if(amount < 0) { + callBackObj.put("tranType", "debit"); + callBackObj.put("debit", Math.abs(amount)); + callBackObj.put("credit", 0); + } else { + callBackObj.put("tranType", "credit"); + callBackObj.put("debit", 0); + callBackObj.put("credit", amount-overAmount); + } + //callBackObj.put("isCancel", 0); + + if("cancel".equals(tranType)) { + callBackObj.put("isCancel", 1); + } else { + callBackObj.put("isCancel", 0); + } + + if("adjust".equals(tranType)) { + callBackObj.put("isBonus", 1); + } else { + callBackObj.put("isBonus", 0); + } + callBackObj.put("requestAt", betDateTimeStr); + log.info(LOG_PREFIX+ "SEND_BET request body: " + callBackObj.toString()); + org.codehaus.jettison.json.JSONObject resTranData = callBackService.changeBalanceSlot(LOG_PREFIX, siteApiInfo, callBackObj); + log.info(LOG_PREFIX+ "SEND_BET response body: " + resTranData.toString()); + + if(resTranData.getLong("result_code") == 0) { + // 성공 + tranParam.put("balance", resTranData.getLong("balance")); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX+ "UPDATE_CALLBACK_API_STATUS END"); + + long balance = resTranData.getLong("balance"); + resData.put("balance", balance); + httpStatus = HttpStatus.OK; + + } else if(resTranData.getLong("result_code") == 98) { + // 중복 + long balance = resTranData.getLong("balance"); + resData.put("balance", balance); + httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; + } else { + // 실패 + log.error(LOG_PREFIX+ "CALLBACK_ERROR"); + httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "::"+grandUserId+"::"+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "::"+grandUserId+"::"+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "::"+grandUserId+"::"+ "[InterruptedException]"+rae.getMessage()); + } + + log.error(LOG_PREFIX+ "::"+grandUserId+"::"+ "[ResourceAccessException]"+rae.getMessage()); + + httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; + + } catch (Exception e) { + log.error(LOG_PREFIX+ "#-Grand::::"+grandUserId+"::"+ "[Exception]"+e.getMessage()); + + httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; + } + + ResponseEntity res = new ResponseEntity(resData, httpStatus); + log.info(LOG_PREFIX+ "::"+grandUserId+"::"+ "Response: "+resData.toString()); + + return new ResponseEntity(resData, httpStatus); + } + + @ResponseBody + @GetMapping(path = "/detail", produces = "application/json") // JSON만 생산 + public ResponseEntity detail(HttpServletRequest request, @RequestParam("username") String grandUserId) throws Exception { + JSONObject resData = new JSONObject(); + HttpStatus httpStatus = null; + + long siteIdx = Long.parseLong(grandUserId.substring(0, 3), 16); + String memberId = grandUserId.substring(3, grandUserId.length()); + final String LOG_PREFIX = "#-CB::GRAND::detail"+memberId+":::"; + + try { + httpStatus = HttpStatus.OK; + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + log.error(LOG_PREFIX+ "[ResourceAccessException]"+rae.getMessage()); + + httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.getMessage()); + + httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; + } + + ResponseEntity res = new ResponseEntity(resData, httpStatus); + log.info(LOG_PREFIX+ "Response: "+resData.toString()); + + return new ResponseEntity(resData, HttpStatus.OK); + } + + private static String makeEdate(String LOG_PREFIX, String paramDate, int flag) { + // TODO Auto-generated method stub + String eDate = ""; + SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + try { + Date date = sdf1.parse(paramDate); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + calendar.add(Calendar.MILLISECOND, flag); + Date date2 = calendar.getTime(); + eDate = sdf2.format(date2); + } catch(Exception e) { + log.error(LOG_PREFIX+ "makeEdate::Exception::"+e.getMessage()); + } + return eDate; + } +} diff --git a/src/main/java/com/bb/front/CallbackGsoftController.java b/src/main/java/com/bb/front/CallbackGsoftController.java new file mode 100644 index 0000000..055138a --- /dev/null +++ b/src/main/java/com/bb/front/CallbackGsoftController.java @@ -0,0 +1,784 @@ +package com.bb.front; + +import java.net.SocketTimeoutException; +import java.util.HashMap; + +import jakarta.servlet.http.HttpServletRequest; + +import org.apache.http.conn.ConnectTimeoutException; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.ResourceAccessException; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.WebClientRequestException; +import org.springframework.web.reactive.function.client.WebClientResponseException; + +import com.bb.model.GsoftApiInfo; +import com.bb.model.GsoftResponse; +import com.bb.model.GsoftTrxVO; +import com.bb.model.GsoftVO; +import com.bb.service.CallBackService; +import com.bb.service.GsoftService; +import com.bb.service.SiteService; + +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@RequestMapping("/api/cb/gsoft") +@RequiredArgsConstructor +@SecurityRequirement(name = "Authorization") +@EnableScheduling +@RestController +public class CallbackGsoftController { + + @Autowired + SiteService siteService; + + @Autowired + GsoftService gsoftService; + + @Autowired + CallBackService callBackService; + + @Autowired + WebClient webClient; + + // https://oprvender.com/api/cb/gsoft/syncBalance + // https://oprvender.com/api/cb/gsoft/balance + // https://oprvender.com/api/cb/gsoft/changeBalance + + @ResponseBody + @RequestMapping(path = "/syncBalance") + public ResponseEntity syncBalance(HttpServletRequest request, @RequestBody GsoftTrxVO gsoftTrxVO) throws Exception { + GsoftResponse response = null; + HttpStatus httpStatus = null; + + long siteIdx = Long.parseLong(gsoftTrxVO.getUserId().substring(0, 3), 16); + String memberId = gsoftTrxVO.getUserId().substring(3, gsoftTrxVO.getUserId().length()); + String game = gsoftTrxVO.getGame(); + final String LOG_PREFIX = "#-Gsoft::syncBalance::"+gsoftTrxVO.getUserId()+"::"+game+"::"+gsoftTrxVO.getTranId()+"::::"; + + log.info(LOG_PREFIX+ "[REQUEST: "+request.getRequestURI()+"] " + gsoftTrxVO); + + try { + log.info(LOG_PREFIX+ "SITE_IDX: "+siteIdx+", USER_INFO: " + memberId+", GAME_INFO: " + game); + + HashMap memParam = new HashMap<>(); + memParam.put("siteIdx", siteIdx); + memParam.put("memberId", memberId); + memParam.put("vendorGameCode", "SxPRG"); + HashMap userVendorInfo = siteService.getUserVendorInfo(memParam); + if(userVendorInfo == null) { + log.error(LOG_PREFIX+ "Error Msg: NOT_FOUND_SITE_INFO::memParam::" + memParam.toString()); + response = new GsoftResponse(); + response.setResult(0); + response.setBalance(gsoftTrxVO.getBalance().intValue()); + httpStatus = HttpStatus.OK; + return new ResponseEntity(response, httpStatus); + } + + String siteId = userVendorInfo.get("siteId").toString(); +// long memberIdx = (long) siteApiInfo.get("memberIdx"); + long memberIdx = Long.parseLong(userVendorInfo.get("memberIdx").toString()); + + int amount = Math.abs(gsoftTrxVO.getAmount().intValue()); + int balance = gsoftTrxVO.getBalance().intValue(); + log.info(LOG_PREFIX + "getBalanceUser::SUCC::BF_BALANCE::"+balance); + + String tranType = ""; + String type = gsoftTrxVO.getType(); + + String tranId = siteId + "#" + gsoftTrxVO.getTranId(); + + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/json"); + header.add("Accept", "application/json"); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + + JSONObject trxObj = new JSONObject(); + trxObj.put("tranId", tranId); + trxObj.put("userId", memberId); + trxObj.put("vendor", "gsoft"); + + if(type.equals("bet")) { + tranType = "debit"; + trxObj.put("tranType", tranType); + balance = balance - amount; + + } else { + // win, lose, cancel + GsoftApiInfo gsoftApiInfo = GsoftApiInfo.builder() + .siteIdx(siteIdx) + .memberIdx(memberIdx) + .apiBaseUrl(userVendorInfo.get("vendorApiUrl").toString()) + .clientId(userVendorInfo.get("vendorApiId").toString()) + .apiAuthKey(userVendorInfo.get("vendorApiKey").toString()) + .userId(gsoftTrxVO.getUserId()) + .build(); + JSONObject balanceRes = gsoftService.getBalanceUser(gsoftApiInfo); + if(balanceRes != null && balanceRes.getInt("result") == 1) { + log.info(LOG_PREFIX + "getBalanceUser::SUCC::AF_BALANCE::"+balance); + balance = balanceRes.getInt("balance"); + tranType = "balance"; + trxObj.put("tranType", tranType); + } else { + log.error(LOG_PREFIX + "Error Msg: BALANCE_ERROR"); + tranType = "credit"; + trxObj.put("tranType", tranType); + balance = balance + amount; + } + } + + trxObj.put("amount", amount); + trxObj.put("balance", balance); + + log.info(LOG_PREFIX + "param: " + trxObj.toString()); + + String url = userVendorInfo.get("siteCbUrl")+"/changebalance/syncBalance"; + org.springframework.http.ResponseEntity responseEntity = null; + try { + responseEntity = webClient.post() + .uri(url) + .headers(h -> { + h.add("Content-Type", "application/json"); + h.add("Accept", "application/json"); + h.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + }) + .bodyValue(trxObj.toString()) + .retrieve() + .toEntity(String.class) + .block(); + + log.info(LOG_PREFIX + "/syncBalance status code : {}" + responseEntity.getStatusCode()); + log.info(LOG_PREFIX + "body: " + responseEntity.getBody()); + } catch (WebClientRequestException wcre) { + Throwable cause = wcre.getCause(); + if(cause instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "### GSOFT API(syncBalance) ###::[ConnectTimeoutException]"+wcre.getMessage()); + } + if(cause instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "### GSOFT API(syncBalance) ###::[SocketTimeoutException]"+wcre.getMessage()); + } + if(cause instanceof InterruptedException) { + log.error(LOG_PREFIX+ "### GSOFT API(syncBalance) ###::[InterruptedException]"+wcre.getMessage()); + } + log.error(LOG_PREFIX+ "### GSOFT API(syncBalance) ###::[WebClientRequestException]"+wcre.getMessage()); + } catch (WebClientResponseException wre) { + String str = wre.getResponseBodyAsString(); + log.error(LOG_PREFIX+ "### GSOFT API(syncBalance) ###::[WebClientResponseException]"+str); + } + + JSONObject resData = new JSONObject(responseEntity != null ? responseEntity.getBody() : "{}"); + log.info(LOG_PREFIX + "result_code: " + resData.getInt("result_code")); + + if(resData.getLong("result_code") == 0) { + log.info(LOG_PREFIX + "CallBack::SUCC"); + } else { + log.error(LOG_PREFIX + "CallBack::FAIL"); + } + + response = new GsoftResponse(); + response.setResult(1); + response.setBalance(0); + httpStatus = HttpStatus.OK; + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "### GSOFT API(syncBalance) ###::[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "### GSOFT API(syncBalance) ###::[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "### GSOFT API(syncBalance) ###::[InterruptedException]"+rae.getMessage()); + } + + log.error(LOG_PREFIX+ "### GSOFT API(syncBalance) ###::[ResourceAccessException]"+rae.getMessage()); + + response = new GsoftResponse(); + response.setResult(1); + response.setBalance(0); + httpStatus = HttpStatus.OK; + + } catch (Exception e) { + log.error(LOG_PREFIX+ "### GSOFT API(syncBalance) ###::[Exception]"+e.getMessage()); + + response = new GsoftResponse(); + response.setResult(0); + response.setBalance(0); + httpStatus = HttpStatus.OK; + } + + ResponseEntity res = new ResponseEntity(response, httpStatus); + log.info(LOG_PREFIX+ "### GSOFT API(syncBalance) ###::syncBalance() Response: " + response.toString()); + + return res; + } + + + @ResponseBody + @RequestMapping(path = "/balance") + public ResponseEntity balance(HttpServletRequest request, @RequestParam("userid") String gsoftUserId) throws Exception { + GsoftResponse response = null; + HttpStatus httpStatus = null; + + try { + //사이트정보 + HashMap sParam = new HashMap(); + long siteIdx = Long.parseLong(gsoftUserId.substring(0, 3), 16); + String memberId = gsoftUserId.substring(3, gsoftUserId.length()); + log.info("#-Gsoft::balance::"+gsoftUserId+"::"+ "SITE_IDX: "+siteIdx+", USER INFO: " + memberId); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + + HashMap siteApiInfo = siteService.getSiteApiInfo(sParam); + if(siteApiInfo==null) { + log.error("#-Gsoft::balance::"+gsoftUserId+"::"+ "Error Msg: NOT_FOUND_SITE_INFO"); + response = new GsoftResponse(); + response.setResult(0); + response.setBalance(0); + httpStatus = HttpStatus.OK; + return new ResponseEntity(response, httpStatus); + } + + JSONObject member = new JSONObject(); + member.put("userId", memberId); + log.info("#-Gsoft::balance::"+gsoftUserId+"::"+ "Callback URL::" + siteApiInfo.get("siteCbUrl")+"/balance"); + log.info("#-Gsoft::balance::"+gsoftUserId+"::"+ "Callback Param::" + member.toString()); + + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/json"); + header.add("Accept", "application/json"); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + String url = siteApiInfo.get("siteCbUrl")+"/balance"; + org.springframework.http.ResponseEntity responseEntity = null; + try { + responseEntity = webClient.post() + .uri(url) + .headers(h -> { + h.add("Content-Type", "application/json"); + h.add("Accept", "application/json"); + h.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + }) + .bodyValue(member.toString()) + .retrieve() + .toEntity(String.class) + .block(); + + log.info("#-Gsoft::balance::"+gsoftUserId+"::"+ "Callback Status code::" + responseEntity.getStatusCode()); + log.info("#-Gsoft::balance::"+gsoftUserId+"::"+ "Callback Response body::" + responseEntity.getBody()); + } catch (WebClientRequestException wcre) { + Throwable cause = wcre.getCause(); + if(cause instanceof ConnectTimeoutException) { + log.error("#-Gsoft::balance::"+gsoftUserId+"::"+ "[ConnectTimeoutException]"+wcre.getMessage()); + } + if(cause instanceof SocketTimeoutException) { + log.error("#-Gsoft::balance::"+gsoftUserId+"::"+ "[SocketTimeoutException]"+wcre.getMessage()); + } + if(cause instanceof InterruptedException) { + log.error("#-Gsoft::balance::"+gsoftUserId+"::"+ "[InterruptedException]"+wcre.getMessage()); + } + log.error("#-Gsoft::balance::"+gsoftUserId+"::"+ "[WebClientRequestException]"+wcre.getMessage()); + } catch (WebClientResponseException wre) { + String str = wre.getResponseBodyAsString(); + log.error("#-Gsoft::balance::"+gsoftUserId+"::"+ "[WebClientResponseException]"+str); + } + + JSONObject resData = new JSONObject(responseEntity != null ? responseEntity.getBody() : "{}"); + int balance = resData.getInt("balance"); + + response = new GsoftResponse(); + response.setResult(1); + response.setBalance(balance); + httpStatus = HttpStatus.OK; + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error("#-Gsoft::balance::"+gsoftUserId+"::"+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error("#-Gsoft::balance::"+gsoftUserId+"::"+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error("#-Gsoft::balance::"+gsoftUserId+"::"+ "[InterruptedException]"+rae.getMessage()); + } + + log.error("#-Gsoft::balance::"+gsoftUserId+"::"+ "[ResourceAccessException]"+rae.getMessage()); + + response = new GsoftResponse(); + response.setResult(0); + response.setBalance(0); + httpStatus = HttpStatus.OK; + + } catch (Exception e) { + log.error("#-Gsoft::balance::"+gsoftUserId+"::"+ "[Exception]"+e.getMessage()); + + response = new GsoftResponse(); + response.setResult(0); + response.setBalance(0); + httpStatus = HttpStatus.OK; + } + + ResponseEntity res = new ResponseEntity(response, httpStatus); + log.info("#-Gsoft::balance::"+gsoftUserId+"::"+ "Response: "+response.toString()); + + return res; + } + + @ResponseBody + @RequestMapping(path = "/changeBalance") + public ResponseEntity changeBalance(HttpServletRequest request, @RequestBody GsoftVO gsoftVO) throws Exception { + GsoftResponse response = null; + HttpStatus httpStatus = null; + + String gsofIdx = gsoftVO.getRealRound(); + String gsofTranType = gsoftVO.getType().toUpperCase(); + String gsofGame = gsoftVO.getGame(); + String gsoftUserId = gsoftVO.getUserId(); + + final String LOG_PREFIX = "#-Gsoft::changeBalance::"+gsoftUserId+"::"+gsofGame+"::"+gsofIdx+"::"+gsofTranType+"::::"; + + try { + log.info(LOG_PREFIX+ "GsoftVO::"+gsoftVO.toString()); + + //사이트정보 + long siteIdx = Long.parseLong(gsoftUserId.substring(0, 3), 16); + String memberId = gsoftUserId.substring(3, gsoftUserId.length()); + log.info(LOG_PREFIX+ "SITE_IDX: "+siteIdx+", USER INFO: " + memberId); + /* + HashMap memParam = new HashMap<>(); + memParam.put("siteIdx", siteIdx); + memParam.put("memberId", memberId); + memParam.put("vendorGameCode", gsofGame); + HashMap userVendorInfo = siteService.getUserVendorInfo(memParam); + log.info(LOG_PREFIX+ "userVendorInfo::"+userVendorInfo.toString()); + */ + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "gsoft"); + sParam.put("vendorGameCode", gsofGame); + log.info(LOG_PREFIX + "getSiteVendorInfo::"+sParam.toString()); + HashMap siteVendorInfo = siteService.getSiteVendorInfo(sParam); + if(siteVendorInfo == null || siteVendorInfo.get("vendorApiId") == null) { + log.error(LOG_PREFIX+ "Error Msg: NOT_FOUND_SITE_INFO"); + response = new GsoftResponse(); + response.setResult(0); + response.setBalance(0); + httpStatus = HttpStatus.OK; + return new ResponseEntity(response, httpStatus); + } + String siteId = siteVendorInfo.get("siteId").toString(); + + if(gsoftVO.getType().equals("bet")) { + // bet 요청 + response = callDebit(gsoftVO, siteVendorInfo, siteId, memberId, LOG_PREFIX); + + } else if(gsoftVO.getType().equals("win") || gsoftVO.getType().equals("lose") || gsoftVO.getType().equals("cancel")) { + // win, lose, cancel 요청 + if(gsoftVO.getType().equals("lose")) { + // 미당첨 시 금액 == 0 + gsoftVO.setAmount(0); + } + response = callCredit(gsoftVO, siteVendorInfo, siteId, memberId, LOG_PREFIX); + + } else { + } + + if(response != null && response.getResult() == 1) { + httpStatus = HttpStatus.OK; + } else { + response = new GsoftResponse(); + response.setResult(0); + response.setBalance(0); + httpStatus = HttpStatus.OK; + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + log.error(LOG_PREFIX+ "[ResourceAccessException]"+rae.getMessage()); + + response = new GsoftResponse(); + response.setResult(0); + response.setBalance(0); + httpStatus = HttpStatus.OK; + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.getMessage()); + + response = new GsoftResponse(); + response.setResult(0); + response.setBalance(0); + httpStatus = HttpStatus.OK; + } + + ResponseEntity res = new ResponseEntity(response, httpStatus); + log.info(LOG_PREFIX+ "Response: "+response.toString() + ", HttpStatus: " + httpStatus); + + return res; + } + + + private GsoftResponse callDebit(GsoftVO gsoftVO, HashMap siteVendorInfo, String siteId, String memberId, final String LOG_PREFIX) { + GsoftResponse response = null; + + log.info(LOG_PREFIX+ "callDebit::START"); + try { + String vendorTranKey = gsoftVO.getTranId(); + String tranId = siteId + "#" + vendorTranKey; + String betId = siteId + "#" + gsoftVO.getRealRound(); + + // 중복체크 + long chs1 = System.currentTimeMillis(); + int betCnt = siteService.getBotaBetCnt(tranId); + long che1 = System.currentTimeMillis(); // 코드 실행 후에 시간 받아오기 + double diff1 = (chs1 - che1)/1000.0; //두 시간에 차 계산 + log.error(LOG_PREFIX+ "Duplicate check::" + String.format("%.3f", diff1)); + if(betCnt != 0) { + response = new GsoftResponse(); + response.setResult(0); + response.setBalance(0); + log.error(LOG_PREFIX + "Duplicate tranId: " + tranId); + return response; + } + + int amount = Math.abs(gsoftVO.getAmount()); + long amountL = amount; + long targetSiteCredit = Long.parseLong(siteVendorInfo.get("credit").toString()); + if(targetSiteCredit < amountL) { + response = new GsoftResponse(); + response.setResult(0); + response.setBalance(0); + log.error(LOG_PREFIX + "no_site_credit"); + return response; + } + long siteMaxBet = Long.parseLong(siteVendorInfo.get("siteMaxBet").toString()); + if(siteMaxBet < amount) { + log.error(LOG_PREFIX+ "MAX_BET_AMOUNT_OVER"); + log.error(LOG_PREFIX+ "siteMaxBet : " + siteMaxBet +", amount : " + amount); + response = new GsoftResponse(); + response.setResult(0); + response.setBalance(0); + log.error(LOG_PREFIX + "MAX_BET_AMOUNT_OVER"); + return response; + } + + long siteIdx = Long.parseLong(siteVendorInfo.get("siteIdx").toString()); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + String siteCbUrl = siteVendorInfo.get("siteCbUrl").toString(); +// HashMap vendorInfo = siteService.getGsoftVendorInfo(gsoftVO.getGame()); + long vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "gsoft"); + tranParam.put("vendorTranKey", vendorTranKey); + tranParam.put("gameIdx", gsoftVO.getTitle()); + tranParam.put("tranType", "debit"); + tranParam.put("depositAmt", amount); + tranParam.put("creditAmt", "0"); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + + long startTime = System.currentTimeMillis(); + siteService.commonBetinsert(tranParam); + long endTime = System.currentTimeMillis(); // 코드 실행 후에 시간 받아오기 + double diffTime = (startTime - endTime)/1000.0; //두 시간에 차 계산 + if(diffTime < -1.0) { + log.error(LOG_PREFIX + "배팅 쓰기지연:"+diffTime+"초 지연발생"); + response = new GsoftResponse(); + response.setResult(0); + response.setBalance(0); + return response; + } + log.info(LOG_PREFIX + "siteService.commonBetinsert() END"); + /* + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/json"); + header.add("Accept", "application/json"); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + */ + JSONObject debit = new JSONObject(); + debit.put("betId", betId); + debit.put("tranId", tranId); + debit.put("userId", memberId); + debit.put("vendorIdx", vendorIdx); + debit.put("vendorKey", vendorKey); + debit.put("vendor", "gsoft"); + debit.put("gameIdx", vendorIdx); + debit.put("gameKey", gsoftVO.getTitle()); + debit.put("tranType", "debit"); + debit.put("debit", amount); + debit.put("credit", 0); + debit.put("isCancel", 0); + debit.put("isBonus", 0); + debit.put("requestAt", gsoftVO.getTime()); + + JSONObject resData = new JSONObject(); + if(vendorCetegory.equals("SLOT")) { + log.info(LOG_PREFIX + "SEND_DEBIT::changeBalanceSlot::param: " + debit.toString()); + resData = callBackService.changeBalanceSlot(LOG_PREFIX, siteVendorInfo, debit); + log.info(LOG_PREFIX + "SEND_DEBIT::changeBalanceSlot::status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_DEBIT::changeBalanceSlot::response body: " + resData.toString()); + } else { + log.info(LOG_PREFIX + "SEND_DEBIT::changeBalance::param: " + debit.toString()); + resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, debit); + log.info(LOG_PREFIX + "SEND_DEBIT::changeBalance::status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_DEBIT::changeBalance::response body: " + resData.toString()); + } + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "siteService.updateCbApi() END"); + int balance = resData.getInt("balance"); + + response = new GsoftResponse(); + response.setResult(1); + response.setBalance(balance); + } else { + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + log.error(LOG_PREFIX + "result_code:"+resData.getLong("result_code")); + log.error(LOG_PREFIX + "error_msg:"+msg); + response = new GsoftResponse(); + response.setResult(0); + response.setBalance(0); + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + log.error(LOG_PREFIX+ "[ResourceAccessException]"+rae.getMessage()); + + response = new GsoftResponse(); + response.setResult(0); + response.setBalance(0); + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+ e.toString()); + } + log.info(LOG_PREFIX+ "callDebit::END"); + + return response; + } + + + private GsoftResponse callCredit(GsoftVO gsoftVO, HashMap siteVendorInfo, String siteId, String memberId, final String LOG_PREFIX) { + GsoftResponse response = null; + + log.info(LOG_PREFIX+ "callCredit::START"); + try { + String vendorTranKey = gsoftVO.getTranId(); + String tranId = siteId + "#" + vendorTranKey; + String betId = siteId + "#" + gsoftVO.getRealRound(); + + // Debit 체크 + long chs1 = System.currentTimeMillis(); + int debitCnt = siteService.getSuccDebitCnt(betId); + long che1 = System.currentTimeMillis(); // 코드 실행 후에 시간 받아오기 + double diff1 = (chs1 - che1)/1000.0; //두 시간에 차 계산 + log.error(LOG_PREFIX+ "Debit check::" + String.format("%.3f", diff1)); + if(debitCnt == 0) { + response = new GsoftResponse(); + response.setResult(0); + response.setBalance(0); + log.error(LOG_PREFIX + "Not found success debit by betId: " + betId); + return response; + } + + // 중복체크 + long chs2 = System.currentTimeMillis(); + int betCnt = siteService.getBotaBetCnt(tranId); + long che2 = System.currentTimeMillis(); // 코드 실행 후에 시간 받아오기 + double diff2 = (chs2 - che2)/1000.0; //두 시간에 차 계산 + log.error(LOG_PREFIX+ "Duplicate check::" + String.format("%.3f", diff2)); + if(betCnt != 0) { + response = new GsoftResponse(); + response.setResult(0); + response.setBalance(0); + log.error(LOG_PREFIX + "Duplicate tranId: " + tranId); + return response; + } + + int amount = Math.abs(gsoftVO.getAmount()); + + long siteIdx = Long.parseLong(siteVendorInfo.get("siteIdx").toString()); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + String siteCbUrl = siteVendorInfo.get("siteCbUrl").toString(); +// HashMap vendorInfo = siteService.getGsoftVendorInfo(gsoftVO.getGame()); + long vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "gsoft"); + tranParam.put("vendorTranKey", vendorTranKey); + tranParam.put("gameIdx", gsoftVO.getTitle()); + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", 0); + tranParam.put("creditAmt", amount); + if(gsoftVO.getType().equals("cancel")) { + tranParam.put("isCancel", "Y"); + } else { + // win, lose + tranParam.put("isCancel", "N"); + } + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + + long startTime = System.currentTimeMillis(); + siteService.commonBetinsert(tranParam); + long endTime = System.currentTimeMillis(); // 코드 실행 후에 시간 받아오기 + double diffTime = (startTime - endTime)/1000.0; //두 시간에 차 계산 + if(diffTime < -1.0) { + log.error(LOG_PREFIX + "배팅 쓰기지연:"+diffTime+"초 지연발생"); + response = new GsoftResponse(); + response.setResult(0); + response.setBalance(0); + return response; + } + log.info(LOG_PREFIX + "siteService.commonBetinsert() END"); + /* + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/json"); + header.add("Accept", "application/json"); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + */ + JSONObject credit = new JSONObject(); + credit.put("betId", betId); + credit.put("tranId", tranId); + credit.put("userId", memberId); + credit.put("vendorIdx", vendorIdx); + credit.put("vendorKey", vendorKey); + credit.put("vendor", "gsoft"); + credit.put("gameIdx", vendorIdx); + credit.put("gameKey", gsoftVO.getTitle()); + credit.put("tranType", "credit"); + credit.put("debit", 0); + credit.put("credit", amount); + if(gsoftVO.getType().equals("cancel")) { + credit.put("isCancel", 1); + } else { + // win, lose + credit.put("isCancel", 0); + } + credit.put("isBonus", 0); + credit.put("requestAt", gsoftVO.getTime()); + + JSONObject resData = new JSONObject(); + if(vendorCetegory.equals("SLOT")) { + log.info(LOG_PREFIX + "SEND_CREDIT::changeBalanceSlot::param: " + credit.toString()); + resData = callBackService.changeBalanceSlot(LOG_PREFIX, siteVendorInfo, credit); + log.info(LOG_PREFIX + "SEND_CREDIT::changeBalanceSlot::status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_CREDIT::changeBalanceSlot::response body: " + resData.toString()); + } else { + log.info(LOG_PREFIX + "SEND_CREDIT::changeBalance::param: " + credit.toString()); + resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, credit); + log.info(LOG_PREFIX + "SEND_CREDIT::changeBalance::status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_CREDIT::changeBalance::response body: " + resData.toString()); + } + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "siteService.updateCbApi() END"); + + int balance = resData.getInt("balance"); + + response = new GsoftResponse(); + response.setResult(1); + response.setBalance(balance); + } else { + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + log.error(LOG_PREFIX + "error_msg:"+msg); + response = new GsoftResponse(); + response.setResult(0); + response.setBalance(0); + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + log.error(LOG_PREFIX+ "[ResourceAccessException]"+rae.getMessage()); + + response = new GsoftResponse(); + response.setResult(0); + response.setBalance(0); + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+ e.toString()); + } + log.info(LOG_PREFIX+ "callCredit::END"); + + return response; + } +} diff --git a/src/main/java/com/bb/front/CallbackPandaController.java b/src/main/java/com/bb/front/CallbackPandaController.java new file mode 100644 index 0000000..30b36e2 --- /dev/null +++ b/src/main/java/com/bb/front/CallbackPandaController.java @@ -0,0 +1,965 @@ +package com.bb.front; + +import java.net.SocketTimeoutException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; + +import org.apache.http.conn.ConnectTimeoutException; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.ResourceAccessException; + +import com.bb.model.PandaResponse; +import com.bb.service.AsyncSiteService; +import com.bb.service.CallBackService; +import com.bb.service.SiteService; + +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@RequestMapping("/api/cb/panda") +@RequiredArgsConstructor +@SecurityRequirement(name = "Authorization") +@EnableScheduling +@RestController +public class CallbackPandaController { + + @Autowired + SiteService siteService; + + @Autowired + CallBackService callBackService; + + @Autowired + AsyncSiteService asyncCallBackService; + + @ResponseBody + @RequestMapping(path = "/balance") + public ResponseEntity balance(HttpServletRequest request, @RequestParam("username") String username) throws Exception { + PandaResponse response = null; + + long siteIdx = 0L; + try { + siteIdx = Long.parseLong(username.substring(0, 3), 16); + } catch (NumberFormatException e) { + log.error("#-CB::PANDA::balance::Invalid username format (hex expected): {}", username); + log.error("#-CB::PANDA::balance::Error Msg: NOT_FOUND_USER"); + response = new PandaResponse(); + response.setBalance(0); + return new ResponseEntity(response, HttpStatus.BAD_REQUEST); + } + String memberId = username.substring(3, username.length()); + final String LOG_PREFIX = "#-CB::PANDA::balance::"+memberId+":::"; + log.info(LOG_PREFIX+ "Request::" + username); + + try { + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + log.info(LOG_PREFIX + "SITE_API_INFO_PARAM::"+sParam.toString()); + HashMap siteApiInfo = siteService.getSiteApiInfo(sParam); + if(siteApiInfo == null) { + log.error(LOG_PREFIX+ "Error Msg: NOT_FOUND_SITE_INFO"); + response = new PandaResponse(); + response.setBalance(0); + return new ResponseEntity(response, HttpStatus.BAD_REQUEST); + } + + if(siteApiInfo.get("memberIdx") == null) { + log.error(LOG_PREFIX+ "존재하지 않는 회원"); + response = new PandaResponse(); + response.setBalance(0); + return new ResponseEntity(response, HttpStatus.BAD_REQUEST); + } + + // ##--isTransfer 처리-## + int balance = 0; + if("N".equals(siteApiInfo.get("isTransfer").toString())) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + JSONObject member = new JSONObject(); + member.put("userId", memberId); + log.info(LOG_PREFIX+ "balance Req ::"+ member.toString()); + JSONObject resData = callBackService.getBalance(siteApiInfo, member); + if(resData == null) { + log.error(LOG_PREFIX+ "Error Msg: BALANCE_CALLBACK_ERROR"); + response = new PandaResponse(); + response.setBalance(0); + return new ResponseEntity(response, HttpStatus.BAD_REQUEST); + } + log.info(LOG_PREFIX+ "balance Res ::"+ resData.toString()); + balance = resData.getInt("balance"); + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + balance = siteService.getUserBalance(balanceMap); + + if(siteApiInfo.get("siteCbUrl") != null && !"".equals(siteApiInfo.get("siteCbUrl").toString())) { + JSONObject member = new JSONObject(); + member.put("userId", memberId); + member.put("balance", balance); + asyncCallBackService.asyncBalance(LOG_PREFIX, siteApiInfo, member); + } + } + + response = new PandaResponse(); + response.setBalance(balance); + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + response = new PandaResponse(); + response.setBalance(0); + return new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + response = new PandaResponse(); + response.setBalance(0); + return new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + ResponseEntity res = new ResponseEntity(response, HttpStatus.OK); + log.info(LOG_PREFIX+ "Response::" + response.toString()); + + return res; + } + + + @ResponseBody + @RequestMapping(path = "/changeBalance") + public ResponseEntity changeBalance(HttpServletRequest request, @RequestBody net.sf.json.JSONObject requestBody) throws Exception { + ResponseEntity resEntity = null; + + String username = requestBody.getString("username"); + long siteIdx = 0L; + try { + siteIdx = Long.parseLong(username.substring(0, 3), 16); + } catch (NumberFormatException e) { + log.error("#-CB::PANDA::changeBalance::Invalid username format (hex expected): {}", username); + log.error("#-CB::PANDA::changeBalance::Error Msg: NOT_FOUND_USER"); + PandaResponse response = new PandaResponse(); + resEntity = new ResponseEntity(response, HttpStatus.BAD_REQUEST); + return resEntity; + } + String memberId = username.substring(3, username.length()); + net.sf.json.JSONObject transaction = requestBody.getJSONObject("transaction"); + net.sf.json.JSONObject game = transaction.getJSONObject("details").getJSONObject("game"); + String transactionId = transaction.getString("id"); + String transactionType = transaction.getString("type"); + + final String LOG_PREFIX = "#-CB::PANDA::changeBalance::"+memberId+"::"+transactionId+"::"+transactionType+":::"; + log.info(LOG_PREFIX+ "Request::" + requestBody.toString()); + + try { + // "processed_at":"2025-01-16T09:25:23.000000Z" + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS"); + String betDateTimeStr = transaction.getString("processed_at"); + log.info(LOG_PREFIX+ "========== BF_betDateTimeStr::" + betDateTimeStr); + betDateTimeStr = betDateTimeStr.substring(0, 19); + betDateTimeStr = betDateTimeStr.replace("T", " "); + log.info(LOG_PREFIX+ "========== MF_betDateTimeStr::" + betDateTimeStr); + betDateTimeStr = makeEdate(LOG_PREFIX, betDateTimeStr, 32400000); + log.info(LOG_PREFIX+ "========== AF_betDateTimeStr::" + betDateTimeStr); + + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "panda"); + sParam.put("vendorGameCode", game.getString("vendor")); + log.info(LOG_PREFIX + "getSiteVendorInfo::"+sParam.toString()); + HashMap siteVendorInfo = siteService.getSiteVendorInfo(sParam); + if(siteVendorInfo == null) { + log.error(LOG_PREFIX+ "존재하지 않는 회원입니다"); + PandaResponse response = new PandaResponse(); + resEntity = new ResponseEntity(response, HttpStatus.BAD_REQUEST); + return resEntity; + } + + if(transactionType.equals("bet")) { + int amount = Math.abs(requestBody.getInt("amount")); + resEntity = callBet(LOG_PREFIX, siteIdx, memberId, transaction, betDateTimeStr, siteVendorInfo, amount); + + } else if(transactionType.equals("win")) { + int amount = Math.abs(requestBody.getInt("amount")); + resEntity = callWin(LOG_PREFIX, siteIdx, memberId, transaction, betDateTimeStr, siteVendorInfo, amount); + + } else if(transactionType.equals("cancel")) { + int amount = Math.abs(requestBody.getInt("amount")); + resEntity = callCancel(LOG_PREFIX, siteIdx, memberId, transaction, betDateTimeStr, siteVendorInfo, amount); + + } else if(transactionType.equals("adjust")) { + int amount = requestBody.getInt("amount"); + resEntity = callAdjust(LOG_PREFIX, siteIdx, memberId, transaction, betDateTimeStr, siteVendorInfo, amount); + + } else if(transactionType.equals("promo_win")) { + int amount = Math.abs(requestBody.getInt("amount")); + resEntity = callPromoWin(LOG_PREFIX, siteIdx, memberId, transaction, betDateTimeStr, siteVendorInfo, amount); + + } else if(transactionType.equals("exceed_credit")) { + log.info(LOG_PREFIX+ "Response::" + resEntity.toString()); + PandaResponse response = new PandaResponse(); + resEntity = new ResponseEntity(response, HttpStatus.OK); + + } else if(transactionType.equals("tip")) { + log.info(LOG_PREFIX+ "Response::" + resEntity.toString()); + PandaResponse response = new PandaResponse(); + resEntity = new ResponseEntity(response, HttpStatus.OK); + + } else if(transactionType.equals("charge")) { + log.info(LOG_PREFIX+ "Response::" + resEntity.toString()); + PandaResponse response = new PandaResponse(); + resEntity = new ResponseEntity(response, HttpStatus.OK); + + } + + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + PandaResponse response = new PandaResponse(); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + return resEntity; + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + PandaResponse response = new PandaResponse(); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + return resEntity; + } + + + log.info(LOG_PREFIX+ "Response::" + resEntity.toString()); + return resEntity; + } + + + private ResponseEntity callBet(String LOG_PREFIX, long siteIdx, String memberId, + net.sf.json.JSONObject transaction, String betDateTimeStr, HashMap siteVendorInfo, + int amount) { + + LOG_PREFIX = LOG_PREFIX + "callBet:::"; + ResponseEntity resEntity = null; + PandaResponse response = new PandaResponse(); + + // ##--isTransfer 처리-## + final String IS_TRANSFER = siteVendorInfo.get("isTransfer").toString(); + + try { + net.sf.json.JSONObject details = transaction.getJSONObject("details"); + net.sf.json.JSONObject game = details.getJSONObject("game"); + + String gameType = game.getString("type").replaceAll(" ", "").toLowerCase(); + String gameName = game.getString("title"); + String gameId = game.getString("id"); + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + String tranId = transaction.getString("id"); + String betId = game.getString("id")+"#"+game.getString("round"); + //String betKey = transaction.getString("referer_id"); + String betKey = betId; + + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("Y")) { + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(tranId); + if(cntTr > 0) { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + response.setBalance(balance); + log.error(LOG_PREFIX+ "중복요청::Response::" + response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + } + + if(siteVendorInfo.get("lastInVendorIdx")==null || "0".equals(siteVendorInfo.get("lastInVendorIdx").toString())) { + HashMap memParam = new HashMap<>(); + memParam.put("siteIdx", siteIdx); + memParam.put("memberIdx", memberIdx); + memParam.put("lastInVendorIdx", Integer.parseInt(siteVendorInfo.get("vendorIdx").toString())); + int updResult = siteService.updMemLastVendorIdx(memParam); + } else { + int lastInVendorIdx = Integer.parseInt(siteVendorInfo.get("lastInVendorIdx").toString()); + if(lastInVendorIdx != vendorIdx) { + log.error(LOG_PREFIX+ "VendorIdx doesn't match"); + resEntity = new ResponseEntity(response, HttpStatus.BAD_REQUEST); + return resEntity; + } + } + + long siteCredit = Long.parseLong(siteVendorInfo.get("credit").toString()); + // ##--isTransfer 처리-## + if(siteCredit < amount && IS_TRANSFER.equals("N")) { + log.error(LOG_PREFIX+ "NO_SITE_CREDIT"); + resEntity = new ResponseEntity(response, HttpStatus.BAD_REQUEST); + return resEntity; + } + + // 최대 베팅 금액 처리 (userMaxBet 우선 적용) + long siteMaxBet = Long.parseLong(siteVendorInfo.get("siteMaxBet").toString()); + long userMaxBet = 0; + if(siteVendorInfo.get("userMaxBet") != null && !siteVendorInfo.get("userMaxBet").toString().isEmpty()) { + try { + userMaxBet = Long.parseLong(siteVendorInfo.get("userMaxBet").toString()); + } catch (NumberFormatException e) { + userMaxBet = 0; + } + } + + // 최종 maxBet 결정: userMaxBet이 0이면 siteMaxBet 사용, 0이 아니면 userMaxBet 사용 + long finalMaxBet = (userMaxBet > 0) ? userMaxBet : siteMaxBet; + log.info(LOG_PREFIX+ "MaxBet Info - siteMaxBet: " + siteMaxBet + ", userMaxBet: " + userMaxBet + ", finalMaxBet: " + finalMaxBet); + if(finalMaxBet < amount) { + log.error(LOG_PREFIX+ "MAX_BET_AMOUNT_OVER"); + log.error(LOG_PREFIX+ "finalMaxBet : " + finalMaxBet +", amount : " + amount); + resEntity = new ResponseEntity(response, HttpStatus.BAD_REQUEST); + return resEntity; + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "panda"); + tranParam.put("vendorTranKey", betKey); + tranParam.put("gameType", gameType); + tranParam.put("gameId", gameId); + tranParam.put("gameIdx", gameName); + tranParam.put("tranType", "debit"); + tranParam.put("depositAmt", amount); + tranParam.put("creditAmt", "0"); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "P"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("betKey", betKey); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "panda"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", gameName); + callBackObj.put("gameId", gameId); + callBackObj.put("gameType", gameType); + callBackObj.put("tranType", "debit"); + callBackObj.put("debit", amount); + callBackObj.put("credit", 0); + callBackObj.put("isCancel", 0); + callBackObj.put("isBonus", 0); + callBackObj.put("isData", "Y"); + callBackObj.put("requestAt", betDateTimeStr); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("N")) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + log.info(LOG_PREFIX + "-----INSERT_BET_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_BET_END-----"); + + log.info(LOG_PREFIX + "SEND_BET request body: " + callBackObj.toString()); + JSONObject resData = null; + if(vendorCetegory.equals("SLOT")) { + resData = callBackService.changeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } else { + resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } + log.info(LOG_PREFIX + "SEND_BET status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_BET response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + response.setBalance(balance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + } else if(resData.getLong("result_code") == 98) { + int balance = resData.getInt("balance"); + response.setBalance(balance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + } else if(resData.getLong("result_code") == 80) { + int balance = resData.getInt("balance"); + response.setBalance(balance); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } else { + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + log.error(LOG_PREFIX+ msg); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + int afBalance = balance - amount; + + if(balance < amount) { + response.setBalance(balance); + log.error(LOG_PREFIX+ "Response::금액을 확인하여 주세요::" + response.toString()); + return new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + log.info(LOG_PREFIX + "-----INSERT_BET_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_BET_END-----"); + + tranParam.put("balance", afBalance); + tranParam.put("preBalance", balance); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + response.setBalance(afBalance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + + if(siteVendorInfo.get("siteCbUrl") != null && !"".equals(siteVendorInfo.get("siteCbUrl").toString())) { + callBackObj.put("balance", afBalance); + if(vendorCetegory.equals("SLOT")) { + asyncCallBackService.asyncChangeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } else { + asyncCallBackService.asyncChangeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } + } + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + return resEntity; + } + + + private ResponseEntity callWin(String LOG_PREFIX, long siteIdx, String memberId, + net.sf.json.JSONObject transaction, String betDateTimeStr, HashMap siteVendorInfo, + int amount) { + + LOG_PREFIX = LOG_PREFIX + "callWin:::"; + ResponseEntity resEntity = null; + PandaResponse response = new PandaResponse(); + + // ##--isTransfer 처리-## + final String IS_TRANSFER = siteVendorInfo.get("isTransfer").toString(); + + try { + net.sf.json.JSONObject details = transaction.getJSONObject("details"); + net.sf.json.JSONObject game = details.getJSONObject("game"); + + String gameType = game.getString("type").replaceAll(" ", "").toLowerCase(); + String gameName = game.getString("title"); + String gameId = game.getString("id"); + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + String tranId = transaction.getString("id"); + String betId = game.getString("id")+"#"+game.getString("round"); + //String betKey = transaction.getString("referer_id"); + String betKey = betId; + + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("Y")) { + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(tranId); + if(cntTr > 0) { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + response.setBalance(balance); + log.error(LOG_PREFIX+ "중복요청::Response::" + response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + + // 베팅 체크 + int cntBet = siteService.getBetIdCheck2(betId); + if(cntBet == 0) { + // 처리한 베팅 존재X + log.error(LOG_PREFIX+ "처리한 베팅 존재X"); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + return resEntity; + } + } + + //초과베팅 체크 + int overCreditAmt = 0; + if(vendorCetegory.equals("SLOT")) { + int siteMaxWin = Integer.parseInt(siteVendorInfo.get("siteMaxWin").toString()); + if(siteMaxWin < amount && siteMaxWin != 0) { + log.error(LOG_PREFIX+ "MAX_WIN_AMOUNT_OVER"); + log.error(LOG_PREFIX+ "siteMaxWin : " + siteMaxWin +", amount : " + amount); + overCreditAmt = amount - siteMaxWin; + amount = siteMaxWin; + log.error(LOG_PREFIX+ "Change amount : " + amount +", overCreditAmt : " + overCreditAmt); + } + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "panda"); + tranParam.put("vendorTranKey", betKey); + tranParam.put("gameType", gameType); + tranParam.put("gameId", gameId); + tranParam.put("gameIdx", gameName); + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + tranParam.put("overCreditAmt", overCreditAmt); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "P"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("betKey", betKey); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "panda"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", gameName); + callBackObj.put("gameId", gameId); + callBackObj.put("gameType", gameType); + callBackObj.put("tranType", "credit"); + callBackObj.put("debit", 0); + callBackObj.put("credit", amount); + callBackObj.put("isCancel", 0); + callBackObj.put("isBonus", 0); + callBackObj.put("isData", "Y"); + callBackObj.put("requestAt", betDateTimeStr); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("N")) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + log.info(LOG_PREFIX + "-----INSERT_RESULT_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_RESULT_END-----"); + + log.info(LOG_PREFIX + "SEND_RESULT request body: " + callBackObj.toString()); + JSONObject resData = null; + if(vendorCetegory.equals("SLOT")) { + resData = callBackService.changeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } else { + resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } + log.info(LOG_PREFIX + "SEND_RESULT status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_RESULT response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + response.setBalance(balance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + } else if(resData.getLong("result_code") == 98) { + int balance = resData.getInt("balance"); + response.setBalance(balance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + } else { + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + log.error(LOG_PREFIX+ msg); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + int afBalance = balance + amount; + + if(balance < amount) { + response.setBalance(balance); + log.error(LOG_PREFIX+ "Response::금액을 확인하여 주세요::" + response.toString()); + return new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + log.info(LOG_PREFIX + "-----INSERT_RESULT_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_RESULT_END-----"); + + tranParam.put("balance", afBalance); + tranParam.put("preBalance", balance); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + response.setBalance(afBalance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + + if(siteVendorInfo.get("siteCbUrl") != null && !"".equals(siteVendorInfo.get("siteCbUrl").toString())) { + callBackObj.put("balance", afBalance); + if(vendorCetegory.equals("SLOT")) { + asyncCallBackService.asyncChangeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } else { + asyncCallBackService.asyncChangeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } + } + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + return resEntity; + } + + + private ResponseEntity callCancel(String LOG_PREFIX, long siteIdx, String memberId, + net.sf.json.JSONObject transaction, String betDateTimeStr, HashMap siteVendorInfo, + int amount) { + + LOG_PREFIX = LOG_PREFIX + "callCancel:::"; + ResponseEntity resEntity = null; + PandaResponse response = new PandaResponse(); + + // ##--isTransfer 처리-## + final String IS_TRANSFER = siteVendorInfo.get("isTransfer").toString(); + + return resEntity; + } + + + private ResponseEntity callAdjust(String LOG_PREFIX, long siteIdx, String memberId, + net.sf.json.JSONObject transaction, String betDateTimeStr, HashMap siteVendorInfo, + int amount) { + + LOG_PREFIX = LOG_PREFIX + "callAdjust:::"; + ResponseEntity resEntity = null; + PandaResponse response = new PandaResponse(); + + // ##--isTransfer 처리-## + final String IS_TRANSFER = siteVendorInfo.get("isTransfer").toString(); + + return resEntity; + } + + + private ResponseEntity callPromoWin(String LOG_PREFIX, long siteIdx, String memberId, + net.sf.json.JSONObject transaction, String betDateTimeStr, HashMap siteVendorInfo, + int amount) { + + LOG_PREFIX = LOG_PREFIX + "callPromoWin:::"; + ResponseEntity resEntity = null; + PandaResponse response = new PandaResponse(); + + // ##--isTransfer 처리-## + final String IS_TRANSFER = siteVendorInfo.get("isTransfer").toString(); + + try { + net.sf.json.JSONObject details = transaction.getJSONObject("details"); + net.sf.json.JSONObject game = details.getJSONObject("game"); + + String gameType = game.getString("type").replaceAll(" ", "").toLowerCase(); + String gameName = game.getString("title"); + String gameId = game.getString("id"); + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + + String tranId = transaction.getString("id"); + String betId = game.getString("id")+"#"+game.getString("round"); + //String betKey = transaction.getString("referer_id"); + String betKey = betId; + + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("Y")) { + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(tranId); + if(cntTr > 0) { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + response.setBalance(balance); + log.error(LOG_PREFIX+ "중복요청::Response::" + response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + } + + //초과베팅 체크 + int overCreditAmt = 0; + if(vendorCetegory.equals("SLOT")) { + int siteMaxWin = Integer.parseInt(siteVendorInfo.get("siteMaxWin").toString()); + if(siteMaxWin < amount && siteMaxWin != 0) { + log.error(LOG_PREFIX+ "MAX_WIN_AMOUNT_OVER"); + log.error(LOG_PREFIX+ "siteMaxWin : " + siteMaxWin +", amount : " + amount); + overCreditAmt = amount - siteMaxWin; + amount = siteMaxWin; + log.error(LOG_PREFIX+ "Change amount : " + amount +", overCreditAmt : " + overCreditAmt); + } + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "panda"); + tranParam.put("vendorTranKey", betKey); + tranParam.put("gameType", gameType); + tranParam.put("gameId", gameId); + tranParam.put("gameIdx", gameName); + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "P"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("betKey", betKey); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "panda"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", gameName); + callBackObj.put("gameId", gameId); + callBackObj.put("gameType", gameType); + callBackObj.put("tranType", "credit"); + callBackObj.put("debit", 0); + callBackObj.put("credit", amount); + callBackObj.put("isCancel", 0); + callBackObj.put("isBonus", 1); + callBackObj.put("isData", "Y"); + callBackObj.put("requestAt", betDateTimeStr); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("N")) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + log.info(LOG_PREFIX + "-----INSERT_PROMO_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_PROMO_END-----"); + + log.info(LOG_PREFIX + "SEND_PROMO request body: " + callBackObj.toString()); + JSONObject resData = null; + if(vendorCetegory.equals("SLOT")) { + resData = callBackService.changeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } else { + resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } + log.info(LOG_PREFIX + "SEND_PROMO status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_PROMO response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + tranParam.put("balance", resData.getInt("balance")); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + response.setBalance(balance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + } else if(resData.getLong("result_code") == 98) { + int balance = resData.getInt("balance"); + response.setBalance(balance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + } else { + String msg = ""; + if(resData.has("error_msg")) msg = resData.getString("error_msg"); + log.error(LOG_PREFIX+ msg); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + int afBalance = balance + amount; + + if(balance < amount) { + response.setBalance(balance); + log.error(LOG_PREFIX+ "Response::금액을 확인하여 주세요::" + response.toString()); + return new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + log.info(LOG_PREFIX + "-----INSERT_PROMO_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_PROMO_END-----"); + + tranParam.put("balance", afBalance); + tranParam.put("preBalance", balance); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + response.setBalance(afBalance); + resEntity = new ResponseEntity(response, HttpStatus.OK); + + if(siteVendorInfo.get("siteCbUrl") != null && !"".equals(siteVendorInfo.get("siteCbUrl").toString())) { + callBackObj.put("balance", afBalance); + if(vendorCetegory.equals("SLOT")) { + asyncCallBackService.asyncChangeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } else { + asyncCallBackService.asyncChangeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } + } + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + resEntity = new ResponseEntity(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + return resEntity; + } + + + private static String makeEdate(String LOG_PREFIX, String paramDate, int flag) { + // TODO Auto-generated method stub + String eDate = ""; + SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + try { + Date date = sdf1.parse(paramDate); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + calendar.add(Calendar.MILLISECOND, flag); + Date date2 = calendar.getTime(); + eDate = sdf2.format(date2); + } catch(Exception e) { + log.error(LOG_PREFIX+ "makeEdate::Exception::"+e.getMessage()); + } + return eDate; + } + +} diff --git a/src/main/java/com/bb/front/CallbackPinkController.java b/src/main/java/com/bb/front/CallbackPinkController.java new file mode 100644 index 0000000..215160d --- /dev/null +++ b/src/main/java/com/bb/front/CallbackPinkController.java @@ -0,0 +1,851 @@ +package com.bb.front; + +import java.net.SocketTimeoutException; +import java.util.HashMap; + +import jakarta.servlet.http.HttpServletRequest; + +import org.apache.http.conn.ConnectTimeoutException; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.ResourceAccessException; + +import com.bb.model.SvendorResponse; +import com.bb.service.AsyncSiteService; +import com.bb.service.CallBackService; +import com.bb.service.SiteService; + +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@RequestMapping("/api/callback/pink") +@RequiredArgsConstructor +@SecurityRequirement(name = "Authorization") +@EnableScheduling +@RestController +public class CallbackPinkController { + + @Autowired + SiteService siteService; + + @Autowired + CallBackService callBackService; + + @Autowired + AsyncSiteService asyncCallBackService; + + + @ResponseBody + @PostMapping(path = "/balance") + public ResponseEntity balance(HttpServletRequest request, @RequestBody net.sf.json.JSONObject requestBody) throws Exception { + + SvendorResponse response = new SvendorResponse(); + String vendorUsername = requestBody.getString("userid"); + String uuid = vendorUsername; + + //사이트정보 + HashMap siteApiInfo = siteService.getNewSiteApiInfo(vendorUsername); + long siteIdx = 0L; + String memberId = ""; + if(siteApiInfo != null) { + siteIdx = Long.parseLong(siteApiInfo.get("siteIdx").toString()); + memberId = siteApiInfo.get("memberId").toString(); + } else { + siteIdx = Long.parseLong(vendorUsername.substring(0, 3), 16); + memberId = vendorUsername.substring(3, vendorUsername.length()); + + //사이트정보 + HashMap sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + siteApiInfo = siteService.getSiteApiInfo(sParam); + } + + final String LOG_PREFIX = "#-CB::PINK::"+memberId+"::balance:::"; + log.info(LOG_PREFIX+ "Request Body::" + requestBody.toString()); + + try { + if(siteApiInfo == null) { + log.error(LOG_PREFIX+ "Error Msg: NOT_FOUND_SITE_INFO"); + response.setBalance("0"); + response.setId(uuid); + log.info(LOG_PREFIX+ "Response::"+response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + + if(siteApiInfo.get("memberIdx") == null) { + log.error(LOG_PREFIX+ "Error Msg: NOT_FOUND_SITE_USER"); + response.setBalance("0"); + response.setId(uuid); + log.info(LOG_PREFIX+ "Response::"+response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + + // ##--isTransfer 처리-## + int balance = 0; + if("N".equals(siteApiInfo.get("isTransfer").toString())) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + JSONObject member = new JSONObject(); + member.put("userId", memberId); + log.info(LOG_PREFIX+ "balance Req ::"+ member.toString()); + JSONObject resData = callBackService.getBalance(siteApiInfo, member); + if(resData == null) { + log.error(LOG_PREFIX+ "Error Msg: BALANCE_CALLBACK_ERROR"); + response.setBalance("0"); + response.setId(uuid); + log.info(LOG_PREFIX+ "Response::"+response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + log.info(LOG_PREFIX+ "balance Res ::"+ resData.toString()); + balance = resData.getInt("balance"); + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + balance = siteService.getUserBalance(balanceMap); + + if(siteApiInfo.get("siteCbUrl") != null && !"".equals(siteApiInfo.get("siteCbUrl").toString())) { + JSONObject member = new JSONObject(); + member.put("userId", memberId); + member.put("balance", balance); + asyncCallBackService.asyncBalance(LOG_PREFIX, siteApiInfo, member); + } + } + + response.setBalance(Integer.toString(balance)); + response.setId(uuid); + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + log.error(LOG_PREFIX+ "Error Msg: RESOURCE_ACCESS_ERROR"); + response.setBalance("0"); + response.setId(uuid); + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + + log.error(LOG_PREFIX+ "Error Msg: UNKNOWN_SERVER_ERROR"); + response.setBalance("0"); + response.setId(uuid); + } + + log.info(LOG_PREFIX+ "Response::"+response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + + + @ResponseBody + @PostMapping(path = "/bet") + public ResponseEntity callBet(HttpServletRequest request, @RequestBody net.sf.json.JSONObject requestBody) throws Exception { + + SvendorResponse response = new SvendorResponse(); + String vendorUsername = requestBody.getString("userid"); + String uuid = vendorUsername; + String vendorGameCode = requestBody.getString("vendor"); + + //사이트정보 + HashMap sParam = new HashMap<>(); + sParam.put("vendorUsername", vendorUsername); + sParam.put("vendor", "pink"); + sParam.put("vendorGameCode", vendorGameCode); + HashMap siteVendorInfo = siteService.getNewSiteVendorInfo(sParam); + long siteIdx = 0L; + String memberId = ""; + if(siteVendorInfo != null) { + siteIdx = Long.parseLong(siteVendorInfo.get("siteIdx").toString()); + memberId = siteVendorInfo.get("memberId").toString(); + } else { + siteIdx = Long.parseLong(vendorUsername.substring(0, 3), 16); + memberId = vendorUsername.substring(3, vendorUsername.length()); + + //사이트정보 + sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "pink"); + sParam.put("vendorGameCode", vendorGameCode); + siteVendorInfo = siteService.getSiteVendorInfo(sParam); + } + + final String LOG_PREFIX = "#-CB::PINK::"+memberId+"::BET::"+requestBody.getString("tr_id")+":::"; + log.info(LOG_PREFIX+ "Request Body::" + requestBody.toString()); + + if(siteVendorInfo == null) { + log.error(LOG_PREFIX+ "Error Msg: NOT_FOUND_SITE_INFO"); + response.setBalance("0"); + response.setId(uuid); + response.setStatuscode(1); + response.setStatus("NOT_FOUND_SITE_INFO"); + log.info(LOG_PREFIX+ "Response::"+response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + + // ##--isTransfer 처리-## + final String IS_TRANSFER = siteVendorInfo.get("isTransfer").toString(); + + // 배팅 고유ID + String transactionId = requestBody.getString("tr_id"); + log.info(LOG_PREFIX+ "transactionId::"+transactionId); + // 베팅 참조ID + String referenceId = requestBody.getString("ref_id"); + log.info(LOG_PREFIX+ "referenceId"+referenceId); + // 라운드 고유ID + String roundId = requestBody.getString("round"); + log.info(LOG_PREFIX+ "roundId::"+roundId); + String tranId = transactionId; + //String betId = referenceId; + String betId = roundId+"#"+vendorUsername; + // 베팅 시각 + String betDateTimeStr = requestBody.getString("processed_at"); + + // 게임타입 + String gameType = requestBody.getString("game_type").replaceAll(" ", "").toLowerCase(); + // 게임테이블 아이디 (optional) + String gameId = ""; + if(requestBody.has("game_code")) gameId = requestBody.getString("game_code"); + String targetTableId = gameId.replaceAll(" ", "").toLowerCase(); + String gameName = ""; + if(requestBody.has("title")) gameName = requestBody.getString("title"); + // 배팅액 + String amountS = requestBody.getString("amount"); + int amount = 0; + Double amountD = Double.parseDouble(amountS); + amount = amountD.intValue(); + + try { + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + + String banGameType = siteVendorInfo.get("banGameType").toString().replaceAll(" ", "").toLowerCase(); + String banGameId = siteVendorInfo.get("banGameId").toString().replaceAll(" ", "").toLowerCase(); + + if(!"".equals(gameType) && !"".equals(banGameType) && banGameType.contains(gameType+"|")) { + // Ban Game Type Exception + HashMap logParam = new HashMap(); + logParam.put("siteIdx", siteIdx); + logParam.put("memberIdx", memberIdx); + logParam.put("vendorIdx", vendorIdx); + logParam.put("statusCode", 501L); + logParam.put("callBackType", "debit"); + logParam.put("tranId", tranId); + logParam.put("callBackReqBody", "gameType:"+gameType+"이 블락설정"); + logParam.put("callBackResBody", ""); + logParam.put("errorCode", "BLOCK_GAME_TYPE"); + logParam.put("errorMsg", "gameType:"+gameType+"이 블락설정"); + long startTimestamp = System.currentTimeMillis(); + logParam.put("regDate", startTimestamp); + logParam.put("updDate", startTimestamp); + callBackService.insertCallBackErrLog(logParam); + log.error(LOG_PREFIX+ "Ban Game Type : " + gameType); + + response.setBalance("0"); + response.setId(uuid); + response.setStatuscode(1); + response.setStatus("BAN_GAME_TYPE_" + gameType); + log.info(LOG_PREFIX+ "Response::"+response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + + if(!"".equals(targetTableId) && !"".equals(banGameId) && banGameId.contains(targetTableId+"|")) { + // Ban Game Id Exception + HashMap logParam = new HashMap(); + logParam.put("siteIdx", siteIdx); + logParam.put("memberIdx", memberIdx); + logParam.put("vendorIdx", vendorIdx); + logParam.put("statusCode", 502L); + logParam.put("callBackType", "debit"); + logParam.put("tranId", tranId); + logParam.put("callBackReqBody", "gameId:"+gameId+"("+gameName+")이 블락설정"); + logParam.put("callBackResBody", ""); + logParam.put("errorCode", "BLOCK_GAME_ID"); + logParam.put("errorMsg", "gameId:"+gameId+"("+gameName+")이 블락설정"); + long startTimestamp = System.currentTimeMillis(); + logParam.put("regDate", startTimestamp); + logParam.put("updDate", startTimestamp); + callBackService.insertCallBackErrLog(logParam); + log.error(LOG_PREFIX+ "Ban Game Id : " + gameId); + + response.setBalance("0"); + response.setId(uuid); + response.setStatuscode(1); + response.setStatus("BAN_GAME_ID_" + gameId); + log.info(LOG_PREFIX+ "Response::"+response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + + if(siteVendorInfo.get("lastInVendorIdx")==null || "0".equals(siteVendorInfo.get("lastInVendorIdx").toString())) { + HashMap memParam = new HashMap<>(); + memParam.put("siteIdx", siteIdx); + memParam.put("memberIdx", memberIdx); + memParam.put("lastInVendorIdx", Integer.parseInt(siteVendorInfo.get("vendorIdx").toString())); + int updResult = siteService.updMemLastVendorIdx(memParam); + } else { + int lastInVendorIdx = Integer.parseInt(siteVendorInfo.get("lastInVendorIdx").toString()); + if(lastInVendorIdx != vendorIdx) { + log.error(LOG_PREFIX+ "VendorIdx doesn't match"); + response.setBalance("0"); + response.setId(uuid); + response.setStatuscode(1); + response.setStatus("ACCESS_VENDOR_MISSMATCH_"+lastInVendorIdx); + log.info(LOG_PREFIX+ "Response::"+response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + } + + long siteCredit = Long.parseLong(siteVendorInfo.get("credit").toString()); + // ##--isTransfer 처리-## + if(siteCredit < amount && IS_TRANSFER.equals("N")) { + log.error(LOG_PREFIX+ "NO_SITE_CREDIT"); + response.setBalance("0"); + response.setId(uuid); + response.setStatuscode(1); + response.setStatus("NO_SITE_CREDIT"); + log.info(LOG_PREFIX+ "Response::"+response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + + long siteMaxBet = Long.parseLong(siteVendorInfo.get("siteMaxBet").toString()); + if(siteMaxBet < amount) { + log.error(LOG_PREFIX+ "MAX_BET_AMOUNT_OVER"); + log.error(LOG_PREFIX+ "siteMaxBet : " + siteMaxBet +", amount : " + amount); + response.setBalance("0"); + response.setId(uuid); + response.setStatuscode(1); + response.setStatus("MAX_BET_AMOUNT_OVER"); + log.info(LOG_PREFIX+ "Response::"+response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("Y")) { + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(tranId); + if(cntTr > 0) { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + response.setBalance(Integer.toString(balance)); + response.setId(uuid); + response.setStatuscode(0); + response.setStatus("OK"); + log.error(LOG_PREFIX+ "중복요청::Response::" + response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "pink"); + tranParam.put("vendorTranKey", referenceId); + tranParam.put("gameType", gameType); + tranParam.put("gameId", gameId); + tranParam.put("gameIdx", gameName); + tranParam.put("tranType", "debit"); + tranParam.put("depositAmt", amount); + tranParam.put("creditAmt", "0"); + tranParam.put("isCancel", "N"); + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("betKey", referenceId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "pink"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", gameName); + callBackObj.put("gameId", gameId); + callBackObj.put("gameType", gameType); + callBackObj.put("tranType", "debit"); + callBackObj.put("debit", amount); + callBackObj.put("credit", 0); + callBackObj.put("isCancel", 0); + callBackObj.put("isBonus", 0); + callBackObj.put("requestAt", betDateTimeStr); + log.info(LOG_PREFIX + "SEND_BET request body: " + callBackObj.toString()); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("N")) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + log.info(LOG_PREFIX + "-----INSERT_BET_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_BET_END-----"); + + JSONObject resData = null; + if(vendorCetegory.equals("SLOT")) { + resData = callBackService.changeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } else { + resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } + log.info(LOG_PREFIX + "SEND_BET status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_BET response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + // 성공 + tranParam.put("balance", resData.getInt("balance")); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + response.setBalance(Integer.toString(balance)); + response.setId(uuid); + response.setStatuscode(0); + response.setStatus("OK"); + } else if(resData.getLong("result_code") == 98) { + // 중복 + int balance = resData.getInt("balance"); + response.setBalance(Integer.toString(balance)); + response.setId(uuid); + response.setStatuscode(0); + response.setStatus("OK"); + } else if(resData.getLong("result_code") == 80) { + // 중복 + int balance = resData.getInt("balance"); + response.setBalance(Integer.toString(balance)); + response.setId(uuid); + response.setStatuscode(0); + response.setStatus("OK"); + } else { + // 실패 + log.error(LOG_PREFIX+ "CALLBACK_ERROR"); + response.setBalance("0"); + response.setId(uuid); + response.setStatuscode(1); + response.setStatus("CALLBACK_ERROR"); + } + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + int afBalance = balance - amount; + + if(balance < amount) { + response.setBalance(Integer.toString(balance)); + response.setId(uuid); + response.setStatuscode(0); + response.setStatus("OK"); + log.error(LOG_PREFIX+ "잔액부족::Response::" + response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + + log.info(LOG_PREFIX + "-----INSERT_BET_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_BET_END-----"); + + tranParam.put("balance", afBalance); + tranParam.put("preBalance", balance); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + response.setBalance(Integer.toString(afBalance)); + response.setId(uuid); + response.setStatuscode(0); + response.setStatus("OK"); + + if(siteVendorInfo.get("siteCbUrl") != null && !"".equals(siteVendorInfo.get("siteCbUrl").toString())) { + callBackObj.put("balance", afBalance); + if(vendorCetegory.equals("SLOT")) { + asyncCallBackService.asyncChangeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } else { + asyncCallBackService.asyncChangeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } + } + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + log.error(LOG_PREFIX+ "Error Msg: RESOURCE_ACCESS_ERROR"); + response.setBalance("0"); + response.setId(uuid); + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + + log.error(LOG_PREFIX+ "Error Msg: UNKNOWN_SERVER_ERROR"); + response.setBalance("0"); + response.setId(uuid); + } + + log.info(LOG_PREFIX+ "Response::"+response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + + + @ResponseBody + @PostMapping(value = { "/win", "/cancel", "/promo"} ) + public ResponseEntity callResult(HttpServletRequest request, @RequestBody net.sf.json.JSONObject requestBody) throws Exception { + + SvendorResponse response = new SvendorResponse(); + String vendorUsername = requestBody.getString("userid"); + String uuid = vendorUsername; + String vendorGameCode = requestBody.getString("vendor"); + String callbackType = requestBody.getString("type"); + + //사이트정보 + HashMap sParam = new HashMap<>(); + sParam.put("vendorUsername", vendorUsername); + sParam.put("vendor", "pink"); + sParam.put("vendorGameCode", vendorGameCode); + HashMap siteVendorInfo = siteService.getNewSiteVendorInfo(sParam); + long siteIdx = 0L; + String memberId = ""; + if(siteVendorInfo != null) { + siteIdx = Long.parseLong(siteVendorInfo.get("siteIdx").toString()); + memberId = siteVendorInfo.get("memberId").toString(); + } else { + siteIdx = Long.parseLong(vendorUsername.substring(0, 3), 16); + memberId = vendorUsername.substring(3, vendorUsername.length()); + + //사이트정보 + sParam = new HashMap(); + sParam.put("siteIdx", siteIdx); + sParam.put("memberId", memberId); + sParam.put("vendor", "pink"); + sParam.put("vendorGameCode", vendorGameCode); + siteVendorInfo = siteService.getSiteVendorInfo(sParam); + } + + final String LOG_PREFIX = "#-CB::PINK::"+memberId+"::RESULT::"+requestBody.getString("tr_id")+":::"; + log.info(LOG_PREFIX+ "Request Body::" + requestBody.toString()); + + if(siteVendorInfo == null) { + log.error(LOG_PREFIX+ "Error Msg: NOT_FOUND_SITE_INFO"); + response.setBalance("0"); + response.setId(uuid); + response.setStatuscode(1); + response.setStatus("NOT_FOUND_SITE_INFO"); + log.info(LOG_PREFIX+ "Response::"+response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + + // ##--isTransfer 처리-## + final String IS_TRANSFER = siteVendorInfo.get("isTransfer").toString(); + + // 배팅 고유ID + String transactionId = requestBody.getString("tr_id"); + log.info(LOG_PREFIX+ "transactionId::"+transactionId); + // 베팅 참조ID + String referenceId = requestBody.getString("ref_id"); + log.info(LOG_PREFIX+ "referenceId"+referenceId); + // 라운드 고유ID + String roundId = requestBody.getString("round"); + log.info(LOG_PREFIX+ "roundId::"+roundId); + String tranId = transactionId; + //String betId = referenceId; + String betId = roundId+"#"+vendorUsername; + // 베팅 시각 + String betDateTimeStr = requestBody.getString("processed_at"); + + // 게임타입 + String gameType = requestBody.getString("game_type").replaceAll(" ", "").toLowerCase(); + // 게임테이블 아이디 (optional) + String gameId = ""; + if(requestBody.has("game_code")) gameId = requestBody.getString("game_code"); + // 게임코드 + if("promo".equals(callbackType)) { + gameId = callbackType; + } + + // 게임타이틀 + String gameName = "" ; + if(requestBody.has("title")) gameName = requestBody.getString("title"); + if("promo".equals(callbackType)) { + gameName =callbackType; + } + // 배팅액 + String amountS = requestBody.getString("amount"); + int amount = 0; + Double amountD = Double.parseDouble(amountS); + amount = amountD.intValue(); + + try { + if(siteVendorInfo == null) { + log.error(LOG_PREFIX+ "Error Msg: NOT_FOUND_SITE_INFO"); + response.setBalance("0"); + response.setId(uuid); + response.setStatuscode(1); + response.setStatus("NOT_FOUND_SITE_INFO"); + log.info(LOG_PREFIX+ "Response::"+response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + + String siteId = siteVendorInfo.get("siteId").toString(); + long memberIdx = Long.parseLong(siteVendorInfo.get("memberIdx").toString()); + String vendorApiId = siteVendorInfo.get("vendorApiId").toString(); + String vendorKey = siteVendorInfo.get("vendorKey").toString(); + int vendorIdx = Integer.parseInt(siteVendorInfo.get("vendorIdx").toString()); + String vendorCetegory = siteVendorInfo.get("vendorCetegory").toString(); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("Y")) { + // tranId 중복체크 + int cntTr = siteService.getTranIdCheck2(tranId); + if(cntTr > 0) { + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + response.setBalance(Integer.toString(balance)); + response.setId(uuid); + response.setStatuscode(0); + response.setStatus("OK"); + log.error(LOG_PREFIX+ "중복요청::Response::" + response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + + // 베팅 체크 + int cntBet = siteService.getBetIdCheck2(betId); + if(cntBet == 0) { + log.error(LOG_PREFIX+ "Error Msg: NOT_FOUND_BET_INFO"); + response.setBalance("0"); + response.setId(uuid); + response.setStatuscode(1); + response.setStatus("NOT_FOUND_BET_INFO"); + log.info(LOG_PREFIX+ "Response::"+response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + } else { + //베팅여부체크 + if("cancel".equals(callbackType)) { //베팅없으면 에러 + int checkBet = siteService.getSuccDebitCnt(betId); + if(checkBet==0) { + log.error(LOG_PREFIX+ "Error Msg: NOT_FOUND_BET_INFO"); + response.setBalance("0"); + response.setId(uuid); + response.setStatuscode(1); + response.setStatus("NOT_FOUND_BET_INFO"); + log.info(LOG_PREFIX+ "Response::"+response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } + } + } + + //초과베팅 체크 + int overCreditAmt = 0; + if(vendorCetegory.equals("SLOT") && "win".equals(callbackType)) { + int siteMaxWin = Integer.parseInt(siteVendorInfo.get("siteMaxWin").toString()); + if(siteMaxWin < amount && siteMaxWin != 0) { + log.error(LOG_PREFIX+ "MAX_WIN_AMOUNT_OVER"); + log.error(LOG_PREFIX+ "siteMaxWin : " + siteMaxWin +", amount : " + amount); + overCreditAmt = amount - siteMaxWin; + amount = siteMaxWin; + log.error(LOG_PREFIX+ "Change amount : " + amount +", overCreditAmt : " + overCreditAmt); + } + } + + HashMap tranParam = new HashMap(); + tranParam.put("tranId", tranId); + tranParam.put("refId", betId); + tranParam.put("siteIdx", siteIdx); + tranParam.put("siteId", siteId); + tranParam.put("memberIdx", memberIdx); + tranParam.put("memberId", memberId); + tranParam.put("vendorCetegory", vendorCetegory); + tranParam.put("vendorIdx", vendorIdx); + tranParam.put("vendorCode", "pink"); + tranParam.put("vendorTranKey", referenceId); + tranParam.put("gameType", gameType); + tranParam.put("gameId", gameId); + tranParam.put("gameIdx", gameName); + tranParam.put("tranType", "credit"); + tranParam.put("depositAmt", "0"); + tranParam.put("creditAmt", amount); + tranParam.put("overCreditAmt", overCreditAmt); + if("cancel".equals(callbackType)) { + tranParam.put("isCancel", "Y"); + } else { + tranParam.put("isCancel", "N"); + } + tranParam.put("isTie", "N"); + tranParam.put("apiStatus", 0); + tranParam.put("vendorApiId", vendorApiId); + + JSONObject callBackObj = new JSONObject(); + callBackObj.put("betId", betId); + callBackObj.put("tranId", tranId); + callBackObj.put("betKey", referenceId); + callBackObj.put("userId", memberId); + callBackObj.put("vendorIdx", vendorIdx); + callBackObj.put("vendorKey", vendorKey); + callBackObj.put("vendor", "pink"); + callBackObj.put("gameIdx", vendorIdx); + callBackObj.put("gameKey", gameName); + callBackObj.put("gameId", gameId); + callBackObj.put("gameType", gameType); + callBackObj.put("tranType", "credit"); + callBackObj.put("debit", 0); + callBackObj.put("credit", amount); + if("cancel".equals(callbackType)) { + callBackObj.put("isCancel", 1); + } else { + callBackObj.put("isCancel", 0); + } + if("promo".equals(callbackType)) { + callBackObj.put("isBonus", 1); + } else { + callBackObj.put("isBonus", 0); + } + callBackObj.put("requestAt", betDateTimeStr); + log.info(LOG_PREFIX + "SEND_RESULT request body: " + callBackObj.toString()); + + // ##--isTransfer 처리-## + if(IS_TRANSFER.equals("N")) { + log.info(LOG_PREFIX + "PLAY_SEAMLESS"); + log.info(LOG_PREFIX + "-----INSERT_RESULT_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_RESULT_END-----"); + + JSONObject resData = null; + if(vendorCetegory.equals("SLOT")) { + resData = callBackService.changeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } else { + resData = callBackService.changeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } + log.info(LOG_PREFIX + "SEND_RESULT status code: " + resData.getLong("result_code")); + log.info(LOG_PREFIX + "SEND_RESULT response body: " + resData.toString()); + + if(resData.getLong("result_code") == 0) { + // 성공 + tranParam.put("balance", resData.getInt("balance")); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + int balance = resData.getInt("balance"); + response.setBalance(Integer.toString(balance)); + response.setId(uuid); + response.setStatuscode(0); + response.setStatus("OK"); + } else if(resData.getLong("result_code") == 98) { + // 중복 + int balance = resData.getInt("balance"); + response.setBalance(Integer.toString(balance)); + response.setId(uuid); + response.setStatuscode(0); + response.setStatus("OK"); + } else { + // 실패 + log.error(LOG_PREFIX+ "CALLBACK_ERROR"); + response.setBalance("0"); + response.setId(uuid); + response.setStatuscode(1); + response.setStatus("CALLBACK_ERROR"); + } + } else { + log.info(LOG_PREFIX + "PLAY_TRANSFER"); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", siteIdx); + balanceMap.put("memberId", memberId); + int balance = siteService.getUserBalance(balanceMap); + int afBalance = balance + amount; + + log.info(LOG_PREFIX + "-----INSERT_RESULT_START-----"); + siteService.commonBetinsert(tranParam); + log.info(LOG_PREFIX + "-----INSERT_RESULT_END-----"); + + tranParam.put("balance", afBalance); + tranParam.put("preBalance", balance); + tranParam.put("isTransfer", IS_TRANSFER); + int res = siteService.updateCbApi(tranParam); + log.info(LOG_PREFIX + "UPDATE_CALLBACK_API_STATUS END"); + + response.setBalance(Integer.toString(afBalance)); + response.setId(uuid); + response.setStatuscode(0); + response.setStatus("OK"); + + if(siteVendorInfo.get("siteCbUrl") != null && !"".equals(siteVendorInfo.get("siteCbUrl").toString())) { + callBackObj.put("balance", afBalance); + if(vendorCetegory.equals("SLOT")) { + asyncCallBackService.asyncChangeBalanceSlot(LOG_PREFIX, siteVendorInfo, callBackObj); + } else { + asyncCallBackService.asyncChangeBalance(LOG_PREFIX, siteVendorInfo, callBackObj); + } + } + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + + log.error(LOG_PREFIX+ "Error Msg: RESOURCE_ACCESS_ERROR"); + response.setBalance("0"); + response.setId(uuid); + + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + e.printStackTrace(); + + log.error(LOG_PREFIX+ "Error Msg: UNKNOWN_SERVER_ERROR"); + response.setBalance("0"); + response.setId(uuid); + } + + log.info(LOG_PREFIX+ "Response::"+response.toString()); + return new ResponseEntity(response, HttpStatus.OK); + } +} diff --git a/src/main/java/com/bb/front/CallbackSpeedTestController.java b/src/main/java/com/bb/front/CallbackSpeedTestController.java new file mode 100644 index 0000000..c985b54 --- /dev/null +++ b/src/main/java/com/bb/front/CallbackSpeedTestController.java @@ -0,0 +1,747 @@ +package com.bb.front; + +import java.security.SecureRandom; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.Valid; + +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.bb.jwt.JwtManager; +import com.bb.model.ApiResponse; +import com.bb.model.CallbackTestResult; +import com.bb.model.Site; +import com.bb.service.CallBackTestService; +import com.bb.service.SiteService; +import com.bb.util.IPKit; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/api/t1/spdtest") +@CrossOrigin( + origins = { + "https://cms.cent-10.com", + "https://core.nsol.cc/", + "https://familys.cc/" + } + ) +public class CallbackSpeedTestController { + + @Autowired + SiteService siteService; + + @Autowired + CallBackTestService callBackTestService; + + @Autowired + private final JwtManager jwtManager; + + private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + private static final SecureRandom random = new SecureRandom(); + + public static List generateRandomStrings(int stringLength, int count) { + Set uniqueStrings = new HashSet<>(); + + while (uniqueStrings.size() < count) { + StringBuilder sb = new StringBuilder(stringLength); + for (int i = 0; i < stringLength; i++) { + sb.append(CHARACTERS.charAt(random.nextInt(CHARACTERS.length()))); + } + + // 시간 기반으로 중복 확률 줄이기 (나노타임 일부 추가) + sb.append(Long.toHexString(System.nanoTime()).substring(0, 4)); + + uniqueStrings.add(sb.toString()); + } + + return new ArrayList<>(uniqueStrings); + } + + + @GetMapping("/testBalance") + public ApiResponse testBalance(HttpServletRequest request, @RequestHeader String token, @Valid @RequestParam String memberId) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + Site site = siteService.getSiteInfo(request); + if(site == null) { + log.error("#-CB::SPD_TEST::testBalance::Authorization apiKey check"); + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("#-CB::SPD_TEST::testBalance::site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + apiResponse.setResultMessage("Deniend IP"); + return apiResponse; + } + + if(token == null || token.equals("")) { + log.error("#-CB::SPD_TEST::testBalance::Authorization apiKey check"); + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization token check"); + return apiResponse; + } + + try { + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfo(token); + final String LOG_PREFIX = "#-CB::SPD_TEST::testBalance::"+tokenInfo.getSid()+"::"; + + int testCnt = site.getTestCnt(); + if(testCnt > 30) { + log.error(LOG_PREFIX+ "TEST_COUNT_OVER"); + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("TEST_COUNT_OVER"); + return apiResponse; + } + + // 여기서 부터 로직 + List resultList = new ArrayList<>(); + + JSONObject requestBody = new JSONObject(); + requestBody.put("userId", memberId); + + for(int i=1; i<=10; i++) { + JSONObject responseObj = callBackTestService.getBalance(LOG_PREFIX, site.getSiteCbUrl(), requestBody); + int resultCode = responseObj.getInt("result_code"); + CallbackTestResult result = new CallbackTestResult(); + result.setIndex(i); + result.setTimeMs(responseObj.getLong("timeMs")); + responseObj.remove("timeMs"); + + if(resultCode == 0) { + result.setStatus("SUCCESS"); + result.setMsg("[balance] 성공"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + + resultList.add(result); + } else { + result.setStatus("FAIL"); + if(resultCode == -99) { + result.setMsg(responseObj.getString("error_msg")); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(""); + } else { + result.setMsg("[balance] 실패"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + } + + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + return apiResponse; + } + + Thread.sleep(500); + } + + responseData.put("resultList", resultList); + + site.setTestCnt(testCnt+1); + int updResult = siteService.updateTestCnt(site); + + apiResponse.setData(responseData); + apiResponse.success(); + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @GetMapping("/testCasino") + public ApiResponse testCasino(HttpServletRequest request, @RequestHeader String token, @Valid @RequestParam String memberId) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + Site site = siteService.getSiteInfo(request); + if(site == null) { + log.error("#-CB::SPD_TEST::testCasino::Authorization apiKey check"); + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("#-CB::SPD_TEST::testCasino::site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + if(token == null || token.equals("")) { + log.error("#-CB::SPD_TEST::testCasino::Authorization apiKey check"); + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization token check"); + return apiResponse; + } + + try { + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfo(token); + final String LOG_PREFIX = "#-CB::SPD_TEST::testCasino::"+tokenInfo.getSid()+"::"; + + int testCnt = site.getTestCnt(); + if(testCnt > 30) { + log.error(LOG_PREFIX+ "TEST_COUNT_OVER"); + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("TEST_COUNT_OVER"); + return apiResponse; + } + + // 여기서 부터 로직 + List resultList = new ArrayList<>(); + + int balance = 0; + int betAmt = 100; + int winAmt = 100; + + JSONObject requestBody = new JSONObject(); + requestBody.put("userId", memberId); + + // 유저 잔액 확인. + JSONObject responseObj = callBackTestService.getBalance(LOG_PREFIX, site.getSiteCbUrl(), requestBody); + int resultCode = responseObj.getInt("result_code"); + CallbackTestResult result = new CallbackTestResult(); + result.setIndex(0); + result.setTimeMs(responseObj.getLong("timeMs")); + responseObj.remove("timeMs"); + + if(resultCode == 0) { + result.setStatus("SUCCESS"); + result.setMsg("[balance] 성공"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + + balance = responseObj.getInt("balance"); + + resultList.add(result); + } else { + result.setStatus("FAIL"); + if(resultCode == -99) { + result.setMsg(responseObj.getString("error_msg")); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(""); + } else { + result.setMsg("[balance] 실패"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + } + + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + return apiResponse; + } + + Thread.sleep(500); + + + // 베팅 - 결과 테스트 진행 + // 1. 랜점한 betId 10개 생성. + List betIds = generateRandomStrings(20, 20); + + // 2. 베팅-결과 콜백 10번 진행. + for (int i = 0; i < 20; i += 2) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + long ctms = System.currentTimeMillis(); + String betId = "B"+site.getSiteIdx()+"_"+betIds.get(i)+"_"+memberId; + String debitTranId = "D"+site.getSiteIdx()+"_"+ctms+"_"+memberId; + String creditTranId = "C"+site.getSiteIdx()+"_"+ctms+"_"+memberId; + + // 2-1 call bet + requestBody = new JSONObject(); + requestBody.put("betId", betId); + requestBody.put("tranId", debitTranId); + requestBody.put("userId", memberId); + requestBody.put("vendorIdx", 1); + requestBody.put("vendorKey", "C01"); + requestBody.put("vendor", "svendor"); + requestBody.put("gameIdx", 1); + requestBody.put("gameKey", "코리안 스피드 바카라 A"); + requestBody.put("gameId", ""); + requestBody.put("tranType", "debit"); + requestBody.put("debit", betAmt); + requestBody.put("credit", 0); + requestBody.put("isCancel", 0); + requestBody.put("isBonus", 0); + requestBody.put("requestAt", sdf.format(System.currentTimeMillis())); + responseObj = callBackTestService.changeBalance(LOG_PREFIX, site.getSiteCbUrl(), requestBody); + resultCode = responseObj.getInt("result_code"); + result = new CallbackTestResult(); + result.setIndex(i+1); + result.setTimeMs(responseObj.getLong("timeMs")); + responseObj.remove("timeMs"); + + if(resultCode == 0) { + int balanceAfter = balance - betAmt; + int balanceResult = responseObj.getInt("balance"); + if(balanceAfter == balanceResult) { + result.setStatus("SUCCESS"); + result.setMsg("[bet] 성공"); + result.setCallbackUrl(site.getSiteCbUrl()+"/changebalance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + balance = balanceAfter; + } else { + result.setStatus("FAIL"); + result.setMsg("[bet] 실패: 잔액이 맞지 않습니다."); + result.setCallbackUrl(site.getSiteCbUrl()+"/changebalance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + return apiResponse; + } + } else { + result.setStatus("FAIL"); + if(resultCode == -99) { + result.setMsg(responseObj.getString("error_msg")); + result.setCallbackUrl(site.getSiteCbUrl()+"/changebalance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(""); + } else { + result.setMsg("[bet] 실패"); + result.setCallbackUrl(site.getSiteCbUrl()+"/changebalance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + } + + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + return apiResponse; + } + + Thread.sleep(500); + + // 2-2 call win + requestBody = new JSONObject(); + requestBody.put("betId", betId); + requestBody.put("tranId", creditTranId); + requestBody.put("userId", memberId); + requestBody.put("vendorIdx", 1); + requestBody.put("vendorKey", "C01"); + requestBody.put("vendor", "svendor"); + requestBody.put("gameIdx", 1); + requestBody.put("gameKey", "코리안 스피드 바카라 A"); + requestBody.put("gameId", ""); + requestBody.put("tranType", "credit"); + requestBody.put("debit", 0); + requestBody.put("credit", winAmt); + requestBody.put("isCancel", 0); + requestBody.put("isBonus", 0); + requestBody.put("requestAt", sdf.format(System.currentTimeMillis())); + responseObj = callBackTestService.changeBalance(LOG_PREFIX, site.getSiteCbUrl(), requestBody); + resultCode = responseObj.getInt("result_code"); + result = new CallbackTestResult(); + result.setIndex(i+2); + result.setTimeMs(responseObj.getLong("timeMs")); + responseObj.remove("timeMs"); + + if(resultCode == 0) { + int balanceAfter = balance + winAmt; + int balanceResult = responseObj.getInt("balance"); + if(balanceAfter == balanceResult) { + result.setStatus("SUCCESS"); + result.setMsg("[win] 성공"); + result.setCallbackUrl(site.getSiteCbUrl()+"/changebalance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + balance = balanceAfter; + } else { + result.setStatus("FAIL"); + result.setMsg("[win] 실패: 잔액이 맞지 않습니다."); + result.setCallbackUrl(site.getSiteCbUrl()+"/changebalance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + return apiResponse; + } + } else { + result.setStatus("FAIL"); + if(resultCode == -99) { + result.setMsg(responseObj.getString("error_msg")); + result.setCallbackUrl(site.getSiteCbUrl()+"/changebalance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(""); + } else { + result.setMsg("[win] 실패"); + result.setCallbackUrl(site.getSiteCbUrl()+"/changebalance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + } + + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + return apiResponse; + } + + Thread.sleep(500); + } + + responseData.put("resultList", resultList); + + site.setTestCnt(testCnt+1); + int updResult = siteService.updateTestCnt(site); + + apiResponse.setData(responseData); + apiResponse.success(); + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } + + + @GetMapping("/testSlot") + public ApiResponse testSlot(HttpServletRequest request, @RequestHeader String token, @Valid @RequestParam String memberId) throws Exception { + ApiResponse apiResponse = new ApiResponse(); + + Site site = siteService.getSiteInfo(request); + if(site == null) { + log.error("#-CB::SPD_TEST::testSlot::Authorization apiKey check"); + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization apiKey check"); + return apiResponse; + } + + if( !( site.getSiteIp()==null || "".equals(site.getSiteIp()) + || "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) { + log.error("#-CB::SPD_TEST::testSlot::site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request)); + apiResponse.setResultCode("10001"); + return apiResponse; + } + + if(token == null || token.equals("")) { + log.error("#-CB::SPD_TEST::testSlot::Authorization apiKey check"); + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("Authorization token check"); + return apiResponse; + } + + try { + // TO DO 토큰체크 + Map responseData = new HashMap(); + + try { + JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfo(token); + final String LOG_PREFIX = "#-CB::SPD_TEST::testSlot::"+tokenInfo.getSid()+"::"; + + int testCnt = site.getTestCnt(); + if(testCnt > 30) { + log.error(LOG_PREFIX+ "TEST_COUNT_OVER"); + apiResponse.setResultCode("9999"); + apiResponse.setResultMessage("TEST_COUNT_OVER"); + return apiResponse; + } + + // 여기서 부터 로직 + List resultList = new ArrayList<>(); + + int balance = 0; + int betAmt = 100; + int winAmt = 100; + + JSONObject requestBody = new JSONObject(); + requestBody.put("userId", memberId); + + // 유저 잔액 확인. + JSONObject responseObj = callBackTestService.getBalance(LOG_PREFIX, site.getSiteCbUrl(), requestBody); + int resultCode = responseObj.getInt("result_code"); + CallbackTestResult result = new CallbackTestResult(); + result.setIndex(0); + result.setTimeMs(responseObj.getLong("timeMs")); + responseObj.remove("timeMs"); + + if(resultCode == 0) { + result.setStatus("SUCCESS"); + result.setMsg("[balance] 성공"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + + balance = responseObj.getInt("balance"); + + resultList.add(result); + } else { + result.setStatus("FAIL"); + if(resultCode == -99) { + result.setMsg(responseObj.getString("error_msg")); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(""); + } else { + result.setMsg("[balance] 실패"); + result.setCallbackUrl(site.getSiteCbUrl()+"/balance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + } + + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + return apiResponse; + } + + Thread.sleep(500); + + + // 베팅 - 결과 테스트 진행 + // 1. 랜점한 betId 10개 생성. + List betIds = generateRandomStrings(20, 20); + + // 2. 베팅-결과 콜백 10번 진행. + for (int i = 0; i < 20; i += 2) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + long ctms = System.currentTimeMillis(); + String betId = "B"+site.getSiteIdx()+"_"+betIds.get(i)+"_"+memberId; + String debitTranId = "D"+site.getSiteIdx()+"_"+ctms+"_"+memberId; + String creditTranId = "C"+site.getSiteIdx()+"_"+ctms+"_"+memberId; + + // 2-1 call bet + requestBody = new JSONObject(); + requestBody.put("betId", betId); + requestBody.put("tranId", debitTranId); + requestBody.put("userId", memberId); + requestBody.put("vendorIdx", 17); + requestBody.put("vendorKey", "S02"); + requestBody.put("vendor", "svendor"); + requestBody.put("gameIdx", 17); + requestBody.put("gameKey", "와일드 웨스트 골드"); + requestBody.put("gameId", ""); + requestBody.put("tranType", "debit"); + requestBody.put("debit", betAmt); + requestBody.put("credit", 0); + requestBody.put("isCancel", 0); + requestBody.put("isBonus", 0); + requestBody.put("requestAt", sdf.format(System.currentTimeMillis())); + responseObj = callBackTestService.changeBalance(LOG_PREFIX, site.getSiteCbUrl(), requestBody); + resultCode = responseObj.getInt("result_code"); + result = new CallbackTestResult(); + result.setIndex(i+1); + result.setTimeMs(responseObj.getLong("timeMs")); + responseObj.remove("timeMs"); + + if(resultCode == 0) { + int balanceAfter = balance - betAmt; + int balanceResult = responseObj.getInt("balance"); + if(balanceAfter == balanceResult) { + result.setStatus("SUCCESS"); + result.setMsg("[bet] 성공"); + result.setCallbackUrl(site.getSiteCbUrl()+"/changebalance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + balance = balanceAfter; + } else { + result.setStatus("FAIL"); + result.setMsg("[bet] 실패: 잔액이 맞지 않습니다."); + result.setCallbackUrl(site.getSiteCbUrl()+"/changebalance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + return apiResponse; + } + } else { + result.setStatus("FAIL"); + if(resultCode == -99) { + result.setMsg(responseObj.getString("error_msg")); + result.setCallbackUrl(site.getSiteCbUrl()+"/changebalance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(""); + } else { + result.setMsg("[bet] 실패"); + result.setCallbackUrl(site.getSiteCbUrl()+"/changebalance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + } + + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + return apiResponse; + } + + Thread.sleep(100); + + // 2-2 call win + requestBody = new JSONObject(); + requestBody.put("betId", betId); + requestBody.put("tranId", creditTranId); + requestBody.put("userId", memberId); + requestBody.put("vendorIdx", 17); + requestBody.put("vendorKey", "S02"); + requestBody.put("vendor", "svendor"); + requestBody.put("gameIdx", 17); + requestBody.put("gameKey", "와일드 웨스트 골드"); + requestBody.put("gameId", ""); + requestBody.put("tranType", "credit"); + requestBody.put("debit", 0); + requestBody.put("credit", winAmt); + requestBody.put("isCancel", 0); + requestBody.put("isBonus", 0); + requestBody.put("requestAt", sdf.format(System.currentTimeMillis())); + responseObj = callBackTestService.changeBalance(LOG_PREFIX, site.getSiteCbUrl(), requestBody); + resultCode = responseObj.getInt("result_code"); + result = new CallbackTestResult(); + result.setIndex(i+2); + result.setTimeMs(responseObj.getLong("timeMs")); + responseObj.remove("timeMs"); + + if(resultCode == 0) { + int balanceAfter = balance + winAmt; + int balanceResult = responseObj.getInt("balance"); + if(balanceAfter == balanceResult) { + result.setStatus("SUCCESS"); + result.setMsg("[win] 성공"); + result.setCallbackUrl(site.getSiteCbUrl()+"/changebalance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + balance = balanceAfter; + } else { + result.setStatus("FAIL"); + result.setMsg("[win] 실패: 잔액이 맞지 않습니다."); + result.setCallbackUrl(site.getSiteCbUrl()+"/changebalance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + return apiResponse; + } + } else { + result.setStatus("FAIL"); + if(resultCode == -99) { + result.setMsg(responseObj.getString("error_msg")); + result.setCallbackUrl(site.getSiteCbUrl()+"/changebalance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(""); + } else { + result.setMsg("[win] 실패"); + result.setCallbackUrl(site.getSiteCbUrl()+"/changebalance"); + result.setRequestBody(requestBody.toString()); + result.setResponseData(responseObj.toString()); + } + + resultList.add(result); + + responseData.put("resultList", resultList); + apiResponse.setData(responseData); + apiResponse.success(); + return apiResponse; + } + + Thread.sleep(100); + } + + responseData.put("resultList", resultList); + + site.setTestCnt(testCnt+1); + int updResult = siteService.updateTestCnt(site); + + apiResponse.setData(responseData); + apiResponse.success(); + + } catch(Exception e) { + log.info(e.toString()); + apiResponse.setResultCode("99995"); + apiResponse.setResultMessage("token is no valid"); + return apiResponse; + } + + } catch (Exception e) { + e.printStackTrace(); + apiResponse.fail(); + } + + return apiResponse; + } +} diff --git a/src/main/java/com/bb/jwt/JwtClame.java b/src/main/java/com/bb/jwt/JwtClame.java new file mode 100644 index 0000000..408561d --- /dev/null +++ b/src/main/java/com/bb/jwt/JwtClame.java @@ -0,0 +1,11 @@ +package com.bb.jwt; + +import lombok.Data; + +@Data +public class JwtClame { + private String siteId; + private String memId; + private String type; + +} diff --git a/src/main/java/com/bb/jwt/JwtConfig.java b/src/main/java/com/bb/jwt/JwtConfig.java new file mode 100644 index 0000000..417449c --- /dev/null +++ b/src/main/java/com/bb/jwt/JwtConfig.java @@ -0,0 +1,25 @@ +package com.bb.jwt; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.bb.jwt.JwtManager; + + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class JwtConfig { + @Value("${jwt.secret}") + private String jwtSecret; + + @Value("${jwt.validity-in-seconds}") + private long tokenValidityInSeconds; + + @Bean + public JwtManager jwtManager() { + return new JwtManager(jwtSecret, tokenValidityInSeconds); + } +} \ No newline at end of file diff --git a/src/main/java/com/bb/jwt/JwtManager.java b/src/main/java/com/bb/jwt/JwtManager.java new file mode 100644 index 0000000..2c156f4 --- /dev/null +++ b/src/main/java/com/bb/jwt/JwtManager.java @@ -0,0 +1,180 @@ +package com.bb.jwt; + + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.security.Keys; +import lombok.Getter; + +import java.nio.charset.StandardCharsets; +import java.security.Key; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Set; + +import com.bb.jwt.JwtManager.TokenInfo; + +public class JwtManager { + private String secretKey; + private long TOKEN_VALIDATiON_SECOND; + private long ADMIN_VALIDATiON_SECOND = 60; + private long ADMIN_VALIDATiON_SECOND_REFRESH = 6000; + + public JwtManager(String secretKey, long TOKEN_VALIDATiON_SECOND) { + this.secretKey = secretKey; + this.TOKEN_VALIDATiON_SECOND = TOKEN_VALIDATiON_SECOND; + } + + // secretKey 로드 + private Key getSigninKey() { + byte[] keyBytes = secretKey.getBytes(StandardCharsets.UTF_8); + return Keys.hmacShaKeyFor(keyBytes); + } + + // 토큰 생성 + public String generateToken(JwtClame jwtinfo) { + Claims claims = Jwts.claims(); + claims.put("mid", jwtinfo.getMemId()); + claims.put("sid", jwtinfo.getSiteId()); + claims.put("type", jwtinfo.getType()); + + return Jwts.builder() + .setClaims(claims) + .setIssuedAt(new Date()) + .setExpiration(new Date(System.currentTimeMillis() + (TOKEN_VALIDATiON_SECOND * 1000))) + .signWith(getSigninKey(), SignatureAlgorithm.HS256) + .compact(); + } + + // 토큰 생성 5일 + public String generateToken2(JwtClame jwtinfo) { + Claims claims = Jwts.claims(); + claims.put("mid", jwtinfo.getMemId()); + claims.put("sid", jwtinfo.getSiteId()); + claims.put("type", jwtinfo.getType()); + + long fiveDays = 5L * 24 * 60 * 60 * 1000; // 5일 밀리초 + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + long currentTMS = System.currentTimeMillis(); + Date issuedAt = new Date(currentTMS); + String issuedAtStr = sdf.format(issuedAt); + Date expiration = new Date(currentTMS + fiveDays); + String expirationStr = sdf.format(expiration); + + System.out.println("[JwtManager.generateToken(jwtinfo)] sid: " + jwtinfo.getSiteId()); + System.out.println("[JwtManager.generateToken(jwtinfo)] mid: " + jwtinfo.getMemId()); + System.out.println("[JwtManager.generateToken(jwtinfo)] IAT: " + issuedAtStr); + System.out.println("[JwtManager.generateToken(jwtinfo)] EAT: " + expirationStr); + System.out.println("#-JwtManager::generateToken::admin::"+jwtinfo.getSiteId()+"::"+jwtinfo.getMemId()+"::IAT::"+issuedAtStr+"::EAT::"+expirationStr); + + return Jwts.builder() + .setClaims(claims) + .setIssuedAt(issuedAt) + .setExpiration(expiration) + .signWith(getSigninKey(), SignatureAlgorithm.HS256) + .compact(); + } + + + // 토큰 생성 + public String generateTokenAdmin(JwtClame jwtinfo) { + Claims claims = Jwts.claims(); + claims.put("sid", jwtinfo.getSiteId()); + claims.put("type", "A"); + return Jwts.builder() + .setClaims(claims) + .setIssuedAt(new Date()) + .setExpiration(new Date(System.currentTimeMillis() + (TOKEN_VALIDATiON_SECOND * 6000))) + .signWith(getSigninKey(), SignatureAlgorithm.HS256) + .compact(); + } + + // 토큰 생성 + public String generateTokenRefresh(JwtClame jwtinfo) { + Claims claims = Jwts.claims(); + claims.put("sid", jwtinfo.getSiteId()); + claims.put("type", "R"); + + return Jwts.builder() + .setClaims(claims) + .setIssuedAt(new Date()) + .setExpiration(new Date(System.currentTimeMillis() + (TOKEN_VALIDATiON_SECOND * 240000))) + .signWith(getSigninKey(), SignatureAlgorithm.HS256) + .compact(); + } + + // 토큰 정보 리턴 + public TokenInfo getTokenInfo(String token) { + Claims body = getClaims(token); + Set keySet = body.keySet(); + for (String s : keySet) { + // System.out.println("s = " + s); + } + + String mid = body.get("mid", String.class); + String sid = body.get("sid", String.class); + String type = body.get("type", String.class); + Date issuedAt = body.getIssuedAt(); + Date expiration = body.getExpiration(); + return new TokenInfo(sid, mid, type, issuedAt, expiration); + } + + // 토큰 정보 리턴 + public TokenInfo getTokenInfoAdmin(String token) { + + + Claims body = getClaims(token); + String type = body.get("type", String.class); + if("A".equals(type)) { + + Set keySet = body.keySet(); + for (String s : keySet) { + // System.out.println("s = " + s); + } + + String sid = body.get("sid", String.class); + + Date issuedAt = body.getIssuedAt(); + Date expiration = body.getExpiration(); + return new TokenInfo(sid, null, type, issuedAt, expiration); + }else { + return null; + } + } + + // 토큰정보 해석 + private Claims getClaims(String token) { + Claims body = Jwts.parserBuilder() + .setSigningKey(getSigninKey()) + .build() + .parseClaimsJws(token) + .getBody(); + return body; + } + + + @Getter + public class TokenInfo { + private String mid; + private String sid; + private String type; + private Date issuedAt; + private Date expire; + + public TokenInfo(String sid, String mid, String type, Date issuedAt, Date expire) { + this.sid = sid; + this.mid = mid; + this.type = type; + this.issuedAt = issuedAt; + this.expire = expire; + } + + @Override + public String toString() { + return "TokenInfo [mid=" + mid + ", sid=" + sid + ", type=" + type + ", issuedAt=" + issuedAt + ", expire=" + expire + "]"; + } + + } +} diff --git a/src/main/java/com/bb/model/ApiResponse.java b/src/main/java/com/bb/model/ApiResponse.java new file mode 100644 index 0000000..78c6d43 --- /dev/null +++ b/src/main/java/com/bb/model/ApiResponse.java @@ -0,0 +1,104 @@ +package com.bb.model; + +import com.bb.exception.ApiException; +import com.bb.exception.RequestParameterApiException; +import com.bb.util.StringUtils; +import com.fasterxml.jackson.annotation.JsonInclude; + + +import lombok.Data; +import lombok.Getter; +import lombok.Setter; + +import java.util.HashMap; +import java.util.Map; + + +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ApiResponse { + /** 결과 코드 */ + private String resultCode; + /** 결과 메시지 */ + private String resultMessage; + /** 데이터 */ + private Map data; + + /** + * 데이터 추가 + * @param key + * @param value + */ + public void put(String key, Object value) { + if(this.data == null) { + this.data = new HashMap<>(); + } + + this.data.put(key, value); + } + + /** + * 성공상태 설정 + */ + public void success() { + this.setResultCode("0"); + this.setResultMessage("SUCC"); + } + + /** + * 실패상태 설정 + */ + public void fail() { + this.setResultCode("9999"); + this.setResultMessage("FAIL"); + } + + /** + * 필수 파라미터 검증 + * @param value + * @param paramName + * @throws ApiException + */ + public static void require(Object value, String paramName) throws ApiException { + String stringValue = (value == null) ? null : String.valueOf(value); + + if(StringUtils.isEmpty(stringValue)) { + throw new RequestParameterApiException( paramName); + } + } + + /** + * 파라미터 조건 검증 + * @param condition + * @param message + * @throws ApiException + */ + public static void then( boolean condition, String message ) throws ApiException { + if( condition ) { + throw new ApiException( message ); + } + } + + /** + * 파라미터가 특정 목록에 포함되어 있는지 검증 + * @param param + * @param paramName + * @param values + * @throws ApiException + */ + public static void notMatched( Object param, String paramName, Object... values ) throws ApiException { + boolean matched = false; + + for( Object value : values ) { + if( param.equals( value ) ) { + matched = true; + break; + } + } + + if( !matched ) { + throw new ApiException( "유효하지 않은 파라미터 : " + paramName ); + } + } + +} diff --git a/src/main/java/com/bb/model/ApiTestVO.java b/src/main/java/com/bb/model/ApiTestVO.java new file mode 100644 index 0000000..5d3e8e0 --- /dev/null +++ b/src/main/java/com/bb/model/ApiTestVO.java @@ -0,0 +1,25 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class ApiTestVO { + + + private String apiUrl; + private String apiKey; + + private String token; + private String vendorKey; + private String gameKey; + private String isMobile; + private String language; + private String userId; + private String nickName; + private String userIp; + private long balance; + + private String startDate; + private String endDate; + private String betId; +} diff --git a/src/main/java/com/bb/model/AuthParam.java b/src/main/java/com/bb/model/AuthParam.java new file mode 100644 index 0000000..851f862 --- /dev/null +++ b/src/main/java/com/bb/model/AuthParam.java @@ -0,0 +1,23 @@ +package com.bb.model; + +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.Size; + +import lombok.Data; + +@Data +public class AuthParam { + + @NotEmpty + @Size(max = 40) // 최대 길이 64 + private String userId; + + @NotEmpty + @Size(max = 40) // 최대 길이 64 + private String nickName; + + private String userIp; + + private long balance; + +} diff --git a/src/main/java/com/bb/model/BalanceParam.java b/src/main/java/com/bb/model/BalanceParam.java new file mode 100644 index 0000000..c91a7f2 --- /dev/null +++ b/src/main/java/com/bb/model/BalanceParam.java @@ -0,0 +1,14 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class BalanceParam { + private Long siteIdx; + private String username; + private String userId; + private String vendor; + private String vendorKey; + private String amount; + private String requestKey; +} diff --git a/src/main/java/com/bb/model/BanGameSearch.java b/src/main/java/com/bb/model/BanGameSearch.java new file mode 100644 index 0000000..b48bcb1 --- /dev/null +++ b/src/main/java/com/bb/model/BanGameSearch.java @@ -0,0 +1,13 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class BanGameSearch { + + private String vendorTitle; + + private Long vendorIdx; + + private String skin; +} diff --git a/src/main/java/com/bb/model/Bet.java b/src/main/java/com/bb/model/Bet.java new file mode 100644 index 0000000..cd77145 --- /dev/null +++ b/src/main/java/com/bb/model/Bet.java @@ -0,0 +1,24 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class Bet { + + private String tranid; + private String refId; + private String siteIdx; + private String memberIdx; + private String vendeorIdx; + private String vendorTranKey; + private String gameIdx; + private String betAmt; + private String betWinAmt; + private String betRate; + private String isCancel; + private String isTie; + private String regDate; + private String apiStatus; + private String updDate; + +} diff --git a/src/main/java/com/bb/model/BetParam.java b/src/main/java/com/bb/model/BetParam.java new file mode 100644 index 0000000..4b82959 --- /dev/null +++ b/src/main/java/com/bb/model/BetParam.java @@ -0,0 +1,21 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class BetParam { + + private int siteIdx; + private String apiKey; + private String betId; + private String memberId; + private Long vendorIdx; + private String vendorKey; + private String vendorCetegory; + private String startDate; + private String endDate; + private String isDetail; + private String page; + private String count; + +} diff --git a/src/main/java/com/bb/model/BetRadarResponse.java b/src/main/java/com/bb/model/BetRadarResponse.java new file mode 100644 index 0000000..a6620fc --- /dev/null +++ b/src/main/java/com/bb/model/BetRadarResponse.java @@ -0,0 +1,12 @@ +package com.bb.model; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import lombok.Data; + +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class BetRadarResponse { + private Integer error; + private Integer balance; +} diff --git a/src/main/java/com/bb/model/BlockGameVO.java b/src/main/java/com/bb/model/BlockGameVO.java new file mode 100644 index 0000000..162de58 --- /dev/null +++ b/src/main/java/com/bb/model/BlockGameVO.java @@ -0,0 +1,23 @@ +package com.bb.model; + +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; + +import lombok.Data; + +@Data +public class BlockGameVO { + + @NotNull + private Long siteIdx; + + @NotNull + private Long vendorIdx; + + private String vendorTitle; + + @NotEmpty + private String blockTableId; + + private String blockTableIds; +} diff --git a/src/main/java/com/bb/model/BoardSearch.java b/src/main/java/com/bb/model/BoardSearch.java new file mode 100644 index 0000000..d2890d9 --- /dev/null +++ b/src/main/java/com/bb/model/BoardSearch.java @@ -0,0 +1,15 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class BoardSearch extends PageFormVO { + + private long siteIdx; + private String siteId; + private String viewType; + private String boardType; + private String startDate; + private String endDate; + private String searchWord; +} diff --git a/src/main/java/com/bb/model/BombAuthVO.java b/src/main/java/com/bb/model/BombAuthVO.java new file mode 100644 index 0000000..074a91a --- /dev/null +++ b/src/main/java/com/bb/model/BombAuthVO.java @@ -0,0 +1,23 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class BombAuthVO { + + String loginToken; + String apiToken; + String accID; + String userID; + String regDate; + String transferId; + String bomb; + String bombs; + String play; + Integer roomNo; + double amount; + String ep; + String endDate; + + +} diff --git a/src/main/java/com/bb/model/BombReponseVo.java b/src/main/java/com/bb/model/BombReponseVo.java new file mode 100644 index 0000000..7c76d2b --- /dev/null +++ b/src/main/java/com/bb/model/BombReponseVo.java @@ -0,0 +1,96 @@ +package com.bb.model; + +import com.bb.exception.ApiException; +import com.bb.exception.RequestParameterApiException; +import com.bb.util.StringUtils; +import com.fasterxml.jackson.annotation.JsonInclude; + + +import lombok.Data; +import lombok.Getter; +import lombok.Setter; + +import java.util.HashMap; +import java.util.Map; + + +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class BombReponseVo { + /** 결과 코드 */ + private int code; + private String accId; + private String nickName; + private String balance; + boolean isDemo; + + + public void success() { + this.setCode(0); + + } + + + /** + * 실패상태 설정 + */ + public void fail() { + this.setCode(-1); + } + + /** + * 실패상태 설정 + */ + public void fail(int code) { + this.setCode(code); + } + + /** + * 필수 파라미터 검증 + * @param value + * @param paramName + * @throws ApiException + */ + public static void require(Object value, String paramName) throws ApiException { + String stringValue = (value == null) ? null : String.valueOf(value); + + if(StringUtils.isEmpty(stringValue)) { + throw new RequestParameterApiException( paramName); + } + } + + /** + * 파라미터 조건 검증 + * @param condition + * @param message + * @throws ApiException + */ + public static void then( boolean condition, String message ) throws ApiException { + if( condition ) { + throw new ApiException( message ); + } + } + + /** + * 파라미터가 특정 목록에 포함되어 있는지 검증 + * @param param + * @param paramName + * @param values + * @throws ApiException + */ + public static void notMatched( Object param, String paramName, Object... values ) throws ApiException { + boolean matched = false; + + for( Object value : values ) { + if( param.equals( value ) ) { + matched = true; + break; + } + } + + if( !matched ) { + throw new ApiException( "유효하지 않은 파라미터 : " + paramName ); + } + } + +} diff --git a/src/main/java/com/bb/model/CallbackTestResult.java b/src/main/java/com/bb/model/CallbackTestResult.java new file mode 100644 index 0000000..49b596a --- /dev/null +++ b/src/main/java/com/bb/model/CallbackTestResult.java @@ -0,0 +1,18 @@ +package com.bb.model; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import lombok.Data; + +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class CallbackTestResult { + + private int index; + private String status; + private String msg; + private String callbackUrl; + private String requestBody; + private String responseData; + private long timeMs; +} diff --git a/src/main/java/com/bb/model/CashParam.java b/src/main/java/com/bb/model/CashParam.java new file mode 100644 index 0000000..4f140d4 --- /dev/null +++ b/src/main/java/com/bb/model/CashParam.java @@ -0,0 +1,28 @@ +package com.bb.model; + +import jakarta.validation.constraints.NotBlank; + +import lombok.Data; + +@Data +public class CashParam { + + private long siteIdx; + + @NotBlank + private String memberId; + + @NotBlank + private String amount; + + private String withAll; + + @NotBlank + private String creditType; + + private String startDate; + + private String endDate; + + private String count; +} diff --git a/src/main/java/com/bb/model/Channel.java b/src/main/java/com/bb/model/Channel.java new file mode 100644 index 0000000..8360536 --- /dev/null +++ b/src/main/java/com/bb/model/Channel.java @@ -0,0 +1,8 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class Channel { + private String type; +} diff --git a/src/main/java/com/bb/model/CheckVo.java b/src/main/java/com/bb/model/CheckVo.java new file mode 100644 index 0000000..0aaeddb --- /dev/null +++ b/src/main/java/com/bb/model/CheckVo.java @@ -0,0 +1,15 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class CheckVo { + + + private String userId; + private String sid; + private Channel channel; + private String uuid; + + +} diff --git a/src/main/java/com/bb/model/CmnSearch.java b/src/main/java/com/bb/model/CmnSearch.java new file mode 100644 index 0000000..72fa927 --- /dev/null +++ b/src/main/java/com/bb/model/CmnSearch.java @@ -0,0 +1,19 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class CmnSearch { + + private Long siteIdx; + + private String siteId; + + private String category; + + private Long vendorIdx; + + private String vendorTitle; + + private String keyword; +} diff --git a/src/main/java/com/bb/model/CncpResponse.java b/src/main/java/com/bb/model/CncpResponse.java new file mode 100644 index 0000000..7601c80 --- /dev/null +++ b/src/main/java/com/bb/model/CncpResponse.java @@ -0,0 +1,13 @@ +package com.bb.model; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import lombok.Data; + +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class CncpResponse { + + private String status; + private CncpResult result; +} diff --git a/src/main/java/com/bb/model/CncpResult.java b/src/main/java/com/bb/model/CncpResult.java new file mode 100644 index 0000000..e01052b --- /dev/null +++ b/src/main/java/com/bb/model/CncpResult.java @@ -0,0 +1,12 @@ +package com.bb.model; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import lombok.Data; + +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class CncpResult { + + private Double balance; +} diff --git a/src/main/java/com/bb/model/CoinVo.java b/src/main/java/com/bb/model/CoinVo.java new file mode 100644 index 0000000..93117c6 --- /dev/null +++ b/src/main/java/com/bb/model/CoinVo.java @@ -0,0 +1,39 @@ +package com.bb.model; + +import java.time.LocalDateTime; + +import lombok.Data; + +@Data +public class CoinVo { + +private String id; +private String symbol; +private String name; +private String currency; +private String image; +private String currentPrice; +private String marketCap; +private Integer marketCapRank; +private String fullyDilutedValuation; +private String totalVolume; +private String high24h; +private String low24h; +private String priceChange24h; +private String priceChangePercentage24h; +private String marketCapChange24h; +private String marketCapChangePercentage24h; +private String circulatingSupply; +private String totalSupply; +private String maxSupply; +private String ath; +private String athChangePercentage; +private LocalDateTime athDate; +private String atl; +private String atlChangePercentage; +private LocalDateTime atlDate; +private String roi; // JSON as String +private LocalDateTime lastUpdated; + + +} \ No newline at end of file diff --git a/src/main/java/com/bb/model/CommonParam.java b/src/main/java/com/bb/model/CommonParam.java new file mode 100644 index 0000000..3c541fe --- /dev/null +++ b/src/main/java/com/bb/model/CommonParam.java @@ -0,0 +1,12 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class CommonParam { + private int siteIdx; + private AuthParam authParam; + private PlayParam playParam; + + +} diff --git a/src/main/java/com/bb/model/CommonParamAdmin.java b/src/main/java/com/bb/model/CommonParamAdmin.java new file mode 100644 index 0000000..1635830 --- /dev/null +++ b/src/main/java/com/bb/model/CommonParamAdmin.java @@ -0,0 +1,11 @@ +package com.bb.model; + +import lombok.Data; +import net.sf.json.JSONArray; +import net.sf.json.JSONObject; + +@Data +public class CommonParamAdmin { + private JSONObject param; + private JSONObject[] paramlist; +} diff --git a/src/main/java/com/bb/model/Credit.java b/src/main/java/com/bb/model/Credit.java new file mode 100644 index 0000000..6b504d5 --- /dev/null +++ b/src/main/java/com/bb/model/Credit.java @@ -0,0 +1,52 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class Credit { + + private long creditIdx; + private long siteIdx; + private String siteId; + private long targetSiteIdx; + private String targetSiteId; + private String creditType; + /** + * creditType + * - 'AI' : 크레딧 지급 + * - 'AO' : 크레딧 회수 + * - 'CO' : ?? + * - 'DP' : 베팅 + * - 'CD' : 결과 + * - 'SDP' : ?? + * - 'SCD' : ?? + * - 'CI' : ?? + * - 'MAI' : 회원 충전 + * - 'MAO' : 회원 환전 + * - 'MCD' : 트랜스퍼 베팅 + * - 'MDP' : 트랜스퍼 결과 + */ + private String creditRate; + private Integer gameCategory; + private String inOut; + private String tranId; + private long creditAmt; + private long userAmt; + private long preCreditAmt; + private long preBalance; + private int creditStatus; + private String regDate; + private String updDate; + private long pointAmt; + private String refId; + private String otp; + + private int waitTime; // 재요청 대기시간 + + private int siteLevel; + private long casinoCreditA; + private long casinoCreditB; + private long slotCreditA; + private long slotCreditB; + +} \ No newline at end of file diff --git a/src/main/java/com/bb/model/CreditPoint.java b/src/main/java/com/bb/model/CreditPoint.java new file mode 100644 index 0000000..d2dbf69 --- /dev/null +++ b/src/main/java/com/bb/model/CreditPoint.java @@ -0,0 +1,28 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class CreditPoint { + + private Long pointIdx; + private Long siteIdx; + private String siteId; + private Long memberIdx; + private String memberId; + private Long targetSiteIdx; + private String targetSiteId; + private String vendor; + private Integer vendorIdx; + private String tranId; + private String betId; + private Integer amount; + private Double baseRate; + private Double vendorRate; + private Double pointRate; + private Long prePointAmt; + private Integer pointAmt; + private String regDate; + private String updDate; + private String otp; +} diff --git a/src/main/java/com/bb/model/CreditPointSearch.java b/src/main/java/com/bb/model/CreditPointSearch.java new file mode 100644 index 0000000..b806918 --- /dev/null +++ b/src/main/java/com/bb/model/CreditPointSearch.java @@ -0,0 +1,29 @@ +package com.bb.model; + +import jakarta.validation.constraints.NotBlank; + +import lombok.Data; + +@Data +public class CreditPointSearch extends PageFormVO { + + @NotBlank + private String startDate; + + @NotBlank + private String endDate; + + private Long searchSiteIdx; + private String searchSiteId; + private String searchBottomId; + private String searchMemberId; + private String searchBetId; + private Integer searchVendorIdx; + private String startDatePartition; + private String endDatePartition; + + @NotBlank + private String oldYN; + + private String orderStr; +} diff --git a/src/main/java/com/bb/model/CreditSearchVO.java b/src/main/java/com/bb/model/CreditSearchVO.java new file mode 100644 index 0000000..f0e553a --- /dev/null +++ b/src/main/java/com/bb/model/CreditSearchVO.java @@ -0,0 +1,42 @@ +package com.bb.model; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; + +import lombok.Data; + +@Data +public class CreditSearchVO extends PageFormVO { + + private Long siteIdx; + + private String siteId; + + @NotBlank + private String startDate; + + @NotBlank + private String endDate; + + private Long upperSiteIdx; + private String upperSiteId; + private Long targetSiteIdx; + private String targetSiteId; + + private String searchSiteId; + + @NotNull + private String transType; // UP-AI, UP-AO, UP, DW-AI, DW-AO, DW, AD-AI, AD-AO, AD, MAI, MAO, MAIO, CD, DP, CDP + + @NotBlank + private String oldYN; + + private String orderStr; + + private String category; + + private Long vendorIdx; + + private String startDatePartition; + private String endDatePartition; +} diff --git a/src/main/java/com/bb/model/CronStatusVo.java b/src/main/java/com/bb/model/CronStatusVo.java new file mode 100644 index 0000000..e730d97 --- /dev/null +++ b/src/main/java/com/bb/model/CronStatusVo.java @@ -0,0 +1,14 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class CronStatusVo { + + private String serviceName; + private String hostName; + private String ipAddress; + private String runYn; + private String regDate; + private String updDate; +} diff --git a/src/main/java/com/bb/model/DgMember.java b/src/main/java/com/bb/model/DgMember.java new file mode 100644 index 0000000..10728c3 --- /dev/null +++ b/src/main/java/com/bb/model/DgMember.java @@ -0,0 +1,16 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class DgMember { + + private String username; + private String password; + private Double balance; + private Integer status; + private String currency; + private Double winLimit; + private Double amount; + +} diff --git a/src/main/java/com/bb/model/DgOrder.java b/src/main/java/com/bb/model/DgOrder.java new file mode 100644 index 0000000..c0af63e --- /dev/null +++ b/src/main/java/com/bb/model/DgOrder.java @@ -0,0 +1,11 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class DgOrder { + private String username; + private Long ticketId; + private String serial; + private Double amount; +} diff --git a/src/main/java/com/bb/model/DgParamVo.java b/src/main/java/com/bb/model/DgParamVo.java new file mode 100644 index 0000000..5217635 --- /dev/null +++ b/src/main/java/com/bb/model/DgParamVo.java @@ -0,0 +1,12 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class DgParamVo { + private String token; + private DgMember member; + private String ticketId; + private Object data; + private DgOrder list; +} diff --git a/src/main/java/com/bb/model/DgReponseVo.java b/src/main/java/com/bb/model/DgReponseVo.java new file mode 100644 index 0000000..cf7d7c5 --- /dev/null +++ b/src/main/java/com/bb/model/DgReponseVo.java @@ -0,0 +1,114 @@ +package com.bb.model; + +import com.bb.exception.ApiException; +import com.bb.exception.RequestParameterApiException; +import com.bb.util.StringUtils; +import com.fasterxml.jackson.annotation.JsonInclude; + + +import lombok.Data; +import lombok.Getter; +import lombok.Setter; + +import java.util.HashMap; +import java.util.Map; + + +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class DgReponseVo { + + /** 결과 코드 */ + private int codeId; + private String token; + private DgMember member; + private Object data; + + /** 데이터 */ + private Map datas; + + /** + * 데이터 추가 + * @param key + * @param value + */ + public void put(String key, Object value) { + if(this.datas == null) { + this.datas = new HashMap<>(); + } + + this.datas.put(key, value); + } + + /** + * 성공상태 설정 + */ + public void success() { + this.setCodeId(0); + + } + + + /** + * 실패상태 설정 + */ + public void fail() { + this.setCodeId(503); + } + + /** + * 실패상태 설정 + */ + public void fail(int code) { + this.setCodeId(code); + } + + /** + * 필수 파라미터 검증 + * @param value + * @param paramName + * @throws ApiException + */ + public static void require(Object value, String paramName) throws ApiException { + String stringValue = (value == null) ? null : String.valueOf(value); + + if(StringUtils.isEmpty(stringValue)) { + throw new RequestParameterApiException( paramName); + } + } + + /** + * 파라미터 조건 검증 + * @param condition + * @param message + * @throws ApiException + */ + public static void then( boolean condition, String message ) throws ApiException { + if( condition ) { + throw new ApiException( message ); + } + } + + /** + * 파라미터가 특정 목록에 포함되어 있는지 검증 + * @param param + * @param paramName + * @param values + * @throws ApiException + */ + public static void notMatched( Object param, String paramName, Object... values ) throws ApiException { + boolean matched = false; + + for( Object value : values ) { + if( param.equals( value ) ) { + matched = true; + break; + } + } + + if( !matched ) { + throw new ApiException( "유효하지 않은 파라미터 : " + paramName ); + } + } + +} diff --git a/src/main/java/com/bb/model/DowinReponseVo.java b/src/main/java/com/bb/model/DowinReponseVo.java new file mode 100644 index 0000000..d2cbd0f --- /dev/null +++ b/src/main/java/com/bb/model/DowinReponseVo.java @@ -0,0 +1,79 @@ +package com.bb.model; + +import com.bb.exception.ApiException; +import com.bb.exception.RequestParameterApiException; +import com.bb.util.StringUtils; +import com.fasterxml.jackson.annotation.JsonInclude; + +import groovy.transform.builder.Builder; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.HashMap; +import java.util.Map; + + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@JsonInclude(JsonInclude.Include.NON_NULL) +public class DowinReponseVo { + /** 결과 코드 */ + private String status; + private Long balance; + private String uuid; + + + /** + * 필수 파라미터 검증 + * @param value + * @param paramName + * @throws ApiException + */ + public static void require(Object value, String paramName) throws ApiException { + String stringValue = (value == null) ? null : String.valueOf(value); + + if(StringUtils.isEmpty(stringValue)) { + throw new RequestParameterApiException( paramName); + } + } + + /** + * 파라미터 조건 검증 + * @param condition + * @param message + * @throws ApiException + */ + public static void then( boolean condition, String message ) throws ApiException { + if( condition ) { + throw new ApiException( message ); + } + } + + /** + * 파라미터가 특정 목록에 포함되어 있는지 검증 + * @param param + * @param paramName + * @param values + * @throws ApiException + */ + public static void notMatched( Object param, String paramName, Object... values ) throws ApiException { + boolean matched = false; + + for( Object value : values ) { + if( param.equals( value ) ) { + matched = true; + break; + } + } + + if( !matched ) { + throw new ApiException( "유효하지 않은 파라미터 : " + paramName ); + } + } + +} diff --git a/src/main/java/com/bb/model/EvoResponse.java b/src/main/java/com/bb/model/EvoResponse.java new file mode 100644 index 0000000..077e8cd --- /dev/null +++ b/src/main/java/com/bb/model/EvoResponse.java @@ -0,0 +1,117 @@ +package com.bb.model; + +import com.bb.exception.ApiException; +import com.bb.exception.RequestParameterApiException; +import com.bb.util.StringUtils; +import com.fasterxml.jackson.annotation.JsonInclude; + + +import lombok.Data; +import lombok.Getter; +import lombok.Setter; + +import java.util.HashMap; +import java.util.Map; + + +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class EvoResponse { + /** 결과 코드 */ + private String status; + private String sid; + private Double balance; + private Double bonus; + private String uuid; + + private boolean retransmission; + + /** 데이터 */ + private Map data; + + /** + * 데이터 추가 + * @param key + * @param value + */ + public void put(String key, Object value) { + if(this.data == null) { + this.data = new HashMap<>(); + } + + this.data.put(key, value); + } + + /** + * 성공상태 설정 + */ + public void success() { + this.setStatus("OK"); + this.retransmission =false; + } + + /** + * 실패상태 설정 + */ + public void fail() { + this.setStatus("INVALID_PARAMETER"); + this.retransmission =true; + } + + /** + * 실패상태 설정 + */ + public void fail(String msg) { + this.setStatus(msg); + this.retransmission =false; + } + + /** + * 필수 파라미터 검증 + * @param value + * @param paramName + * @throws ApiException + */ + public static void require(Object value, String paramName) throws ApiException { + String stringValue = (value == null) ? null : String.valueOf(value); + + if(StringUtils.isEmpty(stringValue)) { + throw new RequestParameterApiException( paramName); + } + } + + /** + * 파라미터 조건 검증 + * @param condition + * @param message + * @throws ApiException + */ + public static void then( boolean condition, String message ) throws ApiException { + if( condition ) { + throw new ApiException( message ); + } + } + + /** + * 파라미터가 특정 목록에 포함되어 있는지 검증 + * @param param + * @param paramName + * @param values + * @throws ApiException + */ + public static void notMatched( Object param, String paramName, Object... values ) throws ApiException { + boolean matched = false; + + for( Object value : values ) { + if( param.equals( value ) ) { + matched = true; + break; + } + } + + if( !matched ) { + throw new ApiException( "유효하지 않은 파라미터 : " + paramName ); + } + } + +} diff --git a/src/main/java/com/bb/model/EvolutionAamsSessionVo.java b/src/main/java/com/bb/model/EvolutionAamsSessionVo.java new file mode 100644 index 0000000..2864598 --- /dev/null +++ b/src/main/java/com/bb/model/EvolutionAamsSessionVo.java @@ -0,0 +1,9 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class EvolutionAamsSessionVo { + private String id; + private String ticket; +} diff --git a/src/main/java/com/bb/model/EvolutionGameDetailTableVo.java b/src/main/java/com/bb/model/EvolutionGameDetailTableVo.java new file mode 100644 index 0000000..8c271c1 --- /dev/null +++ b/src/main/java/com/bb/model/EvolutionGameDetailTableVo.java @@ -0,0 +1,10 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class EvolutionGameDetailTableVo { + private String id; + private String vid; +} + diff --git a/src/main/java/com/bb/model/EvolutionGameDetailVo.java b/src/main/java/com/bb/model/EvolutionGameDetailVo.java new file mode 100644 index 0000000..6053d84 --- /dev/null +++ b/src/main/java/com/bb/model/EvolutionGameDetailVo.java @@ -0,0 +1,8 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class EvolutionGameDetailVo { + private EvolutionGameDetailTableVo table; +} diff --git a/src/main/java/com/bb/model/EvolutionGameVo.java b/src/main/java/com/bb/model/EvolutionGameVo.java new file mode 100644 index 0000000..d03bdff --- /dev/null +++ b/src/main/java/com/bb/model/EvolutionGameVo.java @@ -0,0 +1,9 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class EvolutionGameVo { + private String type; + private EvolutionGameDetailVo details; +} diff --git a/src/main/java/com/bb/model/EvolutionPromoTransactionVo.java b/src/main/java/com/bb/model/EvolutionPromoTransactionVo.java new file mode 100644 index 0000000..15a6b0b --- /dev/null +++ b/src/main/java/com/bb/model/EvolutionPromoTransactionVo.java @@ -0,0 +1,17 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class EvolutionPromoTransactionVo { + private String type; + private String id; + private double amount; + private String voucherId; + private int remainingRounds; + private Jackpot[] jackpots; + private double playableBalance; + private String bonusConfigId; + private String rewardId; + +} diff --git a/src/main/java/com/bb/model/EvolutionTransactionVo.java b/src/main/java/com/bb/model/EvolutionTransactionVo.java new file mode 100644 index 0000000..d05d8b0 --- /dev/null +++ b/src/main/java/com/bb/model/EvolutionTransactionVo.java @@ -0,0 +1,12 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class EvolutionTransactionVo { + private String id; + private String refId; + private double amount; + + +} diff --git a/src/main/java/com/bb/model/EvolutionVo.java b/src/main/java/com/bb/model/EvolutionVo.java new file mode 100644 index 0000000..55a3f69 --- /dev/null +++ b/src/main/java/com/bb/model/EvolutionVo.java @@ -0,0 +1,18 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class EvolutionVo { + private String sid; + private String userId; + private String currency; + private String uuid; + + private EvolutionAamsSessionVo aamsSession; + private EvolutionTransactionVo transaction; + private EvolutionPromoTransactionVo promoTransaction; + + private EvolutionGameVo game; + +} diff --git a/src/main/java/com/bb/model/ExtrApiInfo.java b/src/main/java/com/bb/model/ExtrApiInfo.java new file mode 100644 index 0000000..17c1804 --- /dev/null +++ b/src/main/java/com/bb/model/ExtrApiInfo.java @@ -0,0 +1,20 @@ +package com.bb.model; + +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class ExtrApiInfo { + + private long siteIdx; + private long memberIdx; + private String apiBaseUrl; + private String apiAgentId; + private String apiSecretKey; + + private String apiVendor; // 게임 벤더 + private String apiGameId; // /game-list, /lobby-list API 에서 받은 ID + private int apiSkin; // [에볼루션 전용] 게임 실행시 금액별 스킨을 선택 할 수 있습니다. 각 스킨별 금액은 "서비스 데스크" > "자주 묻는 질문" > "스킨별 각 테이블 최대 최소 금액" 에서 확인하실 수 있습니다 + private String apiUsername; // 유저의 아이디 | 아이디는 대소문자를 구분하지 않습니다. 예를 들어 아이디 abcd1234와 ABCD1234는 동일한 유저를 의미합니다. +} diff --git a/src/main/java/com/bb/model/ExtrResponse.java b/src/main/java/com/bb/model/ExtrResponse.java new file mode 100644 index 0000000..836b8af --- /dev/null +++ b/src/main/java/com/bb/model/ExtrResponse.java @@ -0,0 +1,12 @@ +package com.bb.model; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import lombok.Data; + +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ExtrResponse { + + private Integer balance; +} diff --git a/src/main/java/com/bb/model/Game.java b/src/main/java/com/bb/model/Game.java new file mode 100644 index 0000000..457a743 --- /dev/null +++ b/src/main/java/com/bb/model/Game.java @@ -0,0 +1,14 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class Game { + private long gameIdx; + private String gameKey; + private String gameName; + private String gameNameEn; + private String gameImg; + private String gameType; +} + diff --git a/src/main/java/com/bb/model/GameVo.java b/src/main/java/com/bb/model/GameVo.java new file mode 100644 index 0000000..a8307e7 --- /dev/null +++ b/src/main/java/com/bb/model/GameVo.java @@ -0,0 +1,15 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class GameVo { + + private Long vendorIdx; + private String vendorTitle; + private String gameId; + private String gameName; + private String gameNameEn; + private String gameImg; + +} diff --git a/src/main/java/com/bb/model/GsoftApiInfo.java b/src/main/java/com/bb/model/GsoftApiInfo.java new file mode 100644 index 0000000..8bb4d17 --- /dev/null +++ b/src/main/java/com/bb/model/GsoftApiInfo.java @@ -0,0 +1,20 @@ +package com.bb.model; + +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class GsoftApiInfo { + + private long siteIdx; + private long memberIdx; + private String reqAt; + private String apiBaseUrl; + private String clientId; + private String apiAuthKey; + private String userId; // G-Soft용 회원 아이디 + private String gameId; + private String code; + +} diff --git a/src/main/java/com/bb/model/GsoftResponse.java b/src/main/java/com/bb/model/GsoftResponse.java new file mode 100644 index 0000000..10ea57a --- /dev/null +++ b/src/main/java/com/bb/model/GsoftResponse.java @@ -0,0 +1,12 @@ +package com.bb.model; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import lombok.Data; + +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class GsoftResponse { + private int result; + private int balance; +} diff --git a/src/main/java/com/bb/model/GsoftTrxVO.java b/src/main/java/com/bb/model/GsoftTrxVO.java new file mode 100644 index 0000000..f56fd64 --- /dev/null +++ b/src/main/java/com/bb/model/GsoftTrxVO.java @@ -0,0 +1,71 @@ +package com.bb.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.Data; + +@JsonIgnoreProperties(ignoreUnknown = true) +@Data +public class GsoftTrxVO { + + @JsonProperty("tranid") + private String tranId; + + @JsonProperty("realround") + private String realRound; + + @JsonProperty("userid") + private String userId; + + @JsonProperty("userno") + private String userNo; + + @JsonProperty("amount") + private Double amount; + + @JsonProperty("type") + private String type; + + @JsonProperty("game") + private String game; + + @JsonProperty("title") + private String title; + + @JsonProperty("round") + private String round; + + @JsonProperty("balance") + private Double balance; + + @JsonProperty("time") + private String time; + + @JsonProperty("roundcode") + private String roundCode; + + @JsonProperty("amountsum") + private int amountSum; + + @JsonProperty("resultdata") + private String resultData; + + @JsonProperty("playermoney") + private int playerMoney; + + @JsonProperty("bankermoney") + private int bankerMoney; + + @JsonProperty("tiemoney") + private int tieMoney; + + @JsonProperty("ppairmoney") + private int ppairMoney; + + @JsonProperty("bpairmoney") + private int bpairMoney; + + @JsonProperty("subid") + private String vendorApiId; +} diff --git a/src/main/java/com/bb/model/GsoftVO.java b/src/main/java/com/bb/model/GsoftVO.java new file mode 100644 index 0000000..1b17db8 --- /dev/null +++ b/src/main/java/com/bb/model/GsoftVO.java @@ -0,0 +1,70 @@ +package com.bb.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.Data; + +@JsonIgnoreProperties(ignoreUnknown = true) +@Data +public class GsoftVO { + + @JsonProperty("userid") + private String userId; + + @JsonProperty("amount") + private int amount; + + @JsonProperty("type") + private String type; + + @JsonProperty("game") + private String game; + + @JsonProperty("title") + private String title; + + @JsonProperty("round") + private String round; + + @JsonProperty("balance") + private int balance; + + @JsonProperty("time") + private String time; + + @JsonProperty("roundcode") + private String roundCode; + + @JsonProperty("amountsum") + private String amountsum; + + @JsonProperty("realround") + private String realRound; + + @JsonProperty("tranid") + private String tranId; + + @JsonProperty("userno") + private String userNo; + + @JsonProperty("resultdata") + private String resultData; + + @JsonProperty("playermoney") + private int playerMoney; + + @JsonProperty("bankermoney") + private int bankerMoney; + + @JsonProperty("tiemoney") + private int tieMoney; + + @JsonProperty("ppairmoney") + private int ppairMoney; + + @JsonProperty("bpairmoney") + private int bpairMoney; + + private String vendorApiId; +} diff --git a/src/main/java/com/bb/model/Insure.java b/src/main/java/com/bb/model/Insure.java new file mode 100644 index 0000000..0ab867b --- /dev/null +++ b/src/main/java/com/bb/model/Insure.java @@ -0,0 +1,43 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class Insure { + private long idx; + private long siteIdx; + private String siteId; + private String insureType; + private long insureUpSiteIdx; + private String insureUpSiteId; + private long memberIdx; + private String memberId; + private int vendorIdx; + private String refId; + private String betAmt; + private String winAmt; + private String winLoseAmt; + private String insureBetAmt; + private String rate; + private String insureRate; + private String insurePointRate; + private String upSiteinsurePointRate; + private String siteCreditRate; + private String insureAmt; + private String insureUpperAmt; + private String insurePointAmt; + private String upSiteInsurePointAmt; + private String upCredit; + private String credit; + private String pointAmt; + private long preCreditAmt; + private long preCreditPoint; + private long preInsureAmt; + private long preInsurePoint; + private String status; + private String isCancel; + private String regDate; + private String updDate; + private String regId; + +} diff --git a/src/main/java/com/bb/model/Jackpot.java b/src/main/java/com/bb/model/Jackpot.java new file mode 100644 index 0000000..44d72a8 --- /dev/null +++ b/src/main/java/com/bb/model/Jackpot.java @@ -0,0 +1,9 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class Jackpot { + private String id; + private double winAmount; +} diff --git a/src/main/java/com/bb/model/LunchParamVO.java b/src/main/java/com/bb/model/LunchParamVO.java new file mode 100644 index 0000000..a22972e --- /dev/null +++ b/src/main/java/com/bb/model/LunchParamVO.java @@ -0,0 +1,10 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class LunchParamVO { + private String accessToken; + private String lunchToken; + private String gameCode; +} diff --git a/src/main/java/com/bb/model/Member.java b/src/main/java/com/bb/model/Member.java new file mode 100644 index 0000000..d8c19d8 --- /dev/null +++ b/src/main/java/com/bb/model/Member.java @@ -0,0 +1,29 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class Member { + + private int siteIdx; + private String siteId; + private int memberIdx; + private String memberId; + private String memberNick; + private long balance; + private String lastSid; + private String bombAccId; + private String dowinId; + private Long pragmaticId; + private long amazonId; + private Long starGameId; + private long totalEvoBetAmt; + private String parseEvoYn; + private String ip; + private int lastInVendorIdx; + private String lastBetDate; + + private String vendorUsername; + private long vendorBalance; + private long userBalance; +} diff --git a/src/main/java/com/bb/model/MemberParam.java b/src/main/java/com/bb/model/MemberParam.java new file mode 100644 index 0000000..9379eeb --- /dev/null +++ b/src/main/java/com/bb/model/MemberParam.java @@ -0,0 +1,15 @@ +package com.bb.model; + +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.Size; + +import lombok.Data; + +@Data +public class MemberParam { + + private String userId; + private String nickName; + private String siteUserId; + +} diff --git a/src/main/java/com/bb/model/NexusApiInfo.java b/src/main/java/com/bb/model/NexusApiInfo.java new file mode 100644 index 0000000..6efb519 --- /dev/null +++ b/src/main/java/com/bb/model/NexusApiInfo.java @@ -0,0 +1,29 @@ +package com.bb.model; + +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class NexusApiInfo { + + private long siteIdx; + private long memberIdx; + private String apiBaseUrl; + private String agentId; + private String agentSecretKey; + private String vendorKey; // 게임사 벤더키 + private String gameKey; // 특정 게임을 식별하기 위한 고유 키 + private String skin; // skin 코드 (카지노 게임사 전용) [부록 → 카지노 한도 스킨표]에서 확인가능 + private String type; // 게임타입 (슬롯 게임사 전용) [Slot, Arcade, Fishing, Bingo, Table Games] + private String username; // 3글자 ~ 22글자 API용 회원 아이디 (게임을 위한 고유한 회원 식별자입니다) + private String nickname; // 2글자 ~ 22글자 사이트 닉네임 (게임 중에 다른 플레이어에게 보여지는 회원의 닉네임입니다) + private String siteUsername; // 3글자 ~ 22글자 사이트 회원아이디 (실사이트에서 사용하는 고유 회원 아이디) + private String ip; // 회원접속아이피 + private String language; // 인게임 언어팩 (기본:영문) + private String platform; // 회원브라우저 환경 (desktop, mobile) + + private String sdate; + private String edate; + private String limit; +} diff --git a/src/main/java/com/bb/model/NexusBalanceData.java b/src/main/java/com/bb/model/NexusBalanceData.java new file mode 100644 index 0000000..92be775 --- /dev/null +++ b/src/main/java/com/bb/model/NexusBalanceData.java @@ -0,0 +1,14 @@ +package com.bb.model; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import lombok.Data; + +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class NexusBalanceData { + + private int beforeBalance; + private int balance; + private String currency; +} diff --git a/src/main/java/com/bb/model/NexusResponse.java b/src/main/java/com/bb/model/NexusResponse.java new file mode 100644 index 0000000..007ba9d --- /dev/null +++ b/src/main/java/com/bb/model/NexusResponse.java @@ -0,0 +1,14 @@ +package com.bb.model; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import lombok.Data; + +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class NexusResponse { + + private int code; + private String msg; + private NexusBalanceData data; +} diff --git a/src/main/java/com/bb/model/NexusSmlData.java b/src/main/java/com/bb/model/NexusSmlData.java new file mode 100644 index 0000000..fbb9782 --- /dev/null +++ b/src/main/java/com/bb/model/NexusSmlData.java @@ -0,0 +1,44 @@ +package com.bb.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import lombok.Data; + +@JsonIgnoreProperties(ignoreUnknown = true) +@Data +public class NexusSmlData { + + private long siteIdx; + private long memberIdx; + private String transactionKey; // 거래코드(고유키) + private String parentTransactionKey; // 각 거래를 그룹화 하기 위한 키입니다 (베팅, 결과를 그룹화하는 키입니다) + private String username; // API에 등록된 회원 아이디(고유키) + private String siteUsername; // 사이트에 등록된 회원 아이디 + private String vendorKey; // 게임사 벤더키 + private String vendorName; // 게임사 벤더명 + private String gameCategoryId; // 게임 카테고리 아이디 + private String gameCategory; // 게임 카테고리 + private String gameName; // 특정 게임을 식별하기 위한 게임명 + private String gameTypeId; // 게임 형식 아이디 + private String gameType; // 게임 형식 + private String gameImage; // 게임이미지 URL + private String type; // 트랜잭션 종류(turn_bet, turn_win, turn_draw, turn_cancel, turn_lose, turn_adjust, turn_in, turn_out) + private String key; // 게임사 고유코드 + private String refId; // 게임사 상위 베팅 코드 + private String oRefId; // 게임사로부터 전송 받은 게임 코드 + private String roundId; // 라운드 아이디 + private String isBonus; // 보너스 여부 + private String isJackpot; // 잭팟 여부 + private String isPromo; // 프로모션 여부 + private String isFreeGame; // 프리게임 여부 + private String beforeCash; // 이전 금액 + private String amount; // 금액 + private String afterCash; // 이후 금액 + private String updepositCash; // 당첨금 제한이 설정된 경우 설정된 금액 이상으로 당첨되면 설정된 금액까지는 유저에게 지급되며, 초과하는 금액은 에이전트에게 회수됩니다. 회수된 금액은 [updepositCash] 항목에 기록됩니다. + private String gameId; // 게임 아이디 + private String siteGameId; // 사이트 게임 아이디 + private String createdAt; // 요청 받은 시간 + private String requestedAt; // api 요청 일자 + private String betDateTime; // 배팅 시간 + private String detail; // 상세 +} diff --git a/src/main/java/com/bb/model/NexusSmlRequest.java b/src/main/java/com/bb/model/NexusSmlRequest.java new file mode 100644 index 0000000..cec9099 --- /dev/null +++ b/src/main/java/com/bb/model/NexusSmlRequest.java @@ -0,0 +1,15 @@ +package com.bb.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import lombok.Data; + +@JsonIgnoreProperties(ignoreUnknown = true) +@Data +public class NexusSmlRequest { + + private String apiKey; // 사이트 API 키 + private NexusSmlData params; // 데이터 + private String createdAt; // 요청 받은 시간 + private String requestedAt; // api 요청 일자 +} diff --git a/src/main/java/com/bb/model/NexusTrplVO.java b/src/main/java/com/bb/model/NexusTrplVO.java new file mode 100644 index 0000000..eab2839 --- /dev/null +++ b/src/main/java/com/bb/model/NexusTrplVO.java @@ -0,0 +1,46 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class NexusTrplVO { + /** + * + FieldTypeComment + ea_keybigint unsigned NOT NULL + table_idvarchar(50) NOT NULL게임방 ID + game_idvarchar(50) NOT NULL게임별 ID + siteint unsigned NOT NULL사이트키 + uidvarchar(50) NOT NULL유저 ID + typevarchar(20) NOT NULL게임 타입 + amount1int unsigned NOT NULL유저 배팅금 + amount2int unsigned NOT NULL변환 배팅금 + payoff1int unsigned NOT NULL유저 획득금 + payoff2int unsigned NOT NULL변환 획득금 + statustinyint unsigned NOT NULL상태(0:배팅중,1:배팅확정,2:완료,3:거부) + jsontext NOT NULL상세 내역 json + reg_dtdatetime NOT NULL등록일시 + update_dttimestamp NULL업데이트 일시 + round_idvarchar(50) NULL + */ + private Long eaKey; + private String tableId; + private String gameId; + private Integer site; + private String uid; + private String type; + private Long amount1; + private Long amount2; + private Long payoff1; + private Long payoff2; + private Integer status; + private String json; + private String regDt; + private String updateDt; + private String roundId; + + private long siteIdx; + private String siteId; + private int callbackCnt; +} + diff --git a/src/main/java/com/bb/model/OTPInfo.java b/src/main/java/com/bb/model/OTPInfo.java new file mode 100644 index 0000000..69ef198 --- /dev/null +++ b/src/main/java/com/bb/model/OTPInfo.java @@ -0,0 +1,17 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class OTPInfo { + + private long siteIdx; + private String otpType; + private String siteId; + private String account; + private String issuer; + private String secretKey; + private String url; + private String regDate; + private String updDate; +} diff --git a/src/main/java/com/bb/model/OnixResponse.java b/src/main/java/com/bb/model/OnixResponse.java new file mode 100644 index 0000000..a010ca8 --- /dev/null +++ b/src/main/java/com/bb/model/OnixResponse.java @@ -0,0 +1,48 @@ +package com.bb.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * Onix Seamless API 응답 DTO + * 모든 Onix 콜백 응답 (balance, changeBalance)에 사용 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@JsonInclude(JsonInclude.Include.NON_NULL) +public class OnixResponse { + + /** + * 결과 코드: 1(성공), 0(실패) + */ + private int result; + + /** + * 사용자 현재 잔고 (result=1일 때만 포함) + */ + private long balance; + + /** + * 성공 응답 생성 (result=1, balance 포함) + */ + public static OnixResponse success(long balance) { + return OnixResponse.builder() + .result(1) + .balance(balance) + .build(); + } + + /** + * 실패 응답 생성 (result=0, 에러 메시지 없음) + */ + public static OnixResponse failure() { + return OnixResponse.builder() + .result(0) + .build(); + } +} diff --git a/src/main/java/com/bb/model/PageFormVO.java b/src/main/java/com/bb/model/PageFormVO.java new file mode 100644 index 0000000..ac63adc --- /dev/null +++ b/src/main/java/com/bb/model/PageFormVO.java @@ -0,0 +1,88 @@ +package com.bb.model; + +public class PageFormVO { + + String function_name; + int page; + int count_per_page; + int count_per_list; + int tatal_page_count; + int tatal_list_count; + int limit; + int offset; + String pagination; + + public String getFunction_name() { + return function_name; + } + + public void setFunction_name(String function_name) { + this.function_name = function_name; + } + + public int getPage() { + return page; + } + + public void setPage(int page) { + this.page = page; + } + + public int getCount_per_page() { + return count_per_page; + } + + public void setCount_per_page(int count_per_page) { + this.count_per_page = count_per_page; + } + + public int getCount_per_list() { + return count_per_list; + } + + public void setCount_per_list(int count_per_list) { + this.count_per_list = count_per_list; + } + + public int getTatal_page_count() { + return tatal_page_count; + } + + public void setTatal_page_count(int tatal_page_count) { + this.tatal_page_count = tatal_page_count; + } + + public int getTatal_list_count() { + return tatal_list_count; + } + + public void setTatal_list_count(int tatal_list_count) { + this.tatal_list_count = tatal_list_count; + } + + public int getLimit() { + return limit; + } + + public void setLimit(int limit) { + this.limit = limit; + } + + public int getOffset() { + return offset; + } + + public void setOffset(int offset) { + this.offset = offset; + } + + public String getPagination() { + return pagination; + } + + public void setPagination(String pagination) { + this.pagination = pagination; + } + + +} diff --git a/src/main/java/com/bb/model/PandaResponse.java b/src/main/java/com/bb/model/PandaResponse.java new file mode 100644 index 0000000..ffdd353 --- /dev/null +++ b/src/main/java/com/bb/model/PandaResponse.java @@ -0,0 +1,12 @@ +package com.bb.model; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import lombok.Data; + +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class PandaResponse { + + private Integer balance; +} diff --git a/src/main/java/com/bb/model/PlayParam.java b/src/main/java/com/bb/model/PlayParam.java new file mode 100644 index 0000000..3fdb5de --- /dev/null +++ b/src/main/java/com/bb/model/PlayParam.java @@ -0,0 +1,39 @@ +package com.bb.model; + +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.Size; + +import lombok.Data; + +@Data +public class PlayParam { + + + @NotEmpty + @Size(max = 40) // 최대 길이 64 + private String userId; + + @Size(max = 40) // 최대 길이 64 + private String nickName; + + @NotEmpty + private String vendorKey; + + @NotEmpty + private String gameKey; + + private Long balance; + + private String isMobile; + private String userIp; + + private String language; + private String decYn; + private String requestAT; + private String vendorCode; + private String skinType; + private String parseUseYn; + + // 유저별 최대베팅제한금액 (Optional, 기본값 0) + private Long userMaxBet; +} diff --git a/src/main/java/com/bb/model/PowerballData.java b/src/main/java/com/bb/model/PowerballData.java new file mode 100644 index 0000000..e704732 --- /dev/null +++ b/src/main/java/com/bb/model/PowerballData.java @@ -0,0 +1,11 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class PowerballData { + + private String siteId; + private String memId; + private String balance; +} diff --git a/src/main/java/com/bb/model/PowerballRequest.java b/src/main/java/com/bb/model/PowerballRequest.java new file mode 100644 index 0000000..aa93c71 --- /dev/null +++ b/src/main/java/com/bb/model/PowerballRequest.java @@ -0,0 +1,71 @@ +package com.bb.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.Data; + +@JsonIgnoreProperties(ignoreUnknown = true) +@Data +public class PowerballRequest { + + @JsonProperty("_id") + private String mongoDbId; // 몽고DB ID + + @JsonProperty("siteId") + private String siteId; // 사이트 아이디 + + @JsonProperty("siteName") + private String siteName; // 사이트명 + + @JsonProperty("id") + private String id; // 등록된 유저아이디 + + @JsonProperty("memId") + private String memId; // id 필드와 같은 데이터 + + @JsonProperty("gameId") + private String betId; // 배팅 ID + + @JsonProperty("vendorCode") + private String vendorCode; // 게임코드 + + @JsonProperty("gameName") + private String gameName; // 게임코드 + + @JsonProperty("round") + private long round; // 게임 라운드 + + @JsonProperty("betType") + private String betType; // 선택한 베팅, no = 일반볼 홀 + + @JsonProperty("gameType") + private String gameType; // 베팅한 게임 그룹, noe = 일반볼 홀짝 + + @JsonProperty("resultType") + private String resultType; // 배팅결과 타입 + + @JsonProperty("folder") + private String folder; // 조합베팅: 1: 단일베팅 (예: 홀, 짝, 언더, 오버 등), 2 이상: 조합베팅(예: 홀오버, 짝오버 등) + + @JsonProperty("betAmt") + private int betAmt; // 베팅금 + + @JsonProperty("betWinAmt") + private int betWinAmt; // 당첨금 + + @JsonProperty("balance") + private int balance; // 베팅 후 유저보유금 + + @JsonProperty("betRate") + private String betRate; // 해당 베팅 배당 + + @JsonProperty("rate") + private String gameRate; // 배당 + + @JsonProperty("betTime") + private String betTime; // 베팅시간 + + @JsonProperty("date") + private String betDate; // 배팅날짜 +} diff --git a/src/main/java/com/bb/model/PowerballResponse.java b/src/main/java/com/bb/model/PowerballResponse.java new file mode 100644 index 0000000..13b44e1 --- /dev/null +++ b/src/main/java/com/bb/model/PowerballResponse.java @@ -0,0 +1,14 @@ +package com.bb.model; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import lombok.Data; + +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class PowerballResponse { + + private String result; // SUCCESS 또는 FAILED + private String msg; // "에러 메세지" + private PowerballData data; +} diff --git a/src/main/java/com/bb/model/PpaReponseVo.java b/src/main/java/com/bb/model/PpaReponseVo.java new file mode 100644 index 0000000..c5bcfd2 --- /dev/null +++ b/src/main/java/com/bb/model/PpaReponseVo.java @@ -0,0 +1,84 @@ +package com.bb.model; + +import com.bb.exception.ApiException; +import com.bb.exception.RequestParameterApiException; +import com.bb.util.StringUtils; +import com.fasterxml.jackson.annotation.JsonInclude; + +import groovy.transform.builder.Builder; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.HashMap; +import java.util.Map; + + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@JsonInclude(JsonInclude.Include.NON_NULL) +public class PpaReponseVo { + /** 결과 코드 */ + private String playerSessionId; + private String externalPlayerID; + private String playerName; + private long balance; + private String currency; + private String country; + private int error; + private String message; + + + /** + * 필수 파라미터 검증 + * @param value + * @param paramName + * @throws ApiException + */ + public static void require(Object value, String paramName) throws ApiException { + String stringValue = (value == null) ? null : String.valueOf(value); + + if(StringUtils.isEmpty(stringValue)) { + throw new RequestParameterApiException( paramName); + } + } + + /** + * 파라미터 조건 검증 + * @param condition + * @param message + * @throws ApiException + */ + public static void then( boolean condition, String message ) throws ApiException { + if( condition ) { + throw new ApiException( message ); + } + } + + /** + * 파라미터가 특정 목록에 포함되어 있는지 검증 + * @param param + * @param paramName + * @param values + * @throws ApiException + */ + public static void notMatched( Object param, String paramName, Object... values ) throws ApiException { + boolean matched = false; + + for( Object value : values ) { + if( param.equals( value ) ) { + matched = true; + break; + } + } + + if( !matched ) { + throw new ApiException( "유효하지 않은 파라미터 : " + paramName ); + } + } + +} diff --git a/src/main/java/com/bb/model/PrimeResponse.java b/src/main/java/com/bb/model/PrimeResponse.java new file mode 100644 index 0000000..7923ded --- /dev/null +++ b/src/main/java/com/bb/model/PrimeResponse.java @@ -0,0 +1,13 @@ +package com.bb.model; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import lombok.Data; + +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class PrimeResponse { + + private Integer balance; + private Integer beforeBalance; +} diff --git a/src/main/java/com/bb/model/RaveResponse.java b/src/main/java/com/bb/model/RaveResponse.java new file mode 100644 index 0000000..6f1fd70 --- /dev/null +++ b/src/main/java/com/bb/model/RaveResponse.java @@ -0,0 +1,14 @@ +package com.bb.model; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import lombok.Data; + +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class RaveResponse { + + private int balance; + private int errorCode; + private String message; +} diff --git a/src/main/java/com/bb/model/ReportSearch.java b/src/main/java/com/bb/model/ReportSearch.java new file mode 100644 index 0000000..73be5e1 --- /dev/null +++ b/src/main/java/com/bb/model/ReportSearch.java @@ -0,0 +1,33 @@ +package com.bb.model; + +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class ReportSearch { + + @NotNull + @Min(1) + private Long searchSiteIdx; + + @NotBlank + private String searchSiteId; + + private String searchMemId; + + @NotBlank + private String startDate; + private String year; + private String month; + + @NotBlank + private String endDate; + + private String isToday; + private String topId; // 트리정보에서 최상위 아이디 설정을 위한 변수 + + @NotBlank + private String withBottomYN; +} diff --git a/src/main/java/com/bb/model/ScResponse.java b/src/main/java/com/bb/model/ScResponse.java new file mode 100644 index 0000000..d2c81e4 --- /dev/null +++ b/src/main/java/com/bb/model/ScResponse.java @@ -0,0 +1,89 @@ +package com.bb.model; + +import com.bb.exception.ApiException; +import com.bb.exception.RequestParameterApiException; +import com.bb.util.StringUtils; +import com.fasterxml.jackson.annotation.JsonInclude; + + +import lombok.Data; +import lombok.Getter; +import lombok.Setter; + +import java.util.HashMap; +import java.util.Map; + + +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ScResponse { + /** 결과 코드 */ + private int result; + /** 결과 메시지 */ + private String status; + /** 데이터 */ + private Map data; + + /** + * 데이터 추가 + * @param key + * @param value + */ + public void put(String key, Object value) { + if(this.data == null) { + this.data = new HashMap<>(); + } + + this.data.put(key, value); + } + + + /** + * 필수 파라미터 검증 + * @param value + * @param paramName + * @throws ApiException + */ + public static void require(Object value, String paramName) throws ApiException { + String stringValue = (value == null) ? null : String.valueOf(value); + + if(StringUtils.isEmpty(stringValue)) { + throw new RequestParameterApiException( paramName); + } + } + + /** + * 파라미터 조건 검증 + * @param condition + * @param message + * @throws ApiException + */ + public static void then( boolean condition, String message ) throws ApiException { + if( condition ) { + throw new ApiException( message ); + } + } + + /** + * 파라미터가 특정 목록에 포함되어 있는지 검증 + * @param param + * @param paramName + * @param values + * @throws ApiException + */ + public static void notMatched( Object param, String paramName, Object... values ) throws ApiException { + boolean matched = false; + + for( Object value : values ) { + if( param.equals( value ) ) { + matched = true; + break; + } + } + + if( !matched ) { + throw new ApiException( "유효하지 않은 파라미터 : " + paramName ); + } + } + +} diff --git a/src/main/java/com/bb/model/Site.java b/src/main/java/com/bb/model/Site.java new file mode 100644 index 0000000..c3b4d3f --- /dev/null +++ b/src/main/java/com/bb/model/Site.java @@ -0,0 +1,65 @@ +package com.bb.model; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.List; + +import lombok.Data; + +@Data +public class Site implements Serializable { + + private int siteIdx; + private String siteIdxHex; + private String siteId; + private String siteName; + private int siteLevel; + private String siteGubun; + private String sitePass; + private String siteMobile; + private String siteKey; + private String siteVenderType; + private int siteCompanyIdx; + private String siteCreditRate; + private String ips; + + private String siteUseYn; + private String siteDispYn; + private String regDate; + private String siteType; + private int upperSiteIdx; + private String upperSiteId; + private String memo; + private String siteCbUrl; + private String siteBankInfo; + private String siteIp; + + private long aiCredit; + private long aoCredit; + private long ciCredit; + private long coCredit; + + private int downSiteCnt; + private int downMemCnt; + + private long credit; + private long siteMaxCredit; + private long point; + + private long insurance; + private long insurancePoint; + + private String nowPass; + private String newPass; + private String domain; + + private String token; + + private int testCnt; + + private String isTransfer; + private String useParseStatMenu; + + private List treeInfo; + +} diff --git a/src/main/java/com/bb/model/SitePwdVO.java b/src/main/java/com/bb/model/SitePwdVO.java new file mode 100644 index 0000000..712bd2c --- /dev/null +++ b/src/main/java/com/bb/model/SitePwdVO.java @@ -0,0 +1,14 @@ +package com.bb.model; + +import jakarta.validation.constraints.NotEmpty; + +import lombok.Data; + +@Data +public class SitePwdVO { + + private String siteId; + + @NotEmpty + private String newPassword; +} diff --git a/src/main/java/com/bb/model/SiteSearch.java b/src/main/java/com/bb/model/SiteSearch.java new file mode 100644 index 0000000..4ba6b4d --- /dev/null +++ b/src/main/java/com/bb/model/SiteSearch.java @@ -0,0 +1,49 @@ +package com.bb.model; + +import jakarta.validation.constraints.NotBlank; + +import lombok.Data; + +@Data +public class SiteSearch extends PageFormVO { + + private long siteIdx; + private String siteId; + private long upperSiteIdx; + private String upperSiteId; + private String memberId; + private String vendorUsername; + + private long searchSiteIdx; + private String searchSiteId; + private String searchMemId; + private String searchType; + private String searchValue; + private String startDate; + private String year; + private String month; + private String endDate; + private int searchLimit; + private int searchDepth; + + private int parsEvoAmount; + + private String siteDispYn; + //크레딧 + private String refId; + private String creditType; + private String creditStatus; + + // 보험 + private String status; + private String updown; + private String dispYn; + + private String isExcel; + private String topId; // 트리정보에서 최상위 아이디 설정을 위한 변수 + + @NotBlank + private String withBottomYN; + private String periodType; + +} diff --git a/src/main/java/com/bb/model/SiteVendorSkinVO.java b/src/main/java/com/bb/model/SiteVendorSkinVO.java new file mode 100644 index 0000000..17766dc --- /dev/null +++ b/src/main/java/com/bb/model/SiteVendorSkinVO.java @@ -0,0 +1,36 @@ +package com.bb.model; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; + +import lombok.Data; + +@Data +public class SiteVendorSkinVO { + + @NotNull + private Long siteIdx; + + @NotNull + private Long vendorIdx; + + @NotBlank + private String category; + + @NotBlank + private String useYn; + + @NotNull + private Long siteMaxBet; + + @NotNull + private Long siteMaxWin; + + @NotEmpty + private String skinType; + + private String nexusSkinType; + + private String extrSkinType; +} diff --git a/src/main/java/com/bb/model/SlotGame.java b/src/main/java/com/bb/model/SlotGame.java new file mode 100644 index 0000000..be21f41 --- /dev/null +++ b/src/main/java/com/bb/model/SlotGame.java @@ -0,0 +1,15 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class SlotGame { + + private String id; + private String key; + private SlotGameName names; + private String platform; + private String category; + private String type; + private String image; +} diff --git a/src/main/java/com/bb/model/SlotGameName.java b/src/main/java/com/bb/model/SlotGameName.java new file mode 100644 index 0000000..436dcaa --- /dev/null +++ b/src/main/java/com/bb/model/SlotGameName.java @@ -0,0 +1,10 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class SlotGameName { + + private String ko; + private String en; +} diff --git a/src/main/java/com/bb/model/SvendorResponse.java b/src/main/java/com/bb/model/SvendorResponse.java new file mode 100644 index 0000000..9ce142a --- /dev/null +++ b/src/main/java/com/bb/model/SvendorResponse.java @@ -0,0 +1,15 @@ +package com.bb.model; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import lombok.Data; + +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class SvendorResponse { + + private String balance; + private String id; + private Integer statuscode; + private String status; +} diff --git a/src/main/java/com/bb/model/TheaResponse.java b/src/main/java/com/bb/model/TheaResponse.java new file mode 100644 index 0000000..79954b1 --- /dev/null +++ b/src/main/java/com/bb/model/TheaResponse.java @@ -0,0 +1,12 @@ +package com.bb.model; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import lombok.Data; + +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class TheaResponse { + + private Integer balance; +} diff --git a/src/main/java/com/bb/model/ThenutResponse.java b/src/main/java/com/bb/model/ThenutResponse.java new file mode 100644 index 0000000..3da772e --- /dev/null +++ b/src/main/java/com/bb/model/ThenutResponse.java @@ -0,0 +1,14 @@ +package com.bb.model; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import lombok.Data; + +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ThenutResponse { + + private Integer balance; + private Integer errorCode; + private String message; +} diff --git a/src/main/java/com/bb/model/TplusApiInfo.java b/src/main/java/com/bb/model/TplusApiInfo.java new file mode 100644 index 0000000..b2c12eb --- /dev/null +++ b/src/main/java/com/bb/model/TplusApiInfo.java @@ -0,0 +1,20 @@ +package com.bb.model; + +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class TplusApiInfo { + + private long siteIdx; + private long memberIdx; + private String apiBaseUrl; + private String clientId; + private String apiAuthKey; + private String apiUsername; // Tplus용 회원 아이디 + private String thirdparty; + private String uuid; + private String reqAt; + private String pairTransactionKey; +} diff --git a/src/main/java/com/bb/model/TplusCBData.java b/src/main/java/com/bb/model/TplusCBData.java new file mode 100644 index 0000000..9200b0d --- /dev/null +++ b/src/main/java/com/bb/model/TplusCBData.java @@ -0,0 +1,41 @@ +package com.bb.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.Data; + +@JsonIgnoreProperties(ignoreUnknown = true) +@Data +public class TplusCBData { + + @JsonProperty("agent_name") + private String agentName; + + @JsonProperty("user_name") + private String userName; + + @JsonProperty("amount") + private double amount; + + @JsonProperty("category") + private String category; + + @JsonProperty("game_name") + private String gameName; + + @JsonProperty("game_symbol") + private String gameSymbol; + + @JsonProperty("thirdparty") + private String thirdParty; + + @JsonProperty("transactionKey") + private String transactionKey; + + @JsonProperty("pair_transaction_key") + private String pairTransactionKey; + + @JsonProperty("processed_at") + private String processedAt; +} diff --git a/src/main/java/com/bb/model/TplusCBRequest.java b/src/main/java/com/bb/model/TplusCBRequest.java new file mode 100644 index 0000000..6359c72 --- /dev/null +++ b/src/main/java/com/bb/model/TplusCBRequest.java @@ -0,0 +1,17 @@ +package com.bb.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.Data; + +@JsonIgnoreProperties(ignoreUnknown = true) +@Data +public class TplusCBRequest { + + @JsonProperty("api_key") + private String apiKey; // 사이트 API 키 + + @JsonProperty("params") + private TplusCBData param; +} diff --git a/src/main/java/com/bb/model/TplusData.java b/src/main/java/com/bb/model/TplusData.java new file mode 100644 index 0000000..ff7040f --- /dev/null +++ b/src/main/java/com/bb/model/TplusData.java @@ -0,0 +1,23 @@ +package com.bb.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.Data; + +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class TplusData { + + @JsonProperty("user_name") + private String userName; + + @JsonProperty("balance") + private Double balance; + + @JsonProperty("beforeBalance") + private Double beforeBalance; + + @JsonProperty("currency") + private String currency; +} diff --git a/src/main/java/com/bb/model/TplusResponse.java b/src/main/java/com/bb/model/TplusResponse.java new file mode 100644 index 0000000..ed0ce21 --- /dev/null +++ b/src/main/java/com/bb/model/TplusResponse.java @@ -0,0 +1,20 @@ +package com.bb.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.Data; + +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class TplusResponse { + + @JsonProperty("code") + private int code; + + @JsonProperty("data") + private TplusData data; + + @JsonProperty("msg") + private String msg; +} diff --git a/src/main/java/com/bb/model/TransSearchVO.java b/src/main/java/com/bb/model/TransSearchVO.java new file mode 100644 index 0000000..20e23ed --- /dev/null +++ b/src/main/java/com/bb/model/TransSearchVO.java @@ -0,0 +1,53 @@ +package com.bb.model; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; + +import lombok.Data; + +@Data +public class TransSearchVO extends PageFormVO { + + private Long siteIdx; + + private String siteId; + + @NotBlank + private String startDate; + + @NotBlank + private String endDate; + + private String category; + + private Long vendorIdx; + + private String resultInfo; + + private String betWinAmt; + + @NotNull + private Long searchSiteIdx; + + @NotBlank + private String searchSiteId; + + private String searchMemberId; + + private String betId; + private String refId; + + @NotBlank + private String withBottomYN; + + @NotBlank + private String oldYN; + + private String orderStr; + + private String topId; // 트리정보에서 최상위 아이디 설정을 위한 변수 + + private String startDatePartition; + private String endDatePartition; + +} diff --git a/src/main/java/com/bb/model/TrfApiInfo.java b/src/main/java/com/bb/model/TrfApiInfo.java new file mode 100644 index 0000000..0d7b81d --- /dev/null +++ b/src/main/java/com/bb/model/TrfApiInfo.java @@ -0,0 +1,16 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class TrfApiInfo { + + private Long siteIdx; + private Long memberIdx; + private String memberId; + private String apiUsername; + private String apiVendor; + private String apiBaseUrl; + private String apiAuthId; + private String apiAuthKey; +} diff --git a/src/main/java/com/bb/model/UserKickParam.java b/src/main/java/com/bb/model/UserKickParam.java new file mode 100644 index 0000000..c69985a --- /dev/null +++ b/src/main/java/com/bb/model/UserKickParam.java @@ -0,0 +1,8 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class UserKickParam { + private String userid; // 유저 ID (필수) +} diff --git a/src/main/java/com/bb/model/UserSearch.java b/src/main/java/com/bb/model/UserSearch.java new file mode 100644 index 0000000..4751484 --- /dev/null +++ b/src/main/java/com/bb/model/UserSearch.java @@ -0,0 +1,33 @@ +package com.bb.model; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; + +import lombok.Data; + +@Data +public class UserSearch extends PageFormVO { + + private Long siteIdx; + + private String siteId; + + private Long memberIdx; + + private String memberId; + + @NotNull + private Long searchSiteIdx; + + @NotBlank + private String searchSiteId; + + private String searchMemberId; + + @NotBlank + private String withBottomYN; + + private String orderStr; + + private String topId; // 트리정보에서 최상위 아이디 설정을 위한 변수 +} diff --git a/src/main/java/com/bb/model/Vendor.java b/src/main/java/com/bb/model/Vendor.java new file mode 100644 index 0000000..8a5d439 --- /dev/null +++ b/src/main/java/com/bb/model/Vendor.java @@ -0,0 +1,12 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class Vendor { + + private long siteIdx; + private long vendorIdx; + private String vendorCode; + +} diff --git a/src/main/java/com/bb/model/VendorChangeBalanceLogVo.java b/src/main/java/com/bb/model/VendorChangeBalanceLogVo.java new file mode 100644 index 0000000..c01c7a8 --- /dev/null +++ b/src/main/java/com/bb/model/VendorChangeBalanceLogVo.java @@ -0,0 +1,21 @@ +package com.bb.model; + +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class VendorChangeBalanceLogVo { + + private Long idx; + private Long siteIdx; + private Long memberIdx; + private String vendor; + private String vendorApiId; + private String reqType; + private int amount; + private String reqAt; + private String reqStatus; + private String reqMsg; + private String regDate; +} diff --git a/src/main/java/com/bb/model/VendorsParam.java b/src/main/java/com/bb/model/VendorsParam.java new file mode 100644 index 0000000..9cfa866 --- /dev/null +++ b/src/main/java/com/bb/model/VendorsParam.java @@ -0,0 +1,5 @@ +package com.bb.model; + +public class VendorsParam { + +} diff --git a/src/main/java/com/bb/model/VinusData.java b/src/main/java/com/bb/model/VinusData.java new file mode 100644 index 0000000..c2bb4f5 --- /dev/null +++ b/src/main/java/com/bb/model/VinusData.java @@ -0,0 +1,26 @@ +package com.bb.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.Data; + +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class VinusData { + + @JsonProperty("user_id") + private String userId; + + @JsonProperty("user_username") + private String userUsername; + + @JsonProperty("user_nickname") + private String userNickname; + + @JsonProperty("balance") + private Integer balance; + + @JsonProperty("token") + private String token; +} diff --git a/src/main/java/com/bb/model/VinusResponse.java b/src/main/java/com/bb/model/VinusResponse.java new file mode 100644 index 0000000..67b6b9d --- /dev/null +++ b/src/main/java/com/bb/model/VinusResponse.java @@ -0,0 +1,17 @@ +package com.bb.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.Data; + +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class VinusResponse { + + @JsonProperty("result") + private int result; + + @JsonProperty("data") + private VinusData data; +} diff --git a/src/main/java/com/bb/model/WithdrewRequest.java b/src/main/java/com/bb/model/WithdrewRequest.java new file mode 100644 index 0000000..b22b482 --- /dev/null +++ b/src/main/java/com/bb/model/WithdrewRequest.java @@ -0,0 +1,11 @@ +package com.bb.model; + +import lombok.Data; + +@Data +public class WithdrewRequest { + + private String id; + private String vendor; + private String key; +} diff --git a/src/main/java/com/bb/service/AsyncSiteService.java b/src/main/java/com/bb/service/AsyncSiteService.java new file mode 100644 index 0000000..4052a2b --- /dev/null +++ b/src/main/java/com/bb/service/AsyncSiteService.java @@ -0,0 +1,297 @@ +package com.bb.service; + +import java.time.Duration; +import java.util.HashMap; + +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.WebClientRequestException; + +import com.bb.dao.CallBackDao; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class AsyncSiteService { + + @Autowired + SiteService siteService; + + @Autowired + WebClient webClient; + + @Autowired + CallBackDao callBackDao; + + @Async + public void insertEvoDetailProc(String LOG_PREFIX, String betId, JSONObject saveObj, JSONArray saveObjs) { + try { + HashMap detailMap = new HashMap<>(); + detailMap.put("refId", betId); + if(saveObj != null) { + detailMap.put("orgDetail", saveObj.toString()); + } else { + detailMap.put("orgDetail", saveObjs.toString()); + } + detailMap.put("parDetail", null); + log.info(LOG_PREFIX+ "insertEvoDetailProc START"); + int result = siteService.insertEvoDetail(detailMap); + log.info(LOG_PREFIX+ "insertEvoDetailProc END result::" + result); + + } catch(DataIntegrityViolationException de) { + log.error(LOG_PREFIX+ "Duplicate refId"); + } catch (Exception e) { + log.error(LOG_PREFIX+ "[Exception]"+e.toString()); + } + + } + + @Async + public void asyncBalance(String LOG_PREFIX, HashMap siteApiInfo, JSONObject param) { + HttpHeaders headers = new HttpHeaders(); + headers.set("Connection", "close"); + headers.add("Content-Type", MediaType.APPLICATION_JSON_VALUE); + headers.add("Accept", MediaType.APPLICATION_JSON_VALUE); + headers.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + + final String baseCbUrl = siteApiInfo.get("siteCbUrl").toString().trim(); + log.info(LOG_PREFIX+ "Callback URL: " + baseCbUrl + "/balance"); + log.info(LOG_PREFIX+ "Body: " + param.toString()); + + try { + param.put("requestAt", Long.toString(System.currentTimeMillis())); + + webClient.post() + .uri(baseCbUrl + "/balance") + .headers(h -> h.addAll(headers)) + .bodyValue(param.toString()) + .exchangeToMono(resp -> resp.toEntity(String.class)) + .timeout(Duration.ofSeconds(2)) + .doOnSuccess(response -> { + if (response != null) { + log.info("{}Response HTTP Status: {}", LOG_PREFIX, response.getStatusCode().value()); + log.info("{}Response Body: {}", LOG_PREFIX, response.getBody()); + } + }) + .doOnError(e -> { + if (e instanceof WebClientRequestException wcre) { + Throwable cause = wcre.getCause(); + + if (hasCause(cause, io.netty.channel.ConnectTimeoutException.class) + || hasCause(cause, java.net.ConnectException.class)) { + + log.error("{}CONNECT_TIMEOUT", LOG_PREFIX); + log.error("{}{}", LOG_PREFIX, wcre.toString()); + + } else if (hasCause(cause, io.netty.handler.timeout.ReadTimeoutException.class) + || hasCause(cause, java.net.SocketTimeoutException.class)) { + + log.error("{}READ_TIMEOUT", LOG_PREFIX); + log.error("{}{}", LOG_PREFIX, wcre.toString()); + + } else { + log.error("{}WebClientRequestException", LOG_PREFIX); + log.error("{}{}", LOG_PREFIX, wcre.toString()); + } + + } else { + log.error("{}Exception: {}", LOG_PREFIX, e.toString()); + } + }) + // ❗ 실제 비동기 실행 트리거 + .subscribe(); + + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception e: {}", e.toString()); + } + } + + @Async + public void asyncChangeBalance(String LOG_PREFIX, HashMap siteApiInfo, JSONObject data) { + String tranId = ""; + try { + tranId = data.getString("tranId"); + log.info(LOG_PREFIX+ "data.has(\"isData\"): " + data.has("isData")); + log.info(LOG_PREFIX+ "data.has(\"betKey\"): " + data.has("betKey")); + if(!data.has("isData")) { + data.put("isData", "N"); + } + if(!data.has("betKey")) { + data.put("betKey", tranId); + } + } catch(Exception e) {} + + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/json"); + header.add("Accept", "application/json"); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + header.set("Connection", "close"); + + final String baseCbUrl = siteApiInfo.get("siteCbUrl").toString().trim(); + log.info(LOG_PREFIX+ "Callback URL: " + baseCbUrl + "/changebalance"); + log.info(LOG_PREFIX+ "Body: " + data.toString()); + + try { + webClient.post() + .uri(baseCbUrl + "/changebalance") + .headers(h -> h.addAll(header)) + .bodyValue(data.toString()) + .exchangeToMono(resp -> resp.toEntity(String.class)) + .timeout(Duration.ofSeconds(2)) + .doOnSuccess(response -> { + if (response != null) { + log.info("{}Response HTTP Status: {}", LOG_PREFIX, response.getStatusCode().value()); + log.info("{}Response Body: {}", LOG_PREFIX, response.getBody()); + } + }) + .doOnError(e -> { + if (e instanceof WebClientRequestException wcre) { + Throwable cause = wcre.getCause(); + + if (hasCause(cause, io.netty.channel.ConnectTimeoutException.class) + || hasCause(cause, java.net.ConnectException.class)) { + + log.error("{}CONNECT_TIMEOUT", LOG_PREFIX); + log.error("{}{}", LOG_PREFIX, wcre.toString()); + + } else if (hasCause(cause, io.netty.handler.timeout.ReadTimeoutException.class) + || hasCause(cause, java.net.SocketTimeoutException.class)) { + + log.error("{}READ_TIMEOUT", LOG_PREFIX); + log.error("{}{}", LOG_PREFIX, wcre.toString()); + + } else { + log.error("{}WebClientRequestException", LOG_PREFIX); + log.error("{}{}", LOG_PREFIX, wcre.toString()); + } + + } else { + log.error("{}Exception: {}", LOG_PREFIX, e.toString()); + } + }) + // ❗ 실제 비동기 실행 트리거 + .subscribe(); + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception e: {}", e.toString()); + } + } + + @Async + public void asyncChangeBalanceSlot(String LOG_PREFIX, HashMap siteApiInfo, JSONObject data) { + String tranId = ""; + try { + tranId = data.getString("tranId"); + log.info(LOG_PREFIX+ "data.has(\"isData\"): " + data.has("isData")); + log.info(LOG_PREFIX+ "data.has(\"betKey\"): " + data.has("betKey")); + if(!data.has("isData")) { + data.put("isData", "N"); + } + if(!data.has("betKey")) { + data.put("betKey", tranId); + } + } catch(Exception e) {} + + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/json"); + header.add("Accept", "application/json"); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + header.set("Connection", "close"); + + final String baseCbUrl = siteApiInfo.get("siteCbUrl").toString().trim(); + log.info(LOG_PREFIX+ "Callback URL: " + baseCbUrl + "/changebalance/slot"); + log.info(LOG_PREFIX+ "Body: " + data.toString()); + + try { + webClient.post() + .uri(baseCbUrl + "/changebalance/slot") + .headers(h -> h.addAll(header)) + .bodyValue(data.toString()) + .exchangeToMono(resp -> resp.toEntity(String.class)) + .timeout(Duration.ofSeconds(2)) + .doOnSuccess(response -> { + if (response != null) { + log.info("{}Response HTTP Status: {}", LOG_PREFIX, response.getStatusCode().value()); + log.info("{}Response Body: {}", LOG_PREFIX, response.getBody()); + } + }) + .doOnError(e -> { + if (e instanceof WebClientRequestException wcre) { + Throwable cause = wcre.getCause(); + + if (hasCause(cause, io.netty.channel.ConnectTimeoutException.class) + || hasCause(cause, java.net.ConnectException.class)) { + + log.error("{}CONNECT_TIMEOUT", LOG_PREFIX); + log.error("{}{}", LOG_PREFIX, wcre.toString()); + + } else if (hasCause(cause, io.netty.handler.timeout.ReadTimeoutException.class) + || hasCause(cause, java.net.SocketTimeoutException.class)) { + + log.error("{}READ_TIMEOUT", LOG_PREFIX); + log.error("{}{}", LOG_PREFIX, wcre.toString()); + + } else { + log.error("{}WebClientRequestException", LOG_PREFIX); + log.error("{}{}", LOG_PREFIX, wcre.toString()); + } + + } else { + log.error("{}Exception: {}", LOG_PREFIX, e.toString()); + } + }) + // ❗ 실제 비동기 실행 트리거 + .subscribe(); + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception e: {}", e.toString()); + } + } + + @Async + public void asyncSportsRadarProc(String LOG_PREFIX, HashMap tranParam, net.sf.json.JSONObject data) { + log.info(LOG_PREFIX + "----- asyncSportsRadarProc START -----"); + HashMap sData = new HashMap<>(); + sData.put("tranId", tranParam.get("tranId").toString()); + sData.put("betId", tranParam.get("refId").toString()); + sData.put("jsonstr", data.toString()); + callBackDao.insertBetRadarLog(sData); + log.info(LOG_PREFIX + "----- asyncSportsRadarProc End -----"); + } + + private boolean hasCause(Throwable e, Class clazz) { + Throwable cause = e; + while (cause != null) { + if (clazz.isInstance(cause)) { + return true; + } + cause = cause.getCause(); + } + return false; + } + + @Async + public void asyncIssueLogSave(String LOG_PREFIX, net.sf.json.JSONObject requestBody, HashMap tranParam) { + log.info(LOG_PREFIX + "----- asyncIssueLogSave START -----"); + HashMap sData = new HashMap<>(); + sData.put("siteIdx", tranParam.get("siteIdx")); + sData.put("memberIdx", tranParam.get("memberIdx")); + sData.put("vendorIdx", tranParam.get("vendorIdx")); + sData.put("tranId", tranParam.get("tranId").toString()); + sData.put("refId", tranParam.get("refId").toString()); + sData.put("callBackType", tranParam.get("tranType").toString()); + sData.put("callBackReqBody", requestBody.toString()); + sData.put("callBackResBody", ""); + siteService.insertSiteCallBackLog(sData); + log.info(LOG_PREFIX + "----- asyncIssueLogSave End -----"); + } +} diff --git a/src/main/java/com/bb/service/BetRadarService.java b/src/main/java/com/bb/service/BetRadarService.java new file mode 100644 index 0000000..b846da8 --- /dev/null +++ b/src/main/java/com/bb/service/BetRadarService.java @@ -0,0 +1,11 @@ +package com.bb.service; + +import java.util.HashMap; + +public interface BetRadarService { + + String gameLaunch(String LOG_PREFIX, HashMap apiInfo); + + String getSportsSetting(String LOG_PREFIX, HashMap apiInfo); + +} diff --git a/src/main/java/com/bb/service/BetRadarServiceImpl.java b/src/main/java/com/bb/service/BetRadarServiceImpl.java new file mode 100644 index 0000000..1f46131 --- /dev/null +++ b/src/main/java/com/bb/service/BetRadarServiceImpl.java @@ -0,0 +1,138 @@ +package com.bb.service; + +import java.util.Collections; +import java.util.HashMap; + +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.ResourceAccessException; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.WebClientRequestException; + +import io.netty.channel.ConnectTimeoutException; +import io.netty.handler.timeout.ReadTimeoutException; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class BetRadarServiceImpl implements BetRadarService { + + @Autowired + WebClient webClient; + + @Override + public String gameLaunch(String LOG_PREFIX, HashMap apiInfo) { + LOG_PREFIX = LOG_PREFIX + "BET_RADAR::GAME_LAUNCH:::"; + String luanchUrl = ""; + String apiBaseUrl = apiInfo.get("apiBaseUrl").toString(); + String apiKey = apiInfo.get("apiKey").toString(); + String apiUsername = apiInfo.get("apiUsername").toString(); + String apiNickname = apiInfo.get("apiNickname").toString(); + String apiDevice = apiInfo.get("apiDevice").toString(); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.set("Authorization", "Bearer "+apiKey); + + try { + String launchUrl = apiBaseUrl + "/Game/GameLaunch"; + JSONObject launchBody = new JSONObject(); + launchBody.put("Owner", "SmCasino"); + launchBody.put("Provider", "SMSPORTS"); + launchBody.put("Account", apiUsername); + launchBody.put("Name", apiNickname); + launchBody.put("Device", apiDevice); + launchBody.put("isLobby", true); + launchBody.put("Gameid", "1"); + log.info(LOG_PREFIX+ "Url: " + launchUrl); + log.info(LOG_PREFIX+ "Headers: " + headers.toString()); + log.info(LOG_PREFIX+ "Params: " + launchBody.toString()); + + ResponseEntity launchRes = webClient.post() + .uri(launchUrl) + .headers(h -> h.addAll(headers)) + .bodyValue(launchBody.toString()) + .retrieve() + .toEntity(String.class) + .block(); + + JSONObject launchJson = null; + + if(launchRes != null && launchRes.getStatusCode() == HttpStatus.OK) { + log.info(LOG_PREFIX+ "response : " + launchRes.getBody()); + launchJson = new JSONObject(launchRes.getBody()); + luanchUrl = launchJson.getString("url"); + } + + } catch (WebClientRequestException e) { + Throwable cause = e.getCause(); + if (cause instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectException e: {}", e.toString()); + } else if (cause instanceof ReadTimeoutException) { + log.error(LOG_PREFIX+ "SocketTimeoutException e: {}", e.toString()); + } else { + log.error(LOG_PREFIX+ "ResourceAccessException e: {}", e.toString()); + } + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception e: {}", e.toString()); + } + + return luanchUrl; + } + + @Override + public String getSportsSetting(String LOG_PREFIX, HashMap apiInfo) { + LOG_PREFIX = LOG_PREFIX + "BET_RADAR::GET_SPORTS_SETTING:::"; + String url = ""; + String apiBaseUrl = apiInfo.get("apiBaseUrl").toString(); + String apiKey = apiInfo.get("apiKey").toString(); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.set("Authorization", "Bearer "+apiKey); + + try { + String launchUrl = apiBaseUrl + "/Agent/GetSportsSetting"; + log.info(LOG_PREFIX+ "Url: " + launchUrl); + log.info(LOG_PREFIX+ "Headers: " + headers.toString()); + + HttpEntity reqEntity = new HttpEntity(headers); + ResponseEntity launchRes = null; + JSONObject launchJson = null; + launchRes = webClient.get() + .uri(launchUrl) + .headers(h -> h.addAll(headers)) + .retrieve() + .toEntity(String.class) + .block(); + if(launchRes != null && launchRes.getStatusCode() == HttpStatus.OK) { + log.info(LOG_PREFIX+ "response : " + launchRes.getBody()); + launchJson = new JSONObject(launchRes.getBody()); + url = launchJson.getString("url"); + } + + } catch (WebClientRequestException e) { + Throwable cause = e.getCause(); + if (cause instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectException e: {}", e.toString()); + } else if (cause instanceof ReadTimeoutException) { + log.error(LOG_PREFIX+ "SocketTimeoutException e: {}", e.toString()); + } else { + log.error(LOG_PREFIX+ "ResourceAccessException e: {}", e.toString()); + } + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception e: {}", e.toString()); + } + + return url; + } +} diff --git a/src/main/java/com/bb/service/CallBackService.java b/src/main/java/com/bb/service/CallBackService.java new file mode 100644 index 0000000..ff14276 --- /dev/null +++ b/src/main/java/com/bb/service/CallBackService.java @@ -0,0 +1,14 @@ +package com.bb.service; + +import java.util.HashMap; + +import org.codehaus.jettison.json.JSONObject; + +public interface CallBackService { + + JSONObject getBalance(HashMap siteApiInfo, JSONObject parammember); + JSONObject changeBalance(String LOG_PREFIX, HashMap siteApiInfo, JSONObject debit); + JSONObject changeBalanceSlot(String LOG_PREFIX, HashMap siteApiInfo, JSONObject debit); + void insertCallBackErrLog(HashMap logParam); + +} diff --git a/src/main/java/com/bb/service/CallBackServiceImpl.java b/src/main/java/com/bb/service/CallBackServiceImpl.java new file mode 100644 index 0000000..5b9cf36 --- /dev/null +++ b/src/main/java/com/bb/service/CallBackServiceImpl.java @@ -0,0 +1,755 @@ +package com.bb.service; + +import java.util.HashMap; + +import org.codehaus.jettison.json.JSONException; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.WebClientRequestException; + +import com.bb.dao.CallBackDao; +import com.bb.util.StringUtils; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class CallBackServiceImpl implements CallBackService { + + @Autowired + private CallBackDao callBackDao; + + @Autowired + private WebClient webClient; // Inject WebClient + + @Override + public JSONObject getBalance(HashMap siteApiInfo, JSONObject parammember) { + + JSONObject res = new JSONObject(); + String siteId = siteApiInfo.get("siteId").toString(); + String memberId = siteApiInfo.get("memberId").toString(); + + HttpHeaders header = new HttpHeaders(); + header.set("Connection", "close"); + header.add("Content-Type", MediaType.APPLICATION_JSON_VALUE); + header.add("Accept", MediaType.APPLICATION_JSON_VALUE); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + + long startTimestamp = System.currentTimeMillis(); + final String LOG_PREFIX = "#-CMM::CB::getBalance::" + siteId + "::" + memberId + "::" + startTimestamp + ":::"; + final String baseCbUrl = siteApiInfo.get("siteCbUrl").toString().trim(); + + try { + parammember.put("requestAt", Long.toString(startTimestamp)); + log.info(LOG_PREFIX + "Callback URL: " + baseCbUrl + "/balance"); + log.info(LOG_PREFIX + "Body: " + parammember.toString()); + + /* + ResponseEntity responseEntity = webClient.post() + .uri(baseCbUrl + "/balance") + .headers(h -> h.addAll(header)) + .bodyValue(parammember.toString()) + .retrieve() + .onStatus(HttpStatusCode::isError, resp -> { + // 에러 상태 코드 처리 (선택사항) + return resp.bodyToMono(String.class) + .flatMap(body -> Mono.error(new RuntimeException("HTTP " + resp.statusCode() + " " + body))); + }) + .toEntity(String.class) + .block(); + */ + + ResponseEntity responseEntity = webClient.post().uri(baseCbUrl + "/balance") + .headers(h -> h.addAll(header)).bodyValue(parammember.toString()) + .exchangeToMono(resp -> resp.toEntity(String.class)).block(); + + int statusCode = responseEntity.getStatusCode().value(); + String responseBody = responseEntity.getBody(); + + long endTimestamp = System.currentTimeMillis(); + double diffTime = (startTimestamp - endTimestamp) / 1000.0; // 두 시간에 차 계산 + + log.info(LOG_PREFIX + "Response HTTP Status: " + statusCode); + log.info(LOG_PREFIX + "Response Body: " + responseBody); + + if (responseBody == null || responseBody.isEmpty()) { + log.error(LOG_PREFIX + "Received empty or null response body from WebClient."); + HashMap logParam = new HashMap(); + logParam.put("siteIdx", siteApiInfo.get("siteIdx")); + logParam.put("memberIdx", siteApiInfo.get("memberIdx")); + logParam.put("vendorIdx", null); + logParam.put("statusCode", statusCode); // Use actual HTTP status code + logParam.put("callBackType", "balance"); + logParam.put("callBackReqBody", parammember.toString()); + logParam.put("callBackResBody", "Empty or null response body"); + logParam.put("errorCode", "EMPTY_RESPONSE"); + logParam.put("errorMsg", "WebClient returned empty or null body for /balance"); + logParam.put("regDate", startTimestamp); + logParam.put("updDate", System.currentTimeMillis()); + callBackDao.insertCallBackErrLog(logParam); + return null; + } + + if (statusCode == 200) { + int resultCode = 0; + res = new JSONObject(responseBody); + + if (res.has("result_code")) { + resultCode = res.getInt("result_code"); + } else { + try { + resultCode = res.getInt("resultCode"); + } catch (Exception e) { + resultCode = -9; + } + } + + if (diffTime < -1.8) { + log.error(LOG_PREFIX + "잔액요청 응답시간(1.8초) 초과"); + HashMap logParam = new HashMap(); + logParam.put("siteIdx", siteApiInfo.get("siteIdx")); + logParam.put("memberIdx", siteApiInfo.get("memberIdx")); + logParam.put("vendorIdx", null); + logParam.put("statusCode", resultCode); + logParam.put("callBackType", "balance"); + logParam.put("callBackReqBody", parammember.toString()); + logParam.put("callBackResBody", res.toString()); + logParam.put("errorCode", "RESPONSE_TIME_OUT"); + logParam.put("errorMsg", "응답시간(1.8초) 초과"); + logParam.put("regDate", startTimestamp); + logParam.put("updDate", endTimestamp); + callBackDao.insertCallBackErrLog(logParam); + + return null; + } + + if (resultCode != 0) { + // 에러로그넣기 + HashMap logParam = new HashMap(); + logParam.put("siteIdx", siteApiInfo.get("siteIdx")); + logParam.put("memberIdx", siteApiInfo.get("memberIdx")); + logParam.put("vendorIdx", null); + logParam.put("statusCode", resultCode); + logParam.put("callBackType", "balance"); + logParam.put("callBackReqBody", parammember.toString()); + logParam.put("callBackResBody", res.toString()); + logParam.put("errorCode", "RESULT_CODE_ERR"); + logParam.put("errorMsg", res.toString()); + logParam.put("regDate", startTimestamp); + logParam.put("updDate", endTimestamp); + callBackDao.insertCallBackErrLog(logParam); + log.info(LOG_PREFIX + "code : {}", statusCode); + log.info(LOG_PREFIX + "body: {}", responseBody); + + return null; + } else { + + } + } else { + HashMap logParam = new HashMap(); + logParam.put("siteIdx", siteApiInfo.get("siteIdx")); + logParam.put("memberIdx", siteApiInfo.get("memberIdx")); + logParam.put("vendorIdx", null); + logParam.put("statusCode", statusCode); + logParam.put("callBackType", "balance"); + logParam.put("callBackReqBody", parammember.toString()); + logParam.put("callBackResBody", StringUtils.truncateBodyForDb(responseBody, 1000)); + logParam.put("errorCode", "HTTP_STATUS_CODE_ERR"); + logParam.put("errorMsg", statusCode + " Error"); + logParam.put("regDate", startTimestamp); + logParam.put("updDate", endTimestamp); + callBackDao.insertCallBackErrLog(logParam); + log.error(LOG_PREFIX + "code : {}", statusCode); + log.error(LOG_PREFIX + "body: {}", responseBody); + + return null; + } + + } catch (WebClientRequestException e) { // Catch WebClient specific network errors + long endTimestamp = System.currentTimeMillis(); + double diffTime = (startTimestamp - endTimestamp) / 1000.0; // 두 시간에 차 계산 + String errCode = ""; + String errMsg = ""; + + Throwable cause = e.getCause(); + if (hasCause(cause, io.netty.channel.ConnectTimeoutException.class) + || hasCause(cause, java.net.ConnectException.class)) { + log.error(LOG_PREFIX + "ConnectException e: CONNECT_TIMEOUT (3000ms)"); // WebClient config timeout is + // 3000ms + log.error(LOG_PREFIX + "ConnectException e: {}", e.toString()); + errCode = "CONNECT_TIMEOUT"; + errMsg = "ConnectException e: CONNECT_TIMEOUT (3000ms)"; + } else if (hasCause(cause, io.netty.handler.timeout.ReadTimeoutException.class) + || hasCause(cause, java.net.SocketTimeoutException.class)) { + log.error(LOG_PREFIX + "SocketTimeoutException e: READ_TIMEOUT (5000ms)"); + log.error(LOG_PREFIX + "SocketTimeoutException e: {}", e.toString()); + errCode = "READ_TIMEOUT"; + errMsg = "SocketTimeoutException e: READ_TIMEOUT (5000ms)"; + } else { + log.error(LOG_PREFIX + "WebClientRequestException e: 기타 네트워크 예외 발생 발생!!!"); + log.error(LOG_PREFIX + "WebClientRequestException e: {}", e.toString()); + errCode = "NETWORK_ERROR"; + errMsg = "WebClientRequestException e: 기타 네트워크 예외 발생 발생!!!"; + } + + HashMap logParam = new HashMap(); + logParam.put("siteIdx", siteApiInfo.get("siteIdx")); + logParam.put("memberIdx", siteApiInfo.get("memberIdx")); + logParam.put("vendorIdx", null); + logParam.put("statusCode", null); + logParam.put("callBackType", "balance"); + logParam.put("callBackReqBody", parammember.toString()); + logParam.put("callBackResBody", baseCbUrl + "/balance" + " > 실패"); + logParam.put("errorCode", errCode); + logParam.put("errorMsg", errMsg); + logParam.put("regDate", startTimestamp); + logParam.put("updDate", endTimestamp); + callBackDao.insertCallBackErrLog(logParam); + + res = null; + } catch (Exception e) { // General exception catch + long endTimestamp = System.currentTimeMillis(); + double diffTime = (startTimestamp - endTimestamp) / 1000.0; // 두 시간에 차 계산 + + log.error(LOG_PREFIX + "Exception e: {}", e.toString()); + e.printStackTrace(); + + HashMap logParam = new HashMap(); + logParam.put("siteIdx", siteApiInfo.get("siteIdx")); + logParam.put("memberIdx", siteApiInfo.get("memberIdx")); + logParam.put("vendorIdx", null); + logParam.put("statusCode", null); + logParam.put("callBackType", "balance"); + logParam.put("callBackReqBody", parammember.toString()); + logParam.put("callBackResBody", baseCbUrl + "/balance" + " > 실패"); + logParam.put("errorCode", "GENERAL_ERROR"); + logParam.put("errorMsg", "Exception e: " + e.toString()); + logParam.put("regDate", startTimestamp); + logParam.put("updDate", endTimestamp); + callBackDao.insertCallBackErrLog(logParam); + + res = null; + } + + return res; + } + + @Override + public JSONObject changeBalance(String LOG_PREFIX, HashMap siteApiInfo, JSONObject data) { + + JSONObject res = new JSONObject(); + String siteId = siteApiInfo.get("siteId").toString(); + String memberId = siteApiInfo.get("memberId").toString(); + String tranId = ""; + final String baseCbUrl = siteApiInfo.get("siteCbUrl").toString().trim(); + + try { + tranId = data.getString("tranId"); + log.info(LOG_PREFIX + "data.has(\"isData\"): " + data.has("isData")); + log.info(LOG_PREFIX + "data.has(\"betKey\"): " + data.has("betKey")); + if (!data.has("isData")) { + data.put("isData", "N"); + } + if (!data.has("betKey")) { + data.put("betKey", tranId); + } + } catch (Exception e) { + } + + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", MediaType.APPLICATION_JSON_VALUE); + header.add("Accept", MediaType.APPLICATION_JSON_VALUE); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + header.set("Connection", "close"); + + // 요청시간 + long startTimestamp = System.currentTimeMillis(); + try { + log.info(LOG_PREFIX + "Callback URL: " + baseCbUrl + "/changebalance"); + log.info(LOG_PREFIX + "Body: " + data.toString()); + /* + ResponseEntity responseEntity = webClient.post() + .uri(baseCbUrl + "/changebalance") + .headers(h -> h.addAll(header)) + .bodyValue(data.toString()) + .retrieve() + .toEntity(String.class) + .block(); + */ + ResponseEntity responseEntity = webClient.post().uri(baseCbUrl + "/changebalance") + .headers(h -> h.addAll(header)).bodyValue(data.toString()) + .exchangeToMono(resp -> resp.toEntity(String.class)).block(); + + int statusCode = responseEntity.getStatusCode().value(); + String responseBody = responseEntity.getBody(); // 정상적으로 바디 읽기 가능 + + long endTimestamp = System.currentTimeMillis(); + double diffTime = (startTimestamp - endTimestamp) / 1000.0; // 두 시간에 차 계산 + + if (responseBody == null || responseBody.isEmpty()) { + log.error(LOG_PREFIX + "Received empty or null response body from WebClient."); + HashMap logParam = new HashMap(); + logParam.put("siteIdx", siteApiInfo.get("siteIdx")); + logParam.put("memberIdx", siteApiInfo.get("memberIdx")); + logParam.put("vendorIdx", data.get("vendorIdx")); + logParam.put("statusCode", statusCode); + logParam.put("callBackType", data.get("tranType").toString()); + logParam.put("tranId", tranId); + logParam.put("callBackReqBody", data.toString()); + logParam.put("callBackResBody", "Empty or null response body"); + logParam.put("errorCode", "EMPTY_RESPONSE"); + logParam.put("errorMsg", "WebClient returned empty or null body for /changebalance"); + logParam.put("regDate", startTimestamp); + logParam.put("updDate", System.currentTimeMillis()); + callBackDao.insertCallBackErrLog(logParam); + + res = new JSONObject(); + res.put("result_code", -9999); + res.put("error_msg", "EMPTY_RESPONSE"); + + return res; + } + + if (statusCode == 200) { + int resultCode = 0; + res = new JSONObject(responseBody); + if (res.has("result_code")) { + resultCode = res.getInt("result_code"); + } else { + try { + resultCode = res.getInt("resultCode"); + } catch (Exception e) { + resultCode = -9; + } + } + + if (diffTime < -1.8) { + log.error(LOG_PREFIX + "응답시간(1.8초) 초과"); + HashMap logParam = new HashMap(); + logParam.put("siteIdx", siteApiInfo.get("siteIdx")); + logParam.put("memberIdx", siteApiInfo.get("memberIdx")); + logParam.put("vendorIdx", data.get("vendorIdx")); + logParam.put("statusCode", resultCode); + logParam.put("callBackType", data.get("tranType").toString()); + logParam.put("tranId", tranId); + logParam.put("callBackReqBody", data.toString()); + logParam.put("callBackResBody", res.toString()); + logParam.put("errorCode", "RESPONSE_TIME_OUT"); + logParam.put("errorMsg", "응답시간(1.8초) 초과"); + logParam.put("regDate", startTimestamp); + logParam.put("updDate", endTimestamp); + callBackDao.insertCallBackErrLog(logParam); + + res = new JSONObject(); + res.put("result_code", -9999); + res.put("error_msg", "RESPONSE_TIME_OUT"); + + return res; + } + + if (resultCode != 0 && resultCode != 98) { + HashMap logParam = new HashMap(); + logParam.put("siteIdx", siteApiInfo.get("siteIdx")); + logParam.put("memberIdx", siteApiInfo.get("memberIdx")); + logParam.put("vendorIdx", data.get("vendorIdx")); + logParam.put("statusCode", resultCode); + logParam.put("callBackType", data.get("tranType").toString()); + logParam.put("tranId", tranId); + logParam.put("callBackReqBody", data.toString()); + logParam.put("callBackResBody", res.toString()); + logParam.put("errorCode", "RESULT_CODE_ERR"); + logParam.put("errorMsg", res.toString()); + logParam.put("regDate", startTimestamp); + logParam.put("updDate", endTimestamp); + callBackDao.insertCallBackErrLog(logParam); + + // 에러로그넣기 + log.info(LOG_PREFIX + "changeBalance param : {}", data.toString()); + log.info(LOG_PREFIX + "changeBalance url : {}", baseCbUrl + "/changebalance"); + log.info(LOG_PREFIX + "changeBalance code : {}", statusCode); + log.info(LOG_PREFIX + "changeBalance body: {}", responseBody); + } + } else { + HashMap logParam = new HashMap(); + logParam.put("siteIdx", siteApiInfo.get("siteIdx")); + logParam.put("memberIdx", siteApiInfo.get("memberIdx")); + logParam.put("vendorIdx", data.get("vendorIdx")); + logParam.put("statusCode", statusCode); + logParam.put("callBackType", data.get("tranType").toString()); + logParam.put("tranId", tranId); + logParam.put("callBackReqBody", data.toString()); + logParam.put("callBackResBody", StringUtils.truncateBodyForDb(responseBody, 1000)); + logParam.put("errorCode", "HTTP_STATUS_CODE_ERR"); + logParam.put("errorMsg", statusCode + " Error"); + logParam.put("regDate", startTimestamp); + logParam.put("updDate", endTimestamp); + callBackDao.insertCallBackErrLog(logParam); + + res = new JSONObject(); + res.put("result_code", -9999); + res.put("error_msg", "HTTP_STATUS_CODE_ERR"); + + return res; + } + + } catch (WebClientRequestException e) { + long endTimestamp = System.currentTimeMillis(); + double diffTime = (startTimestamp - endTimestamp) / 1000.0; // 두 시간에 차 계산 + String errCode = ""; + String errMsg = ""; + + Throwable cause = e.getCause(); + if (hasCause(cause, io.netty.channel.ConnectTimeoutException.class) + || hasCause(cause, java.net.ConnectException.class)) { + log.error(LOG_PREFIX + "ConnectException e: CONNECT_TIMEOUT (3000ms)"); + log.error(LOG_PREFIX + "ConnectException e: {}", e.toString()); + errCode = "CONNECT_TIMEOUT"; + errMsg = "ConnectException e: CONNECT_TIMEOUT (3000ms)"; + } else if (hasCause(cause, io.netty.handler.timeout.ReadTimeoutException.class) + || hasCause(cause, java.net.SocketTimeoutException.class)) { + log.error(LOG_PREFIX + "SocketTimeoutException e: READ_TIMEOUT (5000ms)"); + log.error(LOG_PREFIX + "SocketTimeoutException e: {}", e.toString()); + errCode = "READ_TIMEOUT"; + errMsg = "SocketTimeoutException e: READ_TIMEOUT (5000ms)"; + } else { + log.error(LOG_PREFIX + "WebClientRequestException e: 기타 네트워크 예외 발생 발생!!!"); + log.error(LOG_PREFIX + "WebClientRequestException e: {}", e.toString()); + errCode = "NETWORK_ERROR"; + errMsg = "WebClientRequestException e: 기타 네트워크 예외 발생 발생!!!"; + } + + HashMap logParam = new HashMap(); + logParam.put("siteIdx", siteApiInfo.get("siteIdx")); + logParam.put("memberIdx", siteApiInfo.get("memberIdx")); + logParam.put("vendorIdx", null); + logParam.put("statusCode", null); + try { + logParam.put("callBackType", data.get("tranType").toString()); + } catch (Exception de) { + logParam.put("callBackType", "changebalance"); + } + logParam.put("tranId", tranId); + logParam.put("callBackReqBody", data.toString()); + logParam.put("callBackResBody", baseCbUrl + "/changebalance" + " > 실패"); + logParam.put("errorCode", errCode); + logParam.put("errorMsg", errMsg); + logParam.put("regDate", startTimestamp); + logParam.put("updDate", endTimestamp); + callBackDao.insertCallBackErrLog(logParam); + + try { + res.put("result_code", -9999); + res.put("error_msg", errMsg); + } catch (JSONException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + } catch (Exception e) { + long endTimestamp = System.currentTimeMillis(); + double diffTime = (startTimestamp - endTimestamp) / 1000.0; // 두 시간에 차 계산 + + log.error(LOG_PREFIX + "Exception e: {}", e.toString()); + e.printStackTrace(); + + HashMap logParam = new HashMap(); + logParam.put("siteIdx", siteApiInfo.get("siteIdx")); + logParam.put("memberIdx", siteApiInfo.get("memberIdx")); + logParam.put("vendorIdx", null); + logParam.put("statusCode", null); + try { + logParam.put("callBackType", data.get("tranType").toString()); + } catch (Exception de) { + logParam.put("callBackType", "changebalance"); + } + logParam.put("tranId", tranId); + logParam.put("callBackReqBody", data.toString()); + logParam.put("callBackResBody", baseCbUrl + "/changebalance" + " > 실패"); + logParam.put("regDate", startTimestamp); + logParam.put("updDate", endTimestamp); + callBackDao.insertCallBackErrLog(logParam); + + try { + res.put("result_code", -9999); + res.put("error_msg", "GENERAL_ERROR"); + } catch (JSONException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + } + + return res; + } + + + @Override + public JSONObject changeBalanceSlot(String LOG_PREFIX, HashMap siteApiInfo, JSONObject data) { + + JSONObject res = new JSONObject(); + String siteId = siteApiInfo.get("siteId").toString(); + String memberId = siteApiInfo.get("memberId").toString(); + String tranId = ""; + final String baseCbUrl = siteApiInfo.get("siteCbUrl").toString().trim(); + + try { + tranId = data.getString("tranId"); + log.info(LOG_PREFIX + "data.has(\"isData\"): " + data.has("isData")); + log.info(LOG_PREFIX + "data.has(\"betKey\"): " + data.has("betKey")); + if (!data.has("isData")) { + data.put("isData", "N"); + } + if (!data.has("betKey")) { + data.put("betKey", tranId); + } + } catch (Exception e) { + } + + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", MediaType.APPLICATION_JSON_VALUE); + header.add("Accept", MediaType.APPLICATION_JSON_VALUE); + header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"); + header.set("Connection", "close"); + // 요청시간 + long startTimestamp = System.currentTimeMillis(); + log.info(LOG_PREFIX + "Callback URL: " + baseCbUrl + "/changebalance/slot"); + log.info(LOG_PREFIX + "Body: " + data.toString()); + + try { + /* + ResponseEntity responseEntity = webClient.post() + .uri(baseCbUrl + "/changebalance/slot") + .headers(h -> h.addAll(header)) + .bodyValue(data.toString()) + .retrieve().toEntity(String.class) + .block(); + */ + ResponseEntity responseEntity = webClient.post().uri(baseCbUrl + "/changebalance/slot") + .headers(h -> h.addAll(header)).bodyValue(data.toString()) + .exchangeToMono(resp -> resp.toEntity(String.class)).block(); + + int statusCode = responseEntity.getStatusCode().value(); + String responseBody = responseEntity.getBody(); // 정상적으로 바디 읽기 가능 + + long endTimestamp = System.currentTimeMillis(); + double diffTime = (startTimestamp - endTimestamp) / 1000.0; // 두 시간에 차 계산 + + int resultCode = 0; + + if (responseBody == null || responseBody.isEmpty()) { + log.error(LOG_PREFIX + "Received empty or null response body from WebClient."); + HashMap logParam = new HashMap(); + logParam.put("siteIdx", siteApiInfo.get("siteIdx")); + logParam.put("memberIdx", siteApiInfo.get("memberIdx")); + logParam.put("vendorIdx", data.get("vendorIdx")); + logParam.put("statusCode", statusCode); + try { + logParam.put("callBackType", data.get("tranType").toString()); + } catch (Exception de) { + logParam.put("callBackType", "changeBalanceSlot"); + } + logParam.put("tranId", tranId); + logParam.put("callBackReqBody", data.toString()); + logParam.put("callBackResBody", "Empty or null response body"); + logParam.put("errorCode", "EMPTY_RESPONSE"); + logParam.put("errorMsg", "WebClient returned empty or null body for /changebalance/slot"); + logParam.put("regDate", startTimestamp); + logParam.put("updDate", System.currentTimeMillis()); + callBackDao.insertCallBackErrLog(logParam); + + res = new JSONObject(); + res.put("result_code", -9999); + res.put("error_msg", "EMPTY_RESPONSE"); + + return res; + } else { + res = new JSONObject(responseBody); + if (res.has("result_code")) { + resultCode = res.getInt("result_code"); + } else { + resultCode = res.getInt("resultCode"); + } + } + + if (statusCode == 200) { + if (diffTime < -1.8) { + log.error(LOG_PREFIX + "응답시간(1.8초) 초과"); + HashMap logParam = new HashMap(); + logParam.put("siteIdx", siteApiInfo.get("siteIdx")); + logParam.put("memberIdx", siteApiInfo.get("memberIdx")); + logParam.put("vendorIdx", data.get("vendorIdx")); + logParam.put("statusCode", resultCode); + logParam.put("callBackType", data.get("tranType").toString()); + logParam.put("tranId", tranId); + logParam.put("callBackReqBody", data.toString()); + logParam.put("callBackResBody", res.toString()); + logParam.put("errorCode", "RESPONSE_TIME_OUT"); + logParam.put("errorMsg", "응답시간(1.8초) 초과"); + logParam.put("regDate", startTimestamp); + logParam.put("updDate", endTimestamp); + callBackDao.insertCallBackErrLog(logParam); + + res = new JSONObject(); + res.put("result_code", -9999); + res.put("error_msg", "RESPONSE_TIME_OUT"); + + return res; + } + + if (resultCode != 0 && resultCode != 98) { + HashMap logParam = new HashMap(); + logParam.put("siteIdx", siteApiInfo.get("siteIdx")); + logParam.put("memberIdx", siteApiInfo.get("memberIdx")); + logParam.put("vendorIdx", data.get("vendorIdx")); + logParam.put("statusCode", resultCode); + logParam.put("callBackType", data.get("tranType").toString()); + logParam.put("tranId", tranId); + logParam.put("callBackReqBody", data.toString()); + logParam.put("callBackResBody", res.toString()); + logParam.put("errorCode", "RESULT_CODE_ERR"); + logParam.put("errorMsg", res.toString()); + logParam.put("regDate", startTimestamp); + logParam.put("updDate", endTimestamp); + callBackDao.insertCallBackErrLog(logParam); + + // 에러로그넣기 + log.info(LOG_PREFIX + "changeBalanceSlot param : {}", data.toString()); + log.info(LOG_PREFIX + "changeBalanceSlot url : {}", baseCbUrl + "/changebalance/slot"); + log.info(LOG_PREFIX + "changeBalanceSlot code : {}", statusCode); + log.info(LOG_PREFIX + "changeBalanceSlot body: {}", responseBody); + } + } else { + HashMap logParam = new HashMap(); + logParam.put("siteIdx", siteApiInfo.get("siteIdx")); + logParam.put("memberIdx", siteApiInfo.get("memberIdx")); + logParam.put("vendorIdx", data.get("vendorIdx")); + logParam.put("statusCode", statusCode); + logParam.put("callBackType", data.get("tranType").toString()); + logParam.put("tranId", tranId); + logParam.put("callBackReqBody", data.toString()); + logParam.put("callBackResBody", StringUtils.truncateBodyForDb(responseBody, 1000)); + logParam.put("errorCode", "HTTP_STATUS_CODE_ERR"); + logParam.put("errorMsg", statusCode + " Error"); + logParam.put("regDate", startTimestamp); + logParam.put("updDate", endTimestamp); + callBackDao.insertCallBackErrLog(logParam); + + res = new JSONObject(); + res.put("result_code", -9999); + res.put("error_msg", "HTTP_STATUS_CODE_ERR"); + + return res; + } + + } catch (WebClientRequestException e) { + long endTimestamp = System.currentTimeMillis(); + double diffTime = (startTimestamp - endTimestamp) / 1000.0; // 두 시간에 차 계산 + String errCode = ""; + String errMsg = ""; + + Throwable cause = e.getCause(); + if (hasCause(cause, io.netty.channel.ConnectTimeoutException.class) + || hasCause(cause, java.net.ConnectException.class)) { + log.error(LOG_PREFIX + "ConnectException e: CONNECT_TIMEOUT (3000ms)"); + log.error(LOG_PREFIX + "ConnectException e: {}", e.toString()); + errCode = "CONNECT_TIMEOUT"; + errMsg = "ConnectException e: CONNECT_TIMEOUT (3000ms)"; + } else if (hasCause(cause, io.netty.handler.timeout.ReadTimeoutException.class) + || hasCause(cause, java.net.SocketTimeoutException.class)) { + log.error(LOG_PREFIX + "SocketTimeoutException e: READ_TIMEOUT (5000ms)"); + log.error(LOG_PREFIX + "SocketTimeoutException e: {}", e.toString()); + errCode = "READ_TIMEOUT"; + errMsg = "SocketTimeoutException e: READ_TIMEOUT (5000ms)"; + } else { + log.error(LOG_PREFIX + "WebClientRequestException e: 기타 네트워크 예외 발생 발생!!!"); + log.error(LOG_PREFIX + "WebClientRequestException e: {}", e.toString()); + errCode = "NETWORK_ERROR"; + errMsg = "WebClientRequestException e: 기타 네트워크 예외 발생 발생!!!"; + } + + HashMap logParam = new HashMap(); + logParam.put("siteIdx", siteApiInfo.get("siteIdx")); + logParam.put("memberIdx", siteApiInfo.get("memberIdx")); + logParam.put("vendorIdx", null); + logParam.put("statusCode", null); + try { + logParam.put("callBackType", data.get("tranType").toString()); + } catch (Exception de) { + logParam.put("callBackType", "changeBalanceSlot"); + } + logParam.put("tranId", tranId); + logParam.put("callBackReqBody", data.toString()); + logParam.put("callBackResBody", baseCbUrl + "/changebalance/slot" + " > 실패"); + logParam.put("errorCode", errCode); + logParam.put("errorMsg", errMsg); + logParam.put("regDate", startTimestamp); + logParam.put("updDate", endTimestamp); + callBackDao.insertCallBackErrLog(logParam); + + try { + res.put("result_code", -9999); + res.put("error_msg", errMsg); + } catch (JSONException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + } catch (Exception e) { + long endTimestamp = System.currentTimeMillis(); + double diffTime = (startTimestamp - endTimestamp) / 1000.0; // 두 시간에 차 계산 + + log.error(LOG_PREFIX + "Exception e: {}", e.toString()); + e.printStackTrace(); + + HashMap logParam = new HashMap(); + logParam.put("siteIdx", siteApiInfo.get("siteIdx")); + logParam.put("memberIdx", siteApiInfo.get("memberIdx")); + logParam.put("vendorIdx", null); + logParam.put("statusCode", null); + try { + logParam.put("callBackType", data.get("tranType").toString()); + } catch (Exception de) { + logParam.put("callBackType", "changeBalanceSlot"); + } + logParam.put("tranId", tranId); + logParam.put("callBackReqBody", data.toString()); + logParam.put("callBackResBody", baseCbUrl + "/changebalance/slot" + " > 실패"); + logParam.put("regDate", startTimestamp); + logParam.put("updDate", endTimestamp); + callBackDao.insertCallBackErrLog(logParam); + + try { + res.put("result_code", -9999); + res.put("error_msg", "GENERAL_ERROR"); + } catch (JSONException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + } + + return res; + } + + @Override + public void insertCallBackErrLog(HashMap logParam) { + // TODO Auto-generated method stub + callBackDao.insertCallBackErrLog(logParam); + } + + private boolean hasCause(Throwable e, Class clazz) { + Throwable cause = e; + while (cause != null) { + if (clazz.isInstance(cause)) { + return true; + } + cause = cause.getCause(); + } + return false; + } + +} \ No newline at end of file diff --git a/src/main/java/com/bb/service/CallBackTestService.java b/src/main/java/com/bb/service/CallBackTestService.java new file mode 100644 index 0000000..7a95561 --- /dev/null +++ b/src/main/java/com/bb/service/CallBackTestService.java @@ -0,0 +1,14 @@ +package com.bb.service; + +import org.codehaus.jettison.json.JSONObject; + +public interface CallBackTestService { + + JSONObject getBalance(String LOG_PREFIX, String siteCallbackUrl, JSONObject param); + JSONObject changeBalance(String LOG_PREFIX, String siteCallbackUrl, JSONObject param); + JSONObject changeBalanceSlot(String LOG_PREFIX, String siteCallbackUrl, JSONObject param); + + JSONObject getTestBalance(String LOG_PREFIX, String memberId, String token, String authorization); + JSONObject getTestChangeBalance(String LOG_PREFIX, String memberId, String token, String authorization); + JSONObject getTestChangeBalanceSlot(String LOG_PREFIX, String memberId, String token, String authorization); +} diff --git a/src/main/java/com/bb/service/CallBackTestServiceImpl.java b/src/main/java/com/bb/service/CallBackTestServiceImpl.java new file mode 100644 index 0000000..f70901c --- /dev/null +++ b/src/main/java/com/bb/service/CallBackTestServiceImpl.java @@ -0,0 +1,504 @@ +package com.bb.service; + +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.Collections; + +import org.codehaus.jettison.json.JSONException; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.util.UriComponentsBuilder; + +import io.netty.handler.timeout.ReadTimeoutException; +import io.netty.handler.timeout.WriteTimeoutException; +import java.net.ConnectException; +import java.net.SocketTimeoutException; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class CallBackTestServiceImpl implements CallBackTestService { + + @Autowired + private WebClient webClient; + + private HttpHeaders getHeader() { + HttpHeaders header = new HttpHeaders(); + header.setContentType(MediaType.APPLICATION_JSON); + header.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + header.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8"))); + + return header; + } + + @Override + public JSONObject getBalance(String LOG_PREFIX, String siteCallbackUrl, JSONObject param) { + + JSONObject response = new JSONObject(); + String methodLogPrefix = LOG_PREFIX + "getBalance::"; + long startTimestamp = System.currentTimeMillis(); + + try { + HttpHeaders header = getHeader(); + param.put("requestAt", Long.toString(startTimestamp)); + log.info(methodLogPrefix+ "request: {}", param.toString()); + + String responseBody = this.webClient.post() + .uri(siteCallbackUrl + "/balance") + .headers(headers -> headers.addAll(header)) + .bodyValue(param.toString()) + .exchangeToMono(clientResponse -> { + if (clientResponse.statusCode().is2xxSuccessful()) { + return clientResponse.bodyToMono(String.class); + } else { + return clientResponse.bodyToMono(String.class) + .map(body -> { + try { + JSONObject errorResponse = new JSONObject(); + errorResponse.put("result_code", -99); + errorResponse.put("error_msg", "HTTP_STATUS_CODE_ERR > " + clientResponse.statusCode().value()); + return errorResponse.toString(); + } catch (JSONException e) { + log.error(methodLogPrefix + "Error parsing error response body: {}", e.getMessage()); + return "{\"result_code\":-99, \"error_msg\":\"HTTP_STATUS_CODE_ERR and parsing error\"}"; + } + }); + } + }) + .onErrorResume(ConnectException.class, e -> { + log.error(methodLogPrefix+ "ConnectException e: CONNECT_TIMEOUT (3000ms)"); // WebClient config has 3000ms connect timeout + log.error(methodLogPrefix+ "ConnectException e: {}", e.toString()); + return monoErrorResponse("-99", "CONNECT_TIMEOUT (3000ms)"); + }) + .onErrorResume(ReadTimeoutException.class, e -> { + log.error(methodLogPrefix+ "SocketTimeoutException e: READ_TIMEOUT (5000ms)"); // WebClient config has 5000ms read timeout + log.error(methodLogPrefix+ "SocketTimeoutException e: {}", e.toString()); + return monoErrorResponse("-99", "READ_TIMEOUT (5000ms)"); + }) + .onErrorResume(SocketTimeoutException.class, e -> { // Fallback for other SocketTimeoutException + log.error(methodLogPrefix+ "SocketTimeoutException e: READ_TIMEOUT (5000ms)"); + log.error(methodLogPrefix+ "SocketTimeoutException e: {}", e.toString()); + return monoErrorResponse("-99", "READ_TIMEOUT (5000ms)"); + }) + .onErrorResume(Exception.class, e -> { + log.error(methodLogPrefix+ "Exception e: {}", e.toString()); + return monoErrorResponse("-99", "GENERAL_ERROR"); + }) + .block(); // Synchronous call + + long endTimestamp = System.currentTimeMillis(); + double diffTime = (endTimestamp - startTimestamp)/1000.0; //두 시간에 차 계산 + + if (responseBody != null) { + response = new JSONObject(responseBody); + + if (response.has("result_code") == false) { + try { + int resultCode = response.getInt("resultCode"); + response.put("result_code", resultCode); + response.remove("resultCode"); + } catch(Exception e) { + response.put("result_code", -9); + response.put("error_msg", "Not found result_code"); + } + } + + if(diffTime > 0.25) { + log.error(methodLogPrefix+ "잔액요청 응답시간(250ms) 초과"); + response.put("result_code", -99); + response.put("error_msg", "RESPONSE_TIME_OUT [잔액요청 응답시간(250ms) 초과]"); + } + } else { + response.put("result_code", -99); + response.put("error_msg", "EMPTY_RESPONSE_BODY"); + } + + response.put("timeMs", (endTimestamp - startTimestamp)); + + } catch (JSONException e) { + long endTimestamp = System.currentTimeMillis(); + log.error(methodLogPrefix+ "JSONException e: {}", e.toString()); + e.printStackTrace(); + try { + response.put("result_code", -99); + response.put("error_msg", "JSON_PARSE_ERROR"); + response.put("timeMs", (endTimestamp - startTimestamp)); + } catch (JSONException e1) { + e1.printStackTrace(); + } + } catch (Exception e) { // General catch for any other unexpected exceptions + long endTimestamp = System.currentTimeMillis(); + log.error(methodLogPrefix+ "Exception e: {}", e.toString()); + e.printStackTrace(); + try { + response.put("result_code", -99); + response.put("error_msg", "GENERAL_ERROR"); + response.put("timeMs", (endTimestamp - startTimestamp)); + } catch (JSONException e1) { + e1.printStackTrace(); + } + } + + log.info(methodLogPrefix+ "response: {}", response.toString()); + return response; + } + + // Helper method to create error Mono + private reactor.core.publisher.Mono monoErrorResponse(String resultCode, String errorMessage) { + JSONObject errorJson = new JSONObject(); + try { + errorJson.put("result_code", Integer.parseInt(resultCode)); + errorJson.put("error_msg", errorMessage); + } catch (JSONException e) { + log.error("Error creating error JSON: {}", e.getMessage()); + } + return reactor.core.publisher.Mono.just(errorJson.toString()); + } + + @Override + public JSONObject changeBalance(String LOG_PREFIX, String siteCallbackUrl, JSONObject param) { + + JSONObject response = new JSONObject(); + String methodLogPrefix = LOG_PREFIX + "changeBalance::"; + long startTimestamp = System.currentTimeMillis(); + log.info(methodLogPrefix+ "request: {}", param.toString()); + + try { + HttpHeaders header = getHeader(); + + String responseBody = this.webClient.post() + .uri(siteCallbackUrl + "/changebalance") + .headers(headers -> headers.addAll(header)) + .bodyValue(param.toString()) + .exchangeToMono(clientResponse -> { + if (clientResponse.statusCode().is2xxSuccessful()) { + return clientResponse.bodyToMono(String.class); + } else { + return clientResponse.bodyToMono(String.class) + .map(body -> { + try { + JSONObject errorResponse = new JSONObject(); + errorResponse.put("result_code", -99); + errorResponse.put("error_msg", "HTTP_STATUS_CODE_ERR > " + clientResponse.statusCode().value()); + return errorResponse.toString(); + } catch (JSONException e) { + log.error(methodLogPrefix + "Error parsing error response body: {}", e.getMessage()); + return "{\"result_code\":-99, \"error_msg\":\"HTTP_STATUS_CODE_ERR and parsing error\"}"; + } + }); + } + }) + .onErrorResume(ConnectException.class, e -> { + log.error(methodLogPrefix+ "ConnectException e: CONNECT_TIMEOUT (3000ms)"); + log.error(methodLogPrefix+ "ConnectException e: {}", e.toString()); + return monoErrorResponse("-99", "CONNECT_TIMEOUT (3000ms)"); + }) + .onErrorResume(ReadTimeoutException.class, e -> { + log.error(methodLogPrefix+ "SocketTimeoutException e: READ_TIMEOUT (5000ms)"); + log.error(methodLogPrefix+ "SocketTimeoutException e: {}", e.toString()); + return monoErrorResponse("-99", "READ_TIMEOUT (5000ms)"); + }) + .onErrorResume(SocketTimeoutException.class, e -> { + log.error(methodLogPrefix+ "SocketTimeoutException e: READ_TIMEOUT (5000ms)"); + log.error(methodLogPrefix+ "SocketTimeoutException e: {}", e.toString()); + return monoErrorResponse("-99", "READ_TIMEOUT (5000ms)"); + }) + .onErrorResume(Exception.class, e -> { + log.error(methodLogPrefix+ "Exception e: {}", e.toString()); + return monoErrorResponse("-99", "GENERAL_ERROR"); + }) + .block(); // Synchronous call + + long endTimestamp = System.currentTimeMillis(); + double diffTime = (endTimestamp - startTimestamp)/1000.0; + + if (responseBody != null) { + response = new JSONObject(responseBody); + + if (response.has("result_code") == false) { + try { + int resultCode = response.getInt("resultCode"); + response.put("result_code", resultCode); + response.remove("resultCode"); + } catch(Exception e) { + response.put("result_code", -9); + response.put("error_msg", "Not found result_code"); + } + } + + if(diffTime > 0.25) { + log.error(methodLogPrefix+ "잔액변경 응답시간(250ms) 초과"); + response.put("result_code", -99); + response.put("error_msg", "RESPONSE_TIME_OUT [잔액변경 응답시간(250ms) 초과]"); + } + } else { + response.put("result_code", -99); + response.put("error_msg", "EMPTY_RESPONSE_BODY"); + } + + response.put("timeMs", (endTimestamp - startTimestamp)); + + } catch (JSONException e) { + long endTimestamp = System.currentTimeMillis(); + log.error(methodLogPrefix+ "JSONException e: {}", e.toString()); + e.printStackTrace(); + try { + response.put("result_code", -99); + response.put("error_msg", "JSON_PARSE_ERROR"); + response.put("timeMs", (endTimestamp - startTimestamp)); + } catch (JSONException e1) { + e1.printStackTrace(); + } + } catch (Exception e) { + long endTimestamp = System.currentTimeMillis(); + log.error(methodLogPrefix+ "Exception e: {}", e.toString()); + e.printStackTrace(); + try { + response.put("result_code", -99); + response.put("error_msg", "GENERAL_ERROR"); + response.put("timeMs", (endTimestamp - startTimestamp)); + } catch (JSONException e1) { + e1.printStackTrace(); + } + } + + log.info(methodLogPrefix+ "response: {}", response.toString()); + return response; + } + + @Override + public JSONObject changeBalanceSlot(String LOG_PREFIX, String siteCallbackUrl, JSONObject param) { + + JSONObject response = new JSONObject(); + String methodLogPrefix = LOG_PREFIX + "changeBalanceSlot::"; + long startTimestamp = System.currentTimeMillis(); + log.info(methodLogPrefix+ "request: {}", param.toString()); + + try { + HttpHeaders header = getHeader(); + + String responseBody = this.webClient.post() + .uri(siteCallbackUrl + "/changebalance/slot") + .headers(headers -> headers.addAll(header)) + .bodyValue(param.toString()) + .exchangeToMono(clientResponse -> { + if (clientResponse.statusCode().is2xxSuccessful()) { + return clientResponse.bodyToMono(String.class); + } else { + return clientResponse.bodyToMono(String.class) + .map(body -> { + try { + JSONObject errorResponse = new JSONObject(); + errorResponse.put("result_code", -99); + errorResponse.put("error_msg", "HTTP_STATUS_CODE_ERR > " + clientResponse.statusCode().value()); + return errorResponse.toString(); + } catch (JSONException e) { + log.error(methodLogPrefix + "Error parsing error response body: {}", e.getMessage()); + return "{\"result_code\":-99, \"error_msg\":\"HTTP_STATUS_CODE_ERR and parsing error\"}"; + } + }); + } + }) + .onErrorResume(ConnectException.class, e -> { + log.error(methodLogPrefix+ "ConnectException e: CONNECT_TIMEOUT (3000ms)"); + log.error(methodLogPrefix+ "ConnectException e: {}", e.toString()); + return monoErrorResponse("-99", "CONNECT_TIMEOUT (3000ms)"); + }) + .onErrorResume(ReadTimeoutException.class, e -> { + log.error(methodLogPrefix+ "SocketTimeoutException e: READ_TIMEOUT (5000ms)"); + log.error(methodLogPrefix+ "SocketTimeoutException e: {}", e.toString()); + return monoErrorResponse("-99", "READ_TIMEOUT (5000ms)"); + }) + .onErrorResume(SocketTimeoutException.class, e -> { + log.error(methodLogPrefix+ "SocketTimeoutException e: READ_TIMEOUT (5000ms)"); + log.error(methodLogPrefix+ "SocketTimeoutException e: {}", e.toString()); + return monoErrorResponse("-99", "READ_TIMEOUT (5000ms)"); + }) + .onErrorResume(Exception.class, e -> { + log.error(methodLogPrefix+ "Exception e: {}", e.toString()); + return monoErrorResponse("-99", "GENERAL_ERROR"); + }) + .block(); // Synchronous call + + long endTimestamp = System.currentTimeMillis(); + double diffTime = (endTimestamp - startTimestamp)/1000.0; + + if (responseBody != null) { + response = new JSONObject(responseBody); + + if (response.has("result_code") == false) { + try { + int resultCode = response.getInt("resultCode"); + response.put("result_code", resultCode); + response.remove("resultCode"); + } catch(Exception e) { + response.put("result_code", -9); + response.put("error_msg", "Not found result_code"); + } + } + + if(diffTime > 0.25) { + log.error(methodLogPrefix+ "잔액변경 응답시간(250ms) 초과"); + response.put("result_code", -99); + response.put("error_msg", "RESPONSE_TIME_OUT [잔액변경 응답시간(250ms) 초과]"); + } + } else { + response.put("result_code", -99); + response.put("error_msg", "EMPTY_RESPONSE_BODY"); + } + + response.put("timeMs", (endTimestamp - startTimestamp)); + + } catch (JSONException e) { + long endTimestamp = System.currentTimeMillis(); + log.error(methodLogPrefix+ "JSONException e: {}", e.toString()); + e.printStackTrace(); + try { + response.put("result_code", -99); + response.put("error_msg", "JSON_PARSE_ERROR"); + response.put("timeMs", (endTimestamp - startTimestamp)); + } catch (JSONException e1) { + e1.printStackTrace(); + } + } catch (Exception e) { + long endTimestamp = System.currentTimeMillis(); + log.error(methodLogPrefix+ "Exception e: {}", e.toString()); + e.printStackTrace(); + try { + response.put("result_code", -99); + response.put("error_msg", "GENERAL_ERROR"); + response.put("timeMs", (endTimestamp - startTimestamp)); + } catch (JSONException e1) { + e1.printStackTrace(); + } + } + + log.info(methodLogPrefix+ "response: {}", response.toString()); + return response; + } + + @Override + public JSONObject getTestBalance(String LOG_PREFIX, String memberId, String token, String authorization) { + + JSONObject responseObj = null; + String methodLogPrefix = LOG_PREFIX; // LOG_PREFIX is not modified in this method, so it's effectively final. + + try { + // 1. 요청 URL + 쿼리 파라미터 + String url = "https://cb.nxapi.cc/api/t1/spdtest/testBalance"; + UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(url) + .queryParam("memberId", memberId); + + // 2. 헤더 설정 (토큰 필요 시) + HttpHeaders headers = getHeader(); + headers.set("Authorization", authorization); + headers.set("token", token); + + log.info(methodLogPrefix+ "request: {}", uriBuilder.toUriString()); + + // 3. GET 요청 + String responseBody = this.webClient.get() + .uri(uriBuilder.toUriString()) + .headers(h -> h.addAll(headers)) + .retrieve() + .bodyToMono(String.class) + .onErrorResume(Exception.class, e -> { + log.error(methodLogPrefix+ "Exception e: {}", e.toString()); + return reactor.core.publisher.Mono.empty(); // Return empty to simulate null body + }) + .block(); // Synchronous call + + if (responseBody != null && !responseBody.isEmpty()) { + log.info(methodLogPrefix+ "response: {}", responseBody); + responseObj = new JSONObject(responseBody); + } + } catch (Exception e) { + log.error(methodLogPrefix+ "Exception e: {}", e.toString()); + } + + return responseObj; + } + + @Override + public JSONObject getTestChangeBalance(String LOG_PREFIX, String memberId, String token, String authorization) { + + JSONObject responseObj = null; + String methodLogPrefix = LOG_PREFIX; // LOG_PREFIX is not modified in this method, so it's effectively final. + + try { + // 1. 요청 URL + 쿼리 파라미터 + String url = "https://cb.nxapi.cc/api/t1/spdtest/testCasino"; + UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(url) + .queryParam("memberId", memberId); + + // 2. 헤더 설정 (토큰 필요 시) + HttpHeaders headers = getHeader(); + headers.set("Authorization", authorization); + headers.set("token", token); + + // 3. GET 요청 + String responseBody = this.webClient.get() + .uri(uriBuilder.toUriString()) + .headers(h -> h.addAll(headers)) + .retrieve() + .bodyToMono(String.class) + .onErrorResume(Exception.class, e -> { + log.error(methodLogPrefix+ "Exception e: {}", e.toString()); + return reactor.core.publisher.Mono.empty(); // Return empty to simulate null body + }) + .block(); // Synchronous call + + if (responseBody != null && !responseBody.isEmpty()) { + responseObj = new JSONObject(responseBody); + } + } catch (Exception e) { + log.error(methodLogPrefix+ "Exception e: {}", e.toString()); + } + + return responseObj; + } + + @Override + public JSONObject getTestChangeBalanceSlot(String LOG_PREFIX, String memberId, String token, String authorization) { + + JSONObject responseObj = null; + String methodLogPrefix = LOG_PREFIX; // LOG_PREFIX is not modified in this method, so it's effectively final. + + try { + // 1. 요청 URL + 쿼리 파라미터 + String url = "https://cb.nxapi.cc/api/t1/spdtest/testSlot"; + UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(url) + .queryParam("memberId", memberId); + + // 2. 헤더 설정 (토큰 필요 시) + HttpHeaders headers = getHeader(); + headers.set("Authorization", authorization); + headers.set("token", token); + + // 3. GET 요청 + String responseBody = this.webClient.get() + .uri(uriBuilder.toUriString()) + .headers(h -> h.addAll(headers)) + .retrieve() + .bodyToMono(String.class) + .onErrorResume(Exception.class, e -> { + log.error(methodLogPrefix+ "Exception e: {}", e.toString()); + return reactor.core.publisher.Mono.empty(); // Return empty to simulate null body + }) + .block(); // Synchronous call + + if (responseBody != null && !responseBody.isEmpty()) { + responseObj = new JSONObject(responseBody); + } + } catch (Exception e) { + log.error(methodLogPrefix+ "Exception e: {}", e.toString()); + } + + return responseObj; + } +} diff --git a/src/main/java/com/bb/service/CoinService.java b/src/main/java/com/bb/service/CoinService.java new file mode 100644 index 0000000..06f59b0 --- /dev/null +++ b/src/main/java/com/bb/service/CoinService.java @@ -0,0 +1,10 @@ +package com.bb.service; + +import com.bb.model.CoinVo; + +public interface CoinService { + + void saveCoinInfo(CoinVo coinInfo); + CoinVo getCoinInfo(String coinSymbol, String currency); + +} diff --git a/src/main/java/com/bb/service/CoinServiceImpl.java b/src/main/java/com/bb/service/CoinServiceImpl.java new file mode 100644 index 0000000..a86e8a5 --- /dev/null +++ b/src/main/java/com/bb/service/CoinServiceImpl.java @@ -0,0 +1,32 @@ +package com.bb.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.bb.dao.CoinDao; +import com.bb.dao.SiteDao; +import com.bb.model.CoinVo; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class CoinServiceImpl implements CoinService{ + + + @Autowired + private CoinDao coinDao; + + @Override + public void saveCoinInfo(CoinVo coinInfo) { + coinDao.saveCoinInfo(coinInfo); + } + + + + @Override + public CoinVo getCoinInfo(String coinSymbol, String currency) { + return coinDao.getCoinInfo(coinSymbol, currency); + } + +} diff --git a/src/main/java/com/bb/service/CommonService.java b/src/main/java/com/bb/service/CommonService.java new file mode 100644 index 0000000..44800e2 --- /dev/null +++ b/src/main/java/com/bb/service/CommonService.java @@ -0,0 +1,36 @@ +package com.bb.service; + +import java.util.HashMap; +import java.util.List; + +import com.bb.model.BanGameSearch; +import com.bb.model.CmnSearch; +import com.bb.model.GameVo; + +public interface CommonService { + + List> getGameCategoryList(); + + List> getGameVendorList(CmnSearch search); + + List> getBanGameList(BanGameSearch search); + + int insertBanGameInfo(HashMap item); + + int insertNexusGameInfo(HashMap item); + + HashMap getVendorApiInfo(CmnSearch search); + + List getGrandGameList(String LOG_PREFIX, HashMap apiInfo); + + List getSevenGameList(String LOG_PREFIX, HashMap apiInfo); + + List getTplusGameList(String LOG_PREFIX, HashMap apiInfo); + + List getPracpGameList(String LOG_PREFIX, HashMap apiInfo); + + List getNexusGameList(String LOG_PREFIX, HashMap apiInfo); + + List getTowerGameList(String LOG_PREFIX, HashMap apiInfo); + +} diff --git a/src/main/java/com/bb/service/CommonServiceImpl.java b/src/main/java/com/bb/service/CommonServiceImpl.java new file mode 100644 index 0000000..e5ed753 --- /dev/null +++ b/src/main/java/com/bb/service/CommonServiceImpl.java @@ -0,0 +1,571 @@ +package com.bb.service; + +import java.math.BigInteger; +import java.net.SocketTimeoutException; +import java.nio.charset.Charset; +import java.security.MessageDigest; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Base64; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; + +import io.netty.channel.ConnectTimeoutException; +import io.netty.handler.timeout.ReadTimeoutException; +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.WebClientRequestException; +import org.springframework.web.reactive.function.client.WebClientResponseException; +import org.springframework.web.util.UriComponentsBuilder; + +import com.bb.dao.CommonDao; +import com.bb.model.BanGameSearch; +import com.bb.model.CmnSearch; +import com.bb.model.GameVo; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class CommonServiceImpl implements CommonService { + + @Autowired + private CommonDao commonDao; + + @Autowired + WebClient webClient; + + @Override + public List> getGameCategoryList() { + // TODO Auto-generated method stub + return commonDao.getGameCategoryList(); + } + + @Override + public List> getGameVendorList(CmnSearch search) { + // TODO Auto-generated method stub + return commonDao.getGameVendorList(search); + } + + @Override + public List> getBanGameList(BanGameSearch search) { + // TODO Auto-generated method stub + return commonDao.getBanGameList(search); + } + + @Override + public int insertBanGameInfo(HashMap item) { + // TODO Auto-generated method stub + return commonDao.insertBanGameInfo(item); + } + + @Override + public int insertNexusGameInfo(HashMap item) { + // TODO Auto-generated method stub + return commonDao.insertNexusGameInfo(item); + } + + @Override + public HashMap getVendorApiInfo(CmnSearch search) { + // TODO Auto-generated method stub + return commonDao.getVendorApiInfo(search); + } + + @Override + public List getGrandGameList(String LOG_PREFIX, HashMap apiInfo) { + List gameList = null; + long vendorIdx = (long) apiInfo.get("vendorIdx"); + String vendorApiUrl = apiInfo.get("vendorApiUrl").toString(); + String vendorApiId = apiInfo.get("vendorApiId").toString(); + String vendorApiKey = apiInfo.get("vendorApiKey").toString(); + String vendorGameCode = apiInfo.get("vendorGameCode").toString(); + String vendorTitle = apiInfo.get("vendorTitle").toString(); + + try { + HttpHeaders header = new HttpHeaders(); + header.set("Content-Type", "application/json"); + header.set("Accept", "application/json"); + header.set("Authorization", "Bearer " + vendorApiKey); + + ResponseEntity res = webClient.get() + .uri(vendorApiUrl+"/games?vendor_key="+vendorGameCode) + .headers(h -> h.addAll(header)) + .retrieve() + .toEntity(String.class) + .block(); + JSONObject resJson = new JSONObject(res.getBody()); + JSONArray games = resJson.getJSONArray("data"); + int length = games.length(); + log.info(LOG_PREFIX+"getGrandGameList length: " + length); + gameList = new ArrayList<>(); + + for(int i=0; i getSevenGameList(String LOG_PREFIX, HashMap apiInfo) { + List gameList = null; + long vendorIdx = (long) apiInfo.get("vendorIdx"); + String vendorApiUrl = apiInfo.get("vendorApiUrl").toString(); + String vendorApiId = apiInfo.get("vendorApiId").toString(); + String vendorApiKey = apiInfo.get("vendorApiKey").toString(); + String vendorGameCode = apiInfo.get("vendorGameCode").toString(); + String vendorTitle = apiInfo.get("vendorTitle").toString(); + + try { + //body + MultiValueMap parameters = new LinkedMultiValueMap<>(); + parameters.add("vendor", vendorGameCode); + + HttpHeaders header = new HttpHeaders(); + header.set("Content-Type", "application/x-www-form-urlencoded"); + header.set("Authorization", vendorApiKey); + + log.info(LOG_PREFIX+ "getSevenGameList::Request::"+parameters.toString()); + + ResponseEntity responseEntity = webClient.post() + .uri(vendorApiUrl+"/gamelist") + .headers(h -> h.addAll(header)) + .bodyValue(parameters) + .retrieve() + .toEntity(String.class) + .block(); + JSONObject resJson = new JSONObject(responseEntity.getBody()); + log.info(LOG_PREFIX+ "gameList::Response::"+resJson.toString()); + if(resJson.getInt("code") == 0) { + log.info(LOG_PREFIX+ "gameList::Response::code::"+resJson.getInt("code")); + log.info(LOG_PREFIX+ "gameList::Response::msg::"+resJson.getString("msg")); + JSONArray games = resJson.getJSONArray("data"); + int length = games.length(); + gameList = new ArrayList<>(); + + for(int i=0; i getTplusGameList(String LOG_PREFIX, HashMap apiInfo) { + List gameList = null; + long vendorIdx = (long) apiInfo.get("vendorIdx"); + String vendorApiUrl = apiInfo.get("vendorApiUrl").toString(); + String vendorApiId = apiInfo.get("vendorApiId").toString(); + String vendorApiKey = apiInfo.get("vendorApiKey").toString(); + String vendorGameCode = apiInfo.get("vendorGameCode").toString(); + String vendorTitle = apiInfo.get("vendorTitle").toString(); + + try { + HttpHeaders header = new HttpHeaders(); + header.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + header.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + header.set("Authorization", "Bearer "+vendorApiKey); + + UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(vendorApiUrl + "/Games"); + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("thirdparty", vendorGameCode); + + ResponseEntity response = webClient.post() + .uri(builder.toUriString()) + .headers(h -> h.addAll(header)) + .bodyValue(params) + .retrieve() + .toEntity(String.class) + .block(); + JSONObject resJson = new JSONObject(response.getBody()); + if(resJson.getInt("code") == 0) { + log.info(LOG_PREFIX+ "getTplusGameList result: " + resJson.getString("message")); + gameList = new ArrayList<>(); + JSONArray games = resJson.getJSONArray("data"); + int length = games.length(); + + for(int i=0; i getPracpGameList(String LOG_PREFIX, HashMap apiInfo) { + List gameList = null; + long vendorIdx = (long) apiInfo.get("vendorIdx"); + String vendorApiUrl = apiInfo.get("vendorApiUrl").toString(); + String vendorApiId = apiInfo.get("vendorApiId").toString(); + String vendorApiKey = apiInfo.get("vendorApiKey").toString(); + String vendorGameCode = apiInfo.get("vendorGameCode").toString(); + String vendorTitle = apiInfo.get("vendorTitle").toString(); + + try { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8"))); + + String apiUrl = vendorApiUrl + "/app/game/list?"; + + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); + long timeStampL = System.currentTimeMillis(); + String timeStamp = sdf.format(timeStampL); + apiInfo.put("timeStamp", timeStamp); + + String apiKey = ""; + String apiAgentCode = vendorApiId; + String apiToken = vendorApiKey; + + log.info(LOG_PREFIX+ "apiAgentCode::"+apiAgentCode); + log.info(LOG_PREFIX+ "apiToken::"+apiToken); + log.info(LOG_PREFIX+ "timeStamp::"+timeStamp); + + String textA = apiAgentCode+apiToken+timeStamp; + String salt = apiToken; + String textB = textA+salt; + log.info(LOG_PREFIX+ "textB::"+textB); + + try { + MessageDigest md = MessageDigest.getInstance("SHA-256"); + md.update(textB.getBytes("UTF-8")); + byte[] digest = md.digest(); + apiKey = new BigInteger(1, digest).toString(16).toLowerCase(); + log.info(LOG_PREFIX+ "apiKey::"+apiKey); + } catch(Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.getMessage()); + } + + String param = "api_key="+apiKey+"×tamp="+timeStamp + +"&agent_code="+vendorApiId+"&provider_code="+vendorGameCode; + apiUrl = apiUrl + param; + log.info(LOG_PREFIX+ "apiUrl::"+apiUrl); + + ResponseEntity resEntity = webClient.get() + .uri(apiUrl) + .headers(h -> h.addAll(headers)) + .retrieve() + .toEntity(String.class) + .block(); + if(resEntity.getStatusCodeValue() == 200) { + JSONObject responseObj = new JSONObject(resEntity.getBody()); + log.info(LOG_PREFIX+ "Response : " + responseObj.toString()); + + JSONArray games = responseObj.getJSONArray("data"); + int length = games.length(); + gameList = new ArrayList<>(); + + for(int i=0; i getNexusGameList(String LOG_PREFIX, HashMap apiInfo) { + List gameList = null; + long vendorIdx = (long) apiInfo.get("vendorIdx"); + String apiBaseUrl = apiInfo.get("vendorApiUrl").toString(); + String apiAgentId = apiInfo.get("vendorApiId").toString(); + String apiAgentSecretKey = apiInfo.get("vendorApiKey").toString(); + String apiVendorKey = apiInfo.get("vendorGameCode").toString(); + String vendorTitle = apiInfo.get("vendorTitle").toString(); + + try { + JSONObject bodyObj = new JSONObject(); + bodyObj.put("vendorKey", apiVendorKey); + bodyObj.put("skin", "SLOT"); + bodyObj.put("type", "Slot"); + String bodyJson = bodyObj.toString(); + log.info(LOG_PREFIX+ "bodyJson::"+bodyJson); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8"))); + String hashCode = getHashCode(LOG_PREFIX, bodyJson, apiAgentSecretKey); + headers.set("hash", hashCode); + headers.set("agent", apiAgentId); + log.info(LOG_PREFIX+ "HttpHeaders::"+headers.toString()); + + UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(apiBaseUrl + "/games"); + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("vendorKey", apiVendorKey); + params.add("skin", "SLOT"); + params.add("type", "Slot"); + + ResponseEntity response = webClient.post() + .uri(uriBuilder.toUriString()) + .headers(h -> h.addAll(headers)) + .bodyValue(params) + .retrieve() + .toEntity(String.class) + .block(); + JSONObject resObj = new JSONObject(response.getBody()); + if(resObj.getInt("code") == 0) { + JSONArray games = resObj.getJSONArray("games"); + int length = games.length(); + gameList = new ArrayList<>(); + + for(int i=0; i getTowerGameList(String LOG_PREFIX, HashMap apiInfo) { + // https://to-api.com/v2/games?site_code=tripleopr01&vendorCode=pp + List gameList = null; + long vendorIdx = (long) apiInfo.get("vendorIdx"); + String vendorTitle = apiInfo.get("vendorTitle").toString(); + String apiBaseUrl = apiInfo.get("vendorApiUrl").toString(); + String apiAgentId = apiInfo.get("vendorApiId").toString(); + String apiAgentSecretKey = apiInfo.get("vendorApiKey").toString(); + String apiVendorKey = apiInfo.get("vendorGameCode").toString(); + + try { + HttpHeaders header = new HttpHeaders(); + header.set("Authorization", apiAgentSecretKey); + + ResponseEntity responseEntity = webClient.get() + .uri(apiBaseUrl+"/v2/games?site_code="+apiAgentId+"&vendorCode="+apiVendorKey) + .headers(h -> h.addAll(header)) + .retrieve() + .toEntity(String.class) + .block(); + + JSONArray games = new JSONArray(responseEntity.getBody()); + int length = games.length(); + log.info(LOG_PREFIX+ "TOWER_API::gameList::Game List length: " + length); + + if(length > 0) { + gameList = new ArrayList<>(); + for(int i=0; i getCreditList(SiteSearch search); + + int getSiteTranListCnt(SiteSearch search); + List getSiteTranList(SiteSearch search); + + int updateStatus(Credit credit); + + int getPointListCnt(SiteSearch search); + + List getPointList(SiteSearch search); + + int getSiteBetListCnt(SiteSearch search); + + List getSiteBetList(SiteSearch search); + + int insertInsure(Insure insure); + + int updateInsureStatus(Insure insure); + + HashMap getMyInsureInfo(int siteIdx); + + int getInsureListCnt(SiteSearch search); + + List getInsureList(SiteSearch search); + + HashMap getCreditSumToday(SiteSearch search); + + void updateSetStatus(Credit credit2); + + String getRoundIdByGsoft(String refId); + + int insertPoint(CreditPoint point); + + int checkRequestTime(Credit credit); + + int getCashInOutListCnt(CashParam param); + + List getCashInOutList(CashParam param); + + int getTransCreditListCnt(CreditSearchVO search); + + List> getTransCreditList(CreditSearchVO search); + + int getTotalTransactionListCnt(CreditSearchVO search); + + List> getTotalTransactionList(CreditSearchVO search); + + int getCreditPointListCnt(@Valid CreditPointSearch search); + + List> getCreditPointList(@Valid CreditPointSearch search); + + int getCreditBetListCnt(@Valid CreditPointSearch search); + + List> getCreditBetList(@Valid CreditPointSearch search); + + int getStatCreditListCnt(SiteSearch search); + + List getStatCreditList(SiteSearch search); + + HashMap getStatCreditTotal(SiteSearch search); + + + + +} diff --git a/src/main/java/com/bb/service/CreditServiceImpl.java b/src/main/java/com/bb/service/CreditServiceImpl.java new file mode 100644 index 0000000..949b184 --- /dev/null +++ b/src/main/java/com/bb/service/CreditServiceImpl.java @@ -0,0 +1,347 @@ +package com.bb.service; + +import java.util.HashMap; +import java.util.List; + +import jakarta.validation.Valid; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.stereotype.Service; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.support.DefaultTransactionDefinition; + +import com.bb.dao.CreditDao; +import com.bb.dao.SiteDao; +import com.bb.model.CashParam; +import com.bb.model.Credit; +import com.bb.model.CreditPoint; +import com.bb.model.CreditPointSearch; +import com.bb.model.CreditSearchVO; +import com.bb.model.Insure; +import com.bb.model.SiteSearch; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class CreditServiceImpl implements CreditService{ + + @Autowired + private CreditDao creditDao; + + @Autowired + private SiteDao siteDao; + + + @Autowired + private DataSourceTransactionManager transactionManager; + + + @Override + public int insertCredit(Credit credit) { + TransactionStatus txStatus = transactionManager.getTransaction(new DefaultTransactionDefinition()); + int res = 0; + + long siteCredit = siteDao.getSiteCredit(credit.getTargetSiteId()); + log.info("siteCredit" + siteCredit); + try { + log.info("siteCredit" + siteCredit); + if(credit.getCreditAmt() != 0) { + credit.setPreCreditAmt(siteCredit); + creditDao.insertCredit(credit); + creditDao.insertCreditAiAo(credit); + } + if(credit.getSiteLevel() == 1 + && ("AI".equals(credit.getCreditType()) || "AO".equals(credit.getCreditType())) + ) { + creditDao.updateSubCredit(credit); + } + + res = 0; + transactionManager.commit(txStatus); + } catch(Exception e) { + System.out.println("ERROR"); + System.out.println(e.toString()); + res =-1; + transactionManager.rollback(txStatus); + } finally { + return res; + } + } + + @Override + public int insertCreditByCash(Credit credit) { + TransactionStatus txStatus = transactionManager.getTransaction(new DefaultTransactionDefinition()); + int res = 0; + + long siteCredit = siteDao.getSiteCredit(credit.getSiteId()); + HashMap balanceMap = new HashMap<>(); + balanceMap.put("siteIdx", credit.getSiteIdx()); + balanceMap.put("memberIdx", credit.getTargetSiteIdx()); + int userBalance = siteDao.getUserBalance(balanceMap); + try { + log.info("siteCredit" + siteCredit); + credit.setPreCreditAmt(siteCredit); + credit.setPreBalance(userBalance); + log.info("siteCredit" + siteCredit); + creditDao.insertCreditByCash(credit); + creditDao.insertCreditAiAo(credit); + res = 0; + transactionManager.commit(txStatus); + } catch(Exception e) { + System.out.println("ERROR"); + System.out.println(e.toString()); + res =-1; + transactionManager.rollback(txStatus); + } finally { + return res; + } + } + + + @Override + public int getCreditListCnt(SiteSearch search) { + // TODO Auto-generated method stub + return creditDao.getCreditListCnt(search); + } + + + @Override + public List getCreditList(SiteSearch search) { + // TODO Auto-generated method stub + return creditDao.getCreditList(search); + } + + + @Override + public int getSiteTranListCnt(SiteSearch search) { + // TODO Auto-generated method stub + return creditDao.getSiteTranListCnt(search); + } + + + @Override + public List getSiteTranList(SiteSearch search) { + // TODO Auto-generated method stub + return creditDao.getSiteTranList(search); + } + + + @Override + public int updateStatus(Credit credit) { + // TODO Auto-generated method stub + int res = 0; + try { + creditDao.updateStatus(credit); + }catch(Exception e) { + + } + return res; + } + + + @Override + public int getPointListCnt(SiteSearch search) { + return creditDao.getPointListCnt(search); + } + + + @Override + public List getPointList(SiteSearch search) { + return creditDao.getPointList(search); + } + + + @Override + public int getSiteBetListCnt(SiteSearch search) { + return creditDao.getSiteBetListCnt(search); + } + + + @Override + public List getSiteBetList(SiteSearch search) { + return creditDao.getSiteBetList(search); + } + + + @Override + public int insertInsure(Insure insure) { + TransactionStatus txStatus = transactionManager.getTransaction(new DefaultTransactionDefinition()); + int res = 0; + + + long siteInsure = siteDao.getInsureAmt(insure.getSiteId()); + + log.info("siteInsure" + siteInsure); + try { + + insure.setPreInsureAmt(siteInsure); + + creditDao.insertInsure(insure); + + + res =0; + transactionManager.commit(txStatus); + + }catch(Exception e) { + System.out.println("ERROR"); + System.out.println(e.toString()); + res =-1; + transactionManager.rollback(txStatus); + + + }finally { + return res; + } + } + + + @Override + public int updateInsureStatus(Insure insure) { + + int res = 0; + try { + creditDao.updateInsureStatus(insure); + }catch(Exception e) { + + } + return res; + } + + + @Override + public HashMap getMyInsureInfo(int siteIdx) { + // TODO Auto-generated method stub + return creditDao.getMyInsureInfo(siteIdx); + } + + + @Override + public int getInsureListCnt(SiteSearch search) { + return creditDao.getInsureListCnt(search); + } + + + @Override + public List getInsureList(SiteSearch search) { + return creditDao.getInsureList(search); + } + + + @Override + public HashMap getCreditSumToday(SiteSearch search) { + // TODO Auto-generated method stub + return creditDao.getCreditSumToday(search); + } + + + @Override + public void updateSetStatus(Credit credit2) { + // TODO Auto-generated method stub + creditDao.updateSetStatus(credit2); + } + + @Override + public String getRoundIdByGsoft(String refId) { + // TODO Auto-generated method stub + return creditDao.getRoundIdByGsoft(refId); + } + + + @Override + public int insertPoint(CreditPoint point) { + // TODO Auto-generated method stub + return creditDao.insertPoint(point); + } + + + @Override + public int checkRequestTime(Credit credit) { + // TODO Auto-generated method stub + return creditDao.checkRequestTime(credit); + } + + @Override + public int getCashInOutListCnt(CashParam param) { + // TODO Auto-generated method stub + return creditDao.getCashInOutListCnt(param); + } + + @Override + public List getCashInOutList(CashParam param) { + // TODO Auto-generated method stub + return creditDao.getCashInOutList(param); + } + + @Override + public int getTransCreditListCnt(CreditSearchVO search) { + // TODO Auto-generated method stub + return creditDao.getTransCreditListCnt(search); + } + + @Override + public List> getTransCreditList(CreditSearchVO search) { + // TODO Auto-generated method stub + return creditDao.getTransCreditList(search); + } + + @Override + public int getTotalTransactionListCnt(CreditSearchVO search) { + // TODO Auto-generated method stub + return creditDao.getTotalTransactionListCnt(search); + } + + @Override + public List> getTotalTransactionList(CreditSearchVO search) { + // TODO Auto-generated method stub + return creditDao.getTotalTransactionList(search); + } + + @Override + public int getCreditPointListCnt(@Valid CreditPointSearch search) { + // TODO Auto-generated method stub + return creditDao.getCreditPointListCnt(search); + } + + @Override + public List> getCreditPointList(@Valid CreditPointSearch search) { + // TODO Auto-generated method stub + return creditDao.getCreditPointList(search); + } + + @Override + public int getCreditBetListCnt(@Valid CreditPointSearch search) { + // TODO Auto-generated method stub + return creditDao.getCreditBetListCnt(search); + } + + @Override + public List> getCreditBetList(@Valid CreditPointSearch search) { + // TODO Auto-generated method stub + return creditDao.getCreditBetList(search); + } + + @Override + public int getStatCreditListCnt(SiteSearch search) { + // TODO Auto-generated method stub + return creditDao.getStatCreditListCnt(search); + } + + @Override + public List getStatCreditList(SiteSearch search) { + // TODO Auto-generated method stub + return creditDao.getStatCreditList(search); + } + + @Override + public HashMap getStatCreditTotal(SiteSearch search) { + // TODO Auto-generated method stub + return creditDao.getStatCreditTotal(search); + } + + + + + +} diff --git a/src/main/java/com/bb/service/EvoJsonService.java b/src/main/java/com/bb/service/EvoJsonService.java new file mode 100644 index 0000000..e7b4f7e --- /dev/null +++ b/src/main/java/com/bb/service/EvoJsonService.java @@ -0,0 +1,109 @@ +package com.bb.service; + +import org.springframework.stereotype.Service; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class EvoJsonService { + + private final ObjectMapper mapper; + + public EvoJsonService(ObjectMapper objectMapper) { + this.mapper = objectMapper; + } + + public String convert(String rawJson) { + try { + JsonNode root = mapper.readTree(rawJson); + ObjectNode unified = mapper.createObjectNode(); + + // 1. Transaction ID + String txId = root.has("id") ? root.get("id").asText() : ""; + unified.put("transaction_id", txId); + + // 2. Game Info + ObjectNode gameInfo = mapper.createObjectNode(); + gameInfo.put("provider", root.path("gameProvider").asText("evolution")); + gameInfo.put("category", root.path("gameType").asText("unknown")); + gameInfo.put("started_at", root.path("startedAt").asText("")); + gameInfo.put("settled_at", root.path("settledAt").asText("")); + unified.set("game_info", gameInfo); + + // 3. Game Result (가변적인 결과 처리) + ObjectNode gameResult = mapper.createObjectNode(); + JsonNode rawResult = root.path("result"); + + // outcome 추출 (문자열 혹은 숫자 대응) + if (rawResult.has("outcome")) { + gameResult.set("outcome", rawResult.get("outcome")); + } + + // 상세 데이터 (Payload) 구성 + ObjectNode payload = mapper.createObjectNode(); + String gameType = gameInfo.get("category").asText(); + + switch (gameType) { + case "baccarat": + case "dragontiger": + if (rawResult.has("player")) payload.set("player", rawResult.get("player")); + if (rawResult.has("banker")) payload.set("banker", rawResult.get("banker")); + if (rawResult.has("dragon")) payload.set("dragon", rawResult.get("dragon")); + if (rawResult.has("tiger")) payload.set("tiger", rawResult.get("tiger")); + break; + case "sicbo": + case "lightningdice": + ArrayNode dices = mapper.createArrayNode(); + if (rawResult.has("first")) dices.add(rawResult.get("first")); + if (rawResult.has("second")) dices.add(rawResult.get("second")); + if (rawResult.has("third")) dices.add(rawResult.get("third")); + payload.set("dices", dices); + break; + case "crazytime": + case "funkytime": + case "lightningstorm": + if (rawResult.has("wheelResult")) payload.set("wheel", rawResult.get("wheelResult")); + break; + case "racetrack": + if (rawResult.has("lanes")) payload.set("rankings", rawResult.get("lanes")); + break; + case "crazyballs": + case "monopolybigballer": + if (rawResult.has("drawnBalls")) payload.set("drawn_balls", rawResult.get("drawnBalls")); + break; + default: + // 정의되지 않은 게임은 결과 객체 통째로 저장 + payload.set("raw_details", rawResult); + } + gameResult.set("payload", payload); + unified.set("game_result", gameResult); + + // 4. Bet Details (참가자 배열에서 추출) + ArrayNode betDetails = mapper.createArrayNode(); + JsonNode participants = root.path("participants"); + if (participants.isArray() && participants.size() > 0) { + JsonNode bets = participants.get(0).path("bets"); + for (JsonNode bet : bets) { + ObjectNode simplifiedBet = mapper.createObjectNode(); + simplifiedBet.put("code", bet.path("code").asText()); + simplifiedBet.put("stake", bet.path("stake").asLong()); + simplifiedBet.put("payout", bet.path("payout").asDouble()); + simplifiedBet.put("placed_at", bet.path("placedOn").asText()); + betDetails.add(simplifiedBet); + } + } + unified.set("bet_details", betDetails); + + return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(unified); + + } catch (Exception e) { + return "{\"error\": \"데이터 변환 중 오류 발생: " + e.getMessage() + "\"}"; + } + } +} diff --git a/src/main/java/com/bb/service/GrandService.java b/src/main/java/com/bb/service/GrandService.java new file mode 100644 index 0000000..9ae6575 --- /dev/null +++ b/src/main/java/com/bb/service/GrandService.java @@ -0,0 +1,15 @@ +package com.bb.service; + +import java.util.HashMap; +import java.util.List; + +import org.codehaus.jettison.json.JSONObject; + +import com.bb.model.Game; + +public interface GrandService { + String getLaunchUrl(HashMap venderInfo); + List getGameList(HashMap venderInfo); + JSONObject getDetail(String LOG_PREFIX, HashMap apiInfo); + +} diff --git a/src/main/java/com/bb/service/GrandServiceImpl.java b/src/main/java/com/bb/service/GrandServiceImpl.java new file mode 100644 index 0000000..b05a0d5 --- /dev/null +++ b/src/main/java/com/bb/service/GrandServiceImpl.java @@ -0,0 +1,133 @@ +package com.bb.service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +import org.springframework.web.reactive.function.client.WebClient; + + +import com.bb.dao.SiteDao; +import com.bb.model.Game; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class GrandServiceImpl implements GrandService { + + @Autowired + private SiteDao siteDao; + + @Autowired + WebClient webClient; + + @Override + public String getLaunchUrl(HashMap venderInfo) { + + + JSONObject params = new JSONObject(); + try { + params.put("vendor_key", venderInfo.get("vendor_key").toString()); + params.put("game_key", venderInfo.get("game_key").toString()); + params.put("username", venderInfo.get("username").toString()); + params.put("nickname", venderInfo.get("username").toString()); + + HttpHeaders header = new HttpHeaders(); + header.set("Content-Type", "application/json"); + header.set("Accept", "application/json"); + header.set("Authorization", "Bearer " + venderInfo.get("vendorApiKey").toString()); + log.info(venderInfo.get("vendorApiUrl").toString()+"/game-url"); + log.info(params.toString()); + + ResponseEntity res = webClient.post() + .uri(venderInfo.get("vendorApiUrl").toString()+"/game-url") + .headers(h -> h.addAll(header)) + .bodyValue(params.toString()) + .retrieve() + .toEntity(String.class) + .block(); + + log.info(res.getBody()); + JSONObject resJson = new JSONObject(res.getBody()); + JSONObject resData = resJson.getJSONObject("data"); + return resData.getString("url"); + }catch(Exception e) { + log.info("[ERROR] Grand pragmatic getLaunchUrl : "+ venderInfo.get("username").toString()+" - " + e.toString()); + return null; + } + + } + + @Override + public List getGameList(HashMap venderInfo) { + List gameList = null; + try { + + + HttpHeaders header = new HttpHeaders(); + header.set("Content-Type", "application/json"); + header.set("Accept", "application/json"); + header.set("Authorization", "Bearer " + venderInfo.get("vendorApiKey").toString()); + + ResponseEntity res = webClient.get() + .uri(venderInfo.get("vendorApiUrl").toString()+"/games?vendor_key="+venderInfo.get("vendor_key").toString()) + .headers(h -> h.addAll(header)) + .retrieve() + .toEntity(String.class) + .block(); + + JSONObject resJson = new JSONObject(res.getBody()); + + //log.info(resJson.toString()); + JSONArray games = resJson.getJSONArray("data"); + int length = games.length(); + gameList = new ArrayList<>(); + + for(int i=0; i apiInfo) { + // TODO Auto-generated method stub + return null; + } + + + + +} diff --git a/src/main/java/com/bb/service/GsoftService.java b/src/main/java/com/bb/service/GsoftService.java new file mode 100644 index 0000000..577f772 --- /dev/null +++ b/src/main/java/com/bb/service/GsoftService.java @@ -0,0 +1,22 @@ +package com.bb.service; + +import java.util.HashMap; +import java.util.List; + +import org.codehaus.jettison.json.JSONObject; + +import com.bb.model.Game; +import com.bb.model.GsoftApiInfo; + +public interface GsoftService { + + JSONObject getBalanceUser(GsoftApiInfo apiInfo); + + JSONObject depositUser(GsoftApiInfo apiInfo, int amount); + + JSONObject withdrawUser(GsoftApiInfo apiInfo); + + List gameList(GsoftApiInfo apiInfo); + + String getComanyBalance(HashMap vendor); +} diff --git a/src/main/java/com/bb/service/GsoftServiceImpl.java b/src/main/java/com/bb/service/GsoftServiceImpl.java new file mode 100644 index 0000000..f1ece2c --- /dev/null +++ b/src/main/java/com/bb/service/GsoftServiceImpl.java @@ -0,0 +1,458 @@ +package com.bb.service; + +import java.net.SocketTimeoutException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.apache.http.conn.ConnectTimeoutException; +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONException; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.ResourceAccessException; +import org.springframework.web.reactive.function.client.WebClient; + +import com.bb.dao.SiteDao; +import com.bb.model.Game; +import com.bb.model.GsoftApiInfo; +import com.bb.model.VendorChangeBalanceLogVo; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class GsoftServiceImpl implements GsoftService { + + @Autowired + private SiteDao siteDao; + + @Autowired + WebClient webClient; + + + @Override + public JSONObject getBalanceUser(GsoftApiInfo apiInfo) { + JSONObject userBalanceJson = null; + + try { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.set("Authorization", apiInfo.getApiAuthKey()); + + JSONObject params = new JSONObject(); + params.put("userid", apiInfo.getUserId()); + params.put("amount", 0); + params.put("type", "0"); + + String balanceUrl = apiInfo.getApiBaseUrl() + "/csapi/amount"; + log.info("## GSOFT API ## balanceUrl: " + balanceUrl); + log.info("## GSOFT API ## balanceHeaders: " + headers.toString()); + log.info("## GSOFT API ## balanceParams: " + params.toString()); + + ResponseEntity res = webClient.post() + .uri(balanceUrl) + .headers(h -> h.addAll(headers)) + .bodyValue(params.toString()) + .retrieve() + .toEntity(String.class) + .block(); + + log.info("## GSOFT API ## Request \"/csapi/amount\" res : " + res.getBody()); + userBalanceJson = new JSONObject(res.getBody()); + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error("[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error("[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error("[InterruptedException]"+rae.getMessage()); + } + } catch(HttpClientErrorException hee) { + String str = hee.getResponseBodyAsString(); + log.error(str); + } catch (Exception e) { + log.error(e.toString()); + e.printStackTrace(); + } + + return userBalanceJson; + } + + @Override + public JSONObject depositUser(GsoftApiInfo apiInfo, int amount) { + JSONObject depositJson = null; + + try { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.set("Authorization", apiInfo.getApiAuthKey()); + + JSONObject params = new JSONObject(); + params.put("userid", apiInfo.getUserId()); + params.put("amount", amount); + params.put("type", "1"); + + String depositUrl = apiInfo.getApiBaseUrl() + "/csapi/amount"; + log.info("## GSOFT API ## depositUrl: " + depositUrl); + log.info("## GSOFT API ## depositHeaders: " + headers.toString()); + log.info("## GSOFT API ## depositParams: " + params.toString()); + + log.error("#-depositProc::"+apiInfo.getSiteIdx()+"::"+apiInfo.getMemberIdx()+"::"+apiInfo.getReqAt()+"::gsoft::"+ "depositParams::"+params.toString()); + + ResponseEntity res = webClient.post() + .uri(depositUrl) + .headers(h -> h.addAll(headers)) + .bodyValue(params.toString()) + .retrieve() + .toEntity(String.class) + .block(); + log.info("## GSOFT API ## Request \"/csapi/amount\" res : " + res.getBody()); + depositJson = new JSONObject(res.getBody()); + + if(depositJson.getInt("result") == 1) { + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("gsoft") + .vendorApiId(apiInfo.getClientId()) + .reqType("deposit") + .amount(amount) + .reqAt(apiInfo.getReqAt()) + .reqStatus("SUCC") + .reqMsg(depositJson.getString("msg")) + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + } else { + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("gsoft") + .vendorApiId(apiInfo.getClientId()) + .reqType("deposit") + .amount(amount) + .reqAt(apiInfo.getReqAt()) + .reqStatus("FAIL") + .reqMsg(depositJson.getString("msg")) + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error("#-depositProc::"+apiInfo.getSiteIdx()+"::"+apiInfo.getMemberIdx()+"::"+apiInfo.getReqAt()+"::gsoft::"+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error("#-depositProc::"+apiInfo.getSiteIdx()+"::"+apiInfo.getMemberIdx()+"::"+apiInfo.getReqAt()+"::gsoft::"+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error("#-depositProc::"+apiInfo.getSiteIdx()+"::"+apiInfo.getMemberIdx()+"::"+apiInfo.getReqAt()+"::gsoft::"+ "[InterruptedException]"+rae.getMessage()); + } + + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("gsoft") + .vendorApiId(apiInfo.getClientId()) + .reqType("deposit") + .amount(amount) + .reqAt(apiInfo.getReqAt()) + .reqStatus("FAIL") + .reqMsg("TimeoutException") + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + + } catch(HttpClientErrorException hee) { + String str = hee.getResponseBodyAsString(); + log.error("#-depositProc::"+apiInfo.getSiteIdx()+"::"+apiInfo.getMemberIdx()+"::"+apiInfo.getReqAt()+"::gsoft::"+ "[HttpClientErrorException]"+str); + + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("gsoft") + .vendorApiId(apiInfo.getClientId()) + .reqType("deposit") + .amount(amount) + .reqAt(apiInfo.getReqAt()) + .reqStatus("FAIL") + .reqMsg(str) + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + + } catch (Exception e) { + log.error("#-depositProc::"+apiInfo.getSiteIdx()+"::"+apiInfo.getMemberIdx()+"::"+apiInfo.getReqAt()+"::gsoft::"+ "[Exception]"+e.toString()); + + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("gsoft") + .vendorApiId(apiInfo.getClientId()) + .reqType("deposit") + .amount(amount) + .reqAt(apiInfo.getReqAt()) + .reqStatus("FAIL") + .reqMsg("Exception e") + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + } + + return depositJson; + } + + @Override + public JSONObject withdrawUser(GsoftApiInfo apiInfo) { + JSONObject withdrawJson = null; + + try { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.set("Authorization", apiInfo.getApiAuthKey()); + + JSONObject params = new JSONObject(); + params.put("userid", apiInfo.getUserId()); + params.put("amount", 0); + params.put("type", "3"); + + String withdrawUrl = apiInfo.getApiBaseUrl() + "/csapi/amount"; + log.info("## GSOFT API ## withdrawUrl: " + withdrawUrl); + log.info("## GSOFT API ## withdrawHeaders: " + headers.toString()); + log.info("## GSOFT API ## withdrawParams: " + params.toString()); + + ResponseEntity res = webClient.post() + .uri(withdrawUrl) + .headers(h -> h.addAll(headers)) + .bodyValue(params.toString()) + .retrieve() + .toEntity(String.class) + .block(); + log.info("## GSOFT API ## Request \"/csapi/amount\" res : " + res.getBody()); + withdrawJson = new JSONObject(res.getBody()); + + if(withdrawJson.getInt("result") == 1) { + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("gsoft") + .vendorApiId(apiInfo.getClientId()) + .reqType("withdrawAll") + .amount(0) + .reqAt(apiInfo.getReqAt()) + .reqStatus("SUCC") + .reqMsg(withdrawJson.getString("msg")) + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + } else { + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("gsoft") + .vendorApiId(apiInfo.getClientId()) + .reqType("withdrawAll") + .amount(0) + .reqAt(apiInfo.getReqAt()) + .reqStatus("FAIL") + .reqMsg(withdrawJson.getString("msg")) + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error("#-withdrawProc::"+apiInfo.getSiteIdx()+"::"+apiInfo.getMemberIdx()+"::"+apiInfo.getReqAt()+"::gsoft::"+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error("#-withdrawProc::"+apiInfo.getSiteIdx()+"::"+apiInfo.getMemberIdx()+"::"+apiInfo.getReqAt()+"::gsoft::"+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error("#-withdrawProc::"+apiInfo.getSiteIdx()+"::"+apiInfo.getMemberIdx()+"::"+apiInfo.getReqAt()+"::gsoft::"+ "[InterruptedException]"+rae.getMessage()); + } + + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("gsoft") + .vendorApiId(apiInfo.getClientId()) + .reqType("withdrawAll") + .amount(0) + .reqAt(apiInfo.getReqAt()) + .reqStatus("FAIL") + .reqMsg("TimeoutException") + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + + } catch(HttpClientErrorException hee) { + String str = hee.getResponseBodyAsString(); + log.error("#-withdrawProc::"+apiInfo.getSiteIdx()+"::"+apiInfo.getMemberIdx()+"::"+apiInfo.getReqAt()+"::gsoft::"+ "[HttpClientErrorException]"+str); + + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("gsoft") + .vendorApiId(apiInfo.getClientId()) + .reqType("withdrawAll") + .amount(0) + .reqAt(apiInfo.getReqAt()) + .reqStatus("FAIL") + .reqMsg(str) + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + + } catch (Exception e) { + log.error("#-withdrawProc::"+apiInfo.getSiteIdx()+"::"+apiInfo.getMemberIdx()+"::"+apiInfo.getReqAt()+"::gsoft::"+ "[Exception]"+e.toString()); + e.printStackTrace(); + + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("gsoft") + .vendorApiId(apiInfo.getClientId()) + .reqType("withdrawAll") + .amount(0) + .reqAt(apiInfo.getReqAt()) + .reqStatus("FAIL") + .reqMsg("Exception e") + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + } + + return withdrawJson; + } + + @Override + public List gameList(GsoftApiInfo apiInfo) { + + List gameList = null; + + try { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.set("Authorization", apiInfo.getApiAuthKey()); + + JSONObject params = new JSONObject(); + params.put("type", 2); + params.put("gameid", apiInfo.getGameId()); + params.put("code", apiInfo.getCode()); + + String slotUrl = apiInfo.getApiBaseUrl() + "/csapi/Provider"; + log.info("## GSOFT API ## slotUrl: " + slotUrl); + log.info("## GSOFT API ## slotHeaders: " + headers.toString()); + log.info("## GSOFT API ## slotParams: " + params.toString()); + + ResponseEntity res = webClient.post() + .uri(slotUrl) + .headers(h -> h.addAll(headers)) + .bodyValue(params.toString()) + .retrieve() + .toEntity(String.class) + .block(); +// log.info("## GSOFT API ## Request \"/csapi/amount\" res : " + res.getBody()); + JSONObject slotJson = new JSONObject(res.getBody()); + + if(slotJson.getInt("result") == 1) { + log.info("## GSOFT API ## Game List msg: " + slotJson.getString("msg")); + JSONArray games = slotJson.getJSONArray("data"); + int length = games.length(); + gameList = new ArrayList<>(); + + for(int i=0; i res = webClient.post() + .uri(balanceUrl) + .headers(h -> h.addAll(headers)) // 기존의 HttpHeaders 객체 적용 + .retrieve() + .toEntity(String.class) // Mono>를 반환 + .block(); + + log.info("## GSOFT API ## Request \"/csapi/amount\" res : " + res.getBody()); + userBalanceJson = new JSONObject(res.getBody()); + balance = userBalanceJson.get("balance2").toString(); + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error("[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error("[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error("[InterruptedException]"+rae.getMessage()); + } + } catch(HttpClientErrorException hee) { + String str = hee.getResponseBodyAsString(); + log.error(str); + } catch (Exception e) { + log.error(e.toString()); + e.printStackTrace(); + } + + return balance; + } + +} diff --git a/src/main/java/com/bb/service/NexusService.java b/src/main/java/com/bb/service/NexusService.java new file mode 100644 index 0000000..67b4f07 --- /dev/null +++ b/src/main/java/com/bb/service/NexusService.java @@ -0,0 +1,31 @@ +package com.bb.service; + +import java.util.List; + +import org.codehaus.jettison.json.JSONObject; + +import com.bb.model.Game; +import com.bb.model.NexusApiInfo; + +public interface NexusService { + + List gameList(String LOG_PREFIX, NexusApiInfo apiInfo); + + JSONObject createUser(String LOG_PREFIX, NexusApiInfo apiInfo); + + JSONObject userBalance(String LOG_PREFIX, NexusApiInfo apiInfo); + + JSONObject userDeposit(String LOG_PREFIX, NexusApiInfo apiInfo, int amount); + + JSONObject userWithdraw(String LOG_PREFIX, NexusApiInfo apiInfo, int amount); + + JSONObject userWithdrawAll(String LOG_PREFIX, NexusApiInfo apiInfo); + + String gameStart(String LOG_PREFIX, NexusApiInfo apiInfo); + + JSONObject getDetail(String LOG_PREFIX, NexusApiInfo apiInfo, String trxId); + + JSONObject getDetailUrl(String LOG_PREFIX, NexusApiInfo apiInfo, String trxId); + + JSONObject getTransaction(String LOG_PREFIX, NexusApiInfo apiInfo); +} diff --git a/src/main/java/com/bb/service/NexusServiceImpl.java b/src/main/java/com/bb/service/NexusServiceImpl.java new file mode 100644 index 0000000..10bfc02 --- /dev/null +++ b/src/main/java/com/bb/service/NexusServiceImpl.java @@ -0,0 +1,944 @@ +package com.bb.service; + +import java.net.SocketTimeoutException; +import java.nio.charset.Charset; +import java.security.MessageDigest; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Base64; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import io.netty.channel.ConnectTimeoutException; +import io.netty.handler.timeout.ReadTimeoutException; +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.WebClientRequestException; +import org.springframework.web.reactive.function.client.WebClientResponseException; +import org.springframework.web.util.UriComponentsBuilder; + +import com.bb.dao.CallBackDao; +import com.bb.dao.SiteDao; +import com.bb.model.Game; +import com.bb.model.NexusApiInfo; +import com.bb.model.VendorChangeBalanceLogVo; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class NexusServiceImpl implements NexusService { + + /** + * Nexus 공통 API에 필요한 서비스 + */ + + @Autowired + WebClient webClient; + + @Autowired + private SiteDao siteDao; + + @Autowired + CallBackDao callBackDao; + + private HttpHeaders getHeader(String LOG_PREFIX, NexusApiInfo apiInfo, String bodyJson) { + LOG_PREFIX = LOG_PREFIX + "::getHeader::"; + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8"))); + + String hashCode = getHashCode(LOG_PREFIX, bodyJson, apiInfo.getAgentSecretKey()); + headers.set("hash", hashCode); + headers.set("agent", apiInfo.getAgentId()); + log.info(LOG_PREFIX+ "HttpHeaders::"+headers.toString()); + + return headers; + } + + + private String getHashCode(String LOG_PREFIX, String body, String secretKey) { + String hashCode = ""; + LOG_PREFIX = LOG_PREFIX + "::getHashCode::"; + try { + // Json String Body + Secret Key + String result = body + secretKey; + // String result = "{\"username\":\"057007mptest01\",\"nickname\":\"007mptest01\",\"siteUsername\":\"057007mptest01\"}"; + log.info(LOG_PREFIX+ "Body + Secret Key::"+result); + // SHA-256 Hash make + MessageDigest digestObj = MessageDigest.getInstance("SHA-256"); + byte[] hash_data = digestObj.digest(result.getBytes("UTF-8")); + + // Base64 encoding + hashCode = Base64.getEncoder().encodeToString(hash_data); + log.info(LOG_PREFIX+ "hashCode::"+hashCode); + } catch(Exception e) { + log.error("#-NexusService::getHashCode::Exception::"+e.getMessage()); + } + + return hashCode; + } + + + @Override + public List gameList(String LOG_PREFIX, NexusApiInfo apiInfo) { + List gameList = null; + LOG_PREFIX = LOG_PREFIX + "::gameList::"; + + try { + JSONObject bodyObj = new JSONObject(); + bodyObj.put("vendorKey", apiInfo.getVendorKey()); + bodyObj.put("skin", apiInfo.getSkin()); + bodyObj.put("type", apiInfo.getType()); + String bodyJson = bodyObj.toString(); + log.info(LOG_PREFIX+ "bodyJson::"+bodyJson); + + HttpHeaders headers = getHeader(LOG_PREFIX, apiInfo, bodyJson); + UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(apiInfo.getApiBaseUrl() + "/games"); + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("vendorKey", apiInfo.getVendorKey()); + params.add("skin", apiInfo.getSkin()); + params.add("type", apiInfo.getType()); + + ResponseEntity response = webClient.post() + .uri(uriBuilder.toUriString()) + .headers(h -> h.addAll(headers)) + .bodyValue(params) + .retrieve() + .toEntity(String.class) + .block(); + + JSONObject resObj = new JSONObject(response.getBody()); + if(resObj.getInt("code") == 0) { + JSONArray games = resObj.getJSONArray("games"); + int length = games.length(); + gameList = new ArrayList<>(); + + for(int i=0; i params = new LinkedMultiValueMap<>(); + params.add("username", apiInfo.getUsername()); + params.add("nickname", apiInfo.getNickname()); + params.add("siteUsername", apiInfo.getSiteUsername()); + log.info(LOG_PREFIX+ "entity::"+params.toString()); + log.info(LOG_PREFIX+ "headers::"+headers.toString()); + + ResponseEntity response = webClient.post() + .uri(uriBuilder.toUriString()) + .headers(h -> h.addAll(headers)) + .bodyValue(params) + .retrieve() + .toEntity(String.class) + .block(); + + log.info(LOG_PREFIX+ "Response::"+response.getBody().toString()); + jsonObj = new JSONObject(response.getBody()); + + } catch (WebClientResponseException e) { + log.error(LOG_PREFIX+ "WebClientResponseException::"+e.getMessage()); + log.error(LOG_PREFIX+ "status code::"+e.getStatusCode().value()); + log.error(LOG_PREFIX+ "response body::"+e.getResponseBodyAsString()); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof ReadTimeoutException) { + log.error(LOG_PREFIX+ "ReadTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "InterruptedException::"+rae.getMessage()); + } + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.getMessage()); + e.printStackTrace(); + } + + return jsonObj; + } + + + @Override + public JSONObject userBalance(String LOG_PREFIX, NexusApiInfo apiInfo) { + JSONObject jsonObj = null; + LOG_PREFIX = LOG_PREFIX + "::userBalance::"; + + try { + JSONObject bodyObj = new JSONObject(); + bodyObj.put("username", apiInfo.getUsername()); + bodyObj.put("siteUsername", apiInfo.getSiteUsername()); + String bodyJson = bodyObj.toString(); + log.info(LOG_PREFIX+ "bodyJson::"+bodyJson); + + HttpHeaders headers = getHeader(LOG_PREFIX, apiInfo, bodyJson); + UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(apiInfo.getApiBaseUrl() + "/balance"); + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("username", apiInfo.getUsername()); + params.add("siteUsername", apiInfo.getSiteUsername()); + + ResponseEntity response = webClient.post() + .uri(uriBuilder.toUriString()) + .headers(h -> h.addAll(headers)) + .bodyValue(params) + .retrieve() + .toEntity(String.class) + .block(); + + jsonObj = new JSONObject(response.getBody()); + + } catch (WebClientResponseException e) { + log.error(LOG_PREFIX+ "WebClientResponseException::"+e.getMessage()); + log.error(LOG_PREFIX+ "status code::"+e.getStatusCode().value()); + log.error(LOG_PREFIX+ "response body::"+e.getResponseBodyAsString()); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof ReadTimeoutException) { + log.error(LOG_PREFIX+ "ReadTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "InterruptedException::"+rae.getMessage()); + } + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.getMessage()); + e.printStackTrace(); + } + + return jsonObj; + } + + + @Override + public JSONObject userDeposit(String LOG_PREFIX, NexusApiInfo apiInfo, int amount) { + JSONObject jsonObj = null; + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + long reqAtL = System.currentTimeMillis(); + String reqAt = sdf.format(reqAtL); + LOG_PREFIX = LOG_PREFIX + "::userDeposit::"; + + try { + JSONObject bodyObj = new JSONObject(); + bodyObj.put("username", apiInfo.getUsername()); + bodyObj.put("siteUsername", apiInfo.getSiteUsername()); + bodyObj.put("amount", amount); + bodyObj.put("requestKey", Long.toString(reqAtL)); + String bodyJson = bodyObj.toString(); + log.info(LOG_PREFIX+ "bodyJson::"+bodyJson); + + HttpHeaders headers = getHeader(LOG_PREFIX, apiInfo, bodyJson); + UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(apiInfo.getApiBaseUrl() + "/deposit"); + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("username", apiInfo.getUsername()); + params.add("siteUsername", apiInfo.getSiteUsername()); + params.add("amount", amount); + params.add("requestKey", Long.toString(reqAtL)); + + ResponseEntity response = webClient.post() + .uri(uriBuilder.toUriString()) + .headers(h -> h.addAll(headers)) + .bodyValue(params) + .retrieve() + .toEntity(String.class) + .block(); + + jsonObj = new JSONObject(response.getBody()); + + if(jsonObj.getInt("code") == 0) { + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("nexus") + .vendorApiId(apiInfo.getAgentId()) + .reqType("deposit") + .amount(amount) + .reqAt(reqAt) + .reqStatus("SUCC") + .reqMsg("code:"+jsonObj.getInt("code")+", message:"+jsonObj.getDouble("balance")) + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + } else { + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("nexus") + .vendorApiId(apiInfo.getAgentId()) + .reqType("deposit") + .amount(amount) + .reqAt(reqAt) + .reqStatus("FAIL") + .reqMsg("code:"+jsonObj.getInt("code")+", message:"+jsonObj.getString("msg")) + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + } + + } catch (WebClientResponseException e) { + log.error(LOG_PREFIX+ "WebClientResponseException::"+e.getMessage()); + log.error(LOG_PREFIX+ "status code::"+e.getStatusCode().value()); + log.error(LOG_PREFIX+ "response body::"+e.getResponseBodyAsString()); + + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("nexus") + .vendorApiId(apiInfo.getAgentId()) + .reqType("deposit") + .amount(amount) + .reqAt(reqAt) + .reqStatus("FAIL") + .reqMsg(e.getResponseBodyAsString()) + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof ReadTimeoutException) { + log.error(LOG_PREFIX+ "ReadTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "InterruptedException::"+rae.getMessage()); + } + + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("nexus") + .vendorApiId(apiInfo.getAgentId()) + .reqType("deposit") + .amount(amount) + .reqAt(reqAt) + .reqStatus("FAIL") + .reqMsg("TimeoutException") + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.getMessage()); + + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("nexus") + .vendorApiId(apiInfo.getAgentId()) + .reqType("deposit") + .amount(amount) + .reqAt(reqAt) + .reqStatus("FAIL") + .reqMsg("Exception e:"+e.getMessage()) + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + e.printStackTrace(); + } + + return jsonObj; + } + + + @Override + public JSONObject userWithdraw(String LOG_PREFIX, NexusApiInfo apiInfo, int amount) { + JSONObject jsonObj = null; + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + long reqAtL = System.currentTimeMillis(); + String reqAt = sdf.format(reqAtL); + LOG_PREFIX = LOG_PREFIX + "::userWithdraw::"; + + try { + JSONObject bodyObj = new JSONObject(); + bodyObj.put("username", apiInfo.getUsername()); + bodyObj.put("siteUsername", apiInfo.getSiteUsername()); + bodyObj.put("amount", amount); + bodyObj.put("requestKey", Long.toString(reqAtL)); + String bodyJson = bodyObj.toString(); + log.info(LOG_PREFIX+ "bodyJson::"+bodyJson); + + HttpHeaders headers = getHeader(LOG_PREFIX, apiInfo, bodyJson); + UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(apiInfo.getApiBaseUrl() + "/withdraw"); + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("username", apiInfo.getUsername()); + params.add("siteUsername", apiInfo.getSiteUsername()); + params.add("amount", amount); + params.add("requestKey", Long.toString(reqAtL)); + + ResponseEntity response = webClient.post() + .uri(uriBuilder.toUriString()) + .headers(h -> h.addAll(headers)) + .bodyValue(params) + .retrieve() + .toEntity(String.class) + .block(); + + jsonObj = new JSONObject(response.getBody()); + + if(jsonObj.getInt("code") == 0) { + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("nexus") + .vendorApiId(apiInfo.getAgentId()) + .reqType("withdraw") + .amount(amount) + .reqAt(reqAt) + .reqStatus("SUCC") + .reqMsg("code:"+jsonObj.getInt("code")+", message:"+jsonObj.getDouble("balance")) + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + } else { + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("nexus") + .vendorApiId(apiInfo.getAgentId()) + .reqType("withdraw") + .amount(amount) + .reqAt(reqAt) + .reqStatus("FAIL") + .reqMsg("code:"+jsonObj.getInt("code")+", message:"+jsonObj.getString("msg")) + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + } + + } catch (WebClientResponseException e) { + log.error(LOG_PREFIX+ "WebClientResponseException::"+e.getMessage()); + log.error(LOG_PREFIX+ "status code::"+e.getStatusCode().value()); + log.error(LOG_PREFIX+ "response body::"+e.getResponseBodyAsString()); + + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("nexus") + .vendorApiId(apiInfo.getAgentId()) + .reqType("withdraw") + .amount(amount) + .reqAt(reqAt) + .reqStatus("FAIL") + .reqMsg(e.getResponseBodyAsString()) + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof ReadTimeoutException) { + log.error(LOG_PREFIX+ "ReadTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "InterruptedException::"+rae.getMessage()); + } + + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("nexus") + .vendorApiId(apiInfo.getAgentId()) + .reqType("withdraw") + .amount(amount) + .reqAt(reqAt) + .reqStatus("FAIL") + .reqMsg("TimeoutException") + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.getMessage()); + + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("nexus") + .vendorApiId(apiInfo.getAgentId()) + .reqType("withdraw") + .amount(amount) + .reqAt(reqAt) + .reqStatus("FAIL") + .reqMsg("Exception e:"+e.getMessage()) + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + e.printStackTrace(); + } + + return jsonObj; + } + + + @Override + public JSONObject userWithdrawAll(String LOG_PREFIX, NexusApiInfo apiInfo) { + JSONObject jsonObj = null; + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + long reqAtL = System.currentTimeMillis(); + String reqAt = sdf.format(reqAtL); + LOG_PREFIX = LOG_PREFIX + "::userWithdrawAll::"; + + try { + JSONObject bodyObj = new JSONObject(); + bodyObj.put("username", apiInfo.getUsername()); + bodyObj.put("siteUsername", apiInfo.getSiteUsername()); + bodyObj.put("amount", 0); + bodyObj.put("requestKey", Long.toString(reqAtL)); + String bodyJson = bodyObj.toString(); + log.info(LOG_PREFIX+ "bodyJson::"+bodyJson); + + HttpHeaders headers = getHeader(LOG_PREFIX, apiInfo, bodyJson); + UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(apiInfo.getApiBaseUrl() + "/withdraw"); + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("username", apiInfo.getUsername()); + params.add("siteUsername", apiInfo.getSiteUsername()); + params.add("amount", 0); + params.add("requestKey", Long.toString(reqAtL)); + + ResponseEntity response = webClient.post() + .uri(uriBuilder.toUriString()) + .headers(h -> h.addAll(headers)) + .bodyValue(params) + .retrieve() + .toEntity(String.class) + .block(); + + jsonObj = new JSONObject(response.getBody()); + + if(jsonObj.getInt("code") == 0) { + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("nexus") + .vendorApiId(apiInfo.getAgentId()) + .reqType("withdrawAll") + .amount(0) + .reqAt(reqAt) + .reqStatus("SUCC") + .reqMsg("code:"+jsonObj.getInt("code")+", message:"+jsonObj.getDouble("balance")) + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + } else { + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("nexus") + .vendorApiId(apiInfo.getAgentId()) + .reqType("withdrawAll") + .amount(0) + .reqAt(reqAt) + .reqStatus("FAIL") + .reqMsg("code:"+jsonObj.getInt("code")+", message:"+jsonObj.getString("msg")) + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + } + + } catch (WebClientResponseException e) { + log.error(LOG_PREFIX+ "WebClientResponseException::"+e.getMessage()); + log.error(LOG_PREFIX+ "status code::"+e.getStatusCode().value()); + log.error(LOG_PREFIX+ "response body::"+e.getResponseBodyAsString()); + + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("nexus") + .vendorApiId(apiInfo.getAgentId()) + .reqType("withdrawAll") + .amount(0) + .reqAt(reqAt) + .reqStatus("FAIL") + .reqMsg(e.getResponseBodyAsString()) + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof ReadTimeoutException) { + log.error(LOG_PREFIX+ "ReadTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "InterruptedException::"+rae.getMessage()); + } + + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("nexus") + .vendorApiId(apiInfo.getAgentId()) + .reqType("withdrawAll") + .amount(0) + .reqAt(reqAt) + .reqStatus("FAIL") + .reqMsg("TimeoutException") + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.getMessage()); + + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("nexus") + .vendorApiId(apiInfo.getAgentId()) + .reqType("withdrawAll") + .amount(0) + .reqAt(reqAt) + .reqStatus("FAIL") + .reqMsg("Exception e:"+e.getMessage()) + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + e.printStackTrace(); + } + + return jsonObj; + } + + + @Override + public String gameStart(String LOG_PREFIX, NexusApiInfo apiInfo) { + String luanchUrl = null; + long reqAtL = System.currentTimeMillis(); + LOG_PREFIX = LOG_PREFIX + "::gameStart::"; + + try { + JSONObject bodyObj = new JSONObject(); + bodyObj.put("vendorKey", apiInfo.getVendorKey()); + bodyObj.put("gameKey", apiInfo.getGameKey()); + bodyObj.put("siteUsername", apiInfo.getSiteUsername()); + bodyObj.put("nickname", apiInfo.getNickname()); + bodyObj.put("ip", apiInfo.getIp()); + bodyObj.put("language", apiInfo.getLanguage()); + bodyObj.put("platform", apiInfo.getPlatform()); + bodyObj.put("requestKey", Long.toString(reqAtL)); + String bodyJson = bodyObj.toString(); + log.info(LOG_PREFIX+ "bodyJson::"+bodyJson); + + HttpHeaders headers = getHeader(LOG_PREFIX, apiInfo, bodyJson); + UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(apiInfo.getApiBaseUrl() + "/play"); + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("vendorKey", apiInfo.getVendorKey()); + params.add("gameKey", apiInfo.getGameKey()); + params.add("siteUsername", apiInfo.getSiteUsername()); + params.add("nickname", apiInfo.getNickname()); + params.add("ip", apiInfo.getIp()); + params.add("language", apiInfo.getLanguage()); + params.add("platform", apiInfo.getPlatform()); + params.add("requestKey", Long.toString(reqAtL)); + + ResponseEntity response = webClient.post() + .uri(uriBuilder.toUriString()) + .headers(h -> h.addAll(headers)) + .bodyValue(params) + .retrieve() + .toEntity(String.class) + .block(); + + JSONObject resObj = new JSONObject(response.getBody()); + if(resObj.getInt("code") == 0) { + log.info(LOG_PREFIX+ "code::" + resObj.getInt("code")); + log.info(LOG_PREFIX+ "url::" + resObj.getString("url")); + log.info(LOG_PREFIX+ "userId::" + resObj.getInt("userId")); + //log.info(LOG_PREFIX+ "balance::" + resObj.getInt("balance")); + luanchUrl = resObj.getString("url"); + } else { + + + try { + HashMap logParam = new HashMap(); + logParam.put("siteIdx", apiInfo.getSiteIdx()); + logParam.put("memberIdx", apiInfo.getMemberIdx()); + logParam.put("vendorIdx", apiInfo.getVendorKey()); + logParam.put("statusCode",resObj.getInt("code")); + logParam.put("callBackType","LAUNCH"); + logParam.put("callBackReqBody",uriBuilder.toUriString()); + logParam.put("callBackResBody",resObj.getString("msg")); + logParam.put("errorCode", ""); + logParam.put("errorMsg", ""); + logParam.put("regDate",System.currentTimeMillis()); + logParam.put("updDate",null); + callBackDao.insertCallBackErrLog(logParam); + }catch(Exception e) { + + + } + + + log.error(LOG_PREFIX+ "code::" + resObj.getInt("code")); + log.error(LOG_PREFIX+ "message::" + resObj.getString("msg")); + } + + } catch (WebClientResponseException e) { + log.error(LOG_PREFIX+ "WebClientResponseException::"+e.getMessage()); + log.error(LOG_PREFIX+ "status code::"+e.getStatusCode().value()); + log.error(LOG_PREFIX+ "response body::"+e.getResponseBodyAsString()); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof ReadTimeoutException) { + log.error(LOG_PREFIX+ "ReadTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "InterruptedException::"+rae.getMessage()); + } + + try { + HashMap logParam = new HashMap(); + logParam.put("siteIdx", apiInfo.getSiteIdx()); + logParam.put("memberIdx", apiInfo.getMemberIdx()); + logParam.put("vendorIdx", apiInfo.getVendorKey()); + logParam.put("statusCode",500); + logParam.put("callBackType","LAUNCH"); + logParam.put("callBackReqBody",apiInfo.toString()); + logParam.put("callBackResBody",rae.getMessage()); + logParam.put("errorCode", ""); + logParam.put("errorMsg", ""); + logParam.put("regDate",System.currentTimeMillis()); + logParam.put("updDate",null); + callBackDao.insertCallBackErrLog(logParam); + }catch(Exception e) { + + + } + + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.getMessage()); + e.printStackTrace(); + } + + return luanchUrl; + } + + + @Override + public JSONObject getDetail(String LOG_PREFIX, NexusApiInfo apiInfo, String trxId) { + JSONObject jsonObj = null; + LOG_PREFIX = LOG_PREFIX + "::getDetail::"; + + try { + JSONObject bodyObj = new JSONObject(); + bodyObj.put("transactionKeys", trxId); + String bodyJson = bodyObj.toString(); + log.info(LOG_PREFIX+ "bodyJson::"+bodyJson); + + HttpHeaders headers = getHeader(LOG_PREFIX, apiInfo, bodyJson); + UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(apiInfo.getApiBaseUrl() + "/transaction/detail"); + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("transactionKeys", trxId); + + ResponseEntity response = webClient.post() + .uri(uriBuilder.toUriString()) + .headers(h -> h.addAll(headers)) + .bodyValue(params) + .retrieve() + .toEntity(String.class) + .block(); + + jsonObj = new JSONObject(response.getBody()); + + } catch (WebClientResponseException e) { + log.error(LOG_PREFIX+ "WebClientResponseException::"+e.getMessage()); + log.error(LOG_PREFIX+ "status code::"+e.getStatusCode().value()); + log.error(LOG_PREFIX+ "response body::"+e.getResponseBodyAsString()); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof ReadTimeoutException) { + log.error(LOG_PREFIX+ "ReadTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "InterruptedException::"+rae.getMessage()); + } + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.getMessage()); + e.printStackTrace(); + } + + return jsonObj; + } + + + @Override + public JSONObject getDetailUrl(String LOG_PREFIX, NexusApiInfo apiInfo, String trxId) { + JSONObject jsonObj = null; + LOG_PREFIX = LOG_PREFIX + "::getDetailUrl::"; + + try { + JSONObject bodyObj = new JSONObject(); + bodyObj.put("transactionKey", trxId); + bodyObj.put("lang", "ko"); + String bodyJson = bodyObj.toString(); + log.info(LOG_PREFIX+ "bodyJson::"+bodyJson); + + HttpHeaders headers = getHeader(LOG_PREFIX, apiInfo, bodyJson); + UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(apiInfo.getApiBaseUrl() + "/getdetailurl"); + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("transactionKey", trxId); + params.add("lang", "ko"); + + ResponseEntity response = webClient.post() + .uri(uriBuilder.toUriString()) + .headers(h -> h.addAll(headers)) + .bodyValue(params) + .retrieve() + .toEntity(String.class) + .block(); + + jsonObj = new JSONObject(response.getBody()); + + } catch (WebClientResponseException e) { + log.error(LOG_PREFIX+ "WebClientResponseException::"+e.getMessage()); + log.error(LOG_PREFIX+ "status code::"+e.getStatusCode().value()); + log.error(LOG_PREFIX+ "response body::"+e.getResponseBodyAsString()); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof ReadTimeoutException) { + log.error(LOG_PREFIX+ "ReadTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "InterruptedException::"+rae.getMessage()); + } + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.getMessage()); + e.printStackTrace(); + } + + return jsonObj; + } + + + @Override + public JSONObject getTransaction(String LOG_PREFIX, NexusApiInfo apiInfo) { + JSONObject jsonObj = null; + LOG_PREFIX = LOG_PREFIX + "::getTransaction::"; + + try { + JSONObject bodyObj = new JSONObject(); + bodyObj.put("vendorKey", "evolution_casino"); + bodyObj.put("sdate", apiInfo.getSdate()); + bodyObj.put("edate", apiInfo.getEdate()); + bodyObj.put("username", apiInfo.getUsername()); + bodyObj.put("limit", apiInfo.getLimit()); + String bodyJson = bodyObj.toString(); + log.info(LOG_PREFIX+ "bodyJson::"+bodyJson); + + HttpHeaders headers = getHeader(LOG_PREFIX, apiInfo, bodyJson); + UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(apiInfo.getApiBaseUrl() + "/transaction"); + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("vendorKey", "evolution_casino"); + params.add("sdate", apiInfo.getSdate()); + params.add("edate", apiInfo.getEdate()); + params.add("username", apiInfo.getUsername()); + params.add("limit", apiInfo.getLimit()); + + ResponseEntity response = webClient.post() + .uri(uriBuilder.toUriString()) + .headers(h -> h.addAll(headers)) + .bodyValue(params) + .retrieve() + .toEntity(String.class) + .block(); + + jsonObj = new JSONObject(response.getBody()); + + } catch (WebClientResponseException e) { + log.error(LOG_PREFIX+ "WebClientResponseException::"+e.getMessage()); + log.error(LOG_PREFIX+ "status code::"+e.getStatusCode().value()); + log.error(LOG_PREFIX+ "response body::"+e.getResponseBodyAsString()); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof ReadTimeoutException) { + log.error(LOG_PREFIX+ "ReadTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "InterruptedException::"+rae.getMessage()); + } + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.getMessage()); + e.printStackTrace(); + } + + return jsonObj; + } +} diff --git a/src/main/java/com/bb/service/PandaService.java b/src/main/java/com/bb/service/PandaService.java new file mode 100644 index 0000000..9d8f1c5 --- /dev/null +++ b/src/main/java/com/bb/service/PandaService.java @@ -0,0 +1,13 @@ +package com.bb.service; + +import java.util.HashMap; +import java.util.List; + +import com.bb.model.Game; + +public interface PandaService { + + List getGameList(String LOG_PREFIX, HashMap apiInfo); + String getLaunchUrl(String LOG_PREFIX, HashMap apiInfo); + String getDetail(String LOG_PREFIX, HashMap apiInfo); +} diff --git a/src/main/java/com/bb/service/PandaServiceImpl.java b/src/main/java/com/bb/service/PandaServiceImpl.java new file mode 100644 index 0000000..cb5b914 --- /dev/null +++ b/src/main/java/com/bb/service/PandaServiceImpl.java @@ -0,0 +1,213 @@ +package com.bb.service; + +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; + +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.WebClientRequestException; +import org.springframework.web.reactive.function.client.WebClientResponseException; + +import com.bb.model.Game; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class PandaServiceImpl implements PandaService { + + @Autowired + WebClient webClient; + + + @Override + public List getGameList(String LOG_PREFIX, HashMap apiInfo) { + LOG_PREFIX = LOG_PREFIX + "getGameList::"; + List gameList = null; + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8"))); + String apiKey = "Bearer "+apiInfo.get("apiKey").toString(); + headers.set("Authorization", apiKey); + + String apiUrl = apiInfo.get("apiBaseUrl").toString() + "/game/gamelist?"; + String param = "&vendor="+apiInfo.get("apiVendor"); + apiUrl = apiUrl + param; + log.info(LOG_PREFIX+ "apiUrl::"+apiUrl); + + try { + ResponseEntity resEntity = webClient.get() + .uri(apiUrl) + .headers(h -> h.addAll(headers)) + .retrieve() + .toEntity(String.class) + .block(); + if(resEntity != null && resEntity.getStatusCode() == HttpStatus.OK) { + JSONArray games = new JSONArray(resEntity.getBody()); + int length = games.length(); + gameList = new ArrayList<>(); + + for(int i=0; i apiInfo) { + LOG_PREFIX = LOG_PREFIX + "getLaunchUrl::"; + String luanchUrl = ""; + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8"))); + String apiKey = "Bearer "+apiInfo.get("apiKey").toString(); + headers.set("Authorization", apiKey); + + String apiUrl = apiInfo.get("apiBaseUrl").toString() + "/game/launch?"; + String param = "vendor="+apiInfo.get("apiVendor")+"&username="+apiInfo.get("apiUsername") + +"&game_id="+apiInfo.get("apiGameCode")+"&nick_name="+apiInfo.get("apiNickname"); + apiUrl = apiUrl + param; + log.info(LOG_PREFIX+ "apiUrl::"+apiUrl); + + try { + ResponseEntity resEntity = webClient.get() + .uri(apiUrl) + .headers(h -> h.addAll(headers)) + .retrieve() + .toEntity(String.class) + .block(); + if(resEntity != null && resEntity.getStatusCode() == HttpStatus.OK) { + JSONObject responseObj = new JSONObject(resEntity.getBody()); + log.info(LOG_PREFIX+ "Response : " + responseObj.toString()); + + luanchUrl = responseObj.getString("url"); + } + } catch (WebClientResponseException wce) { + log.error(LOG_PREFIX+ "WebClientResponseException::"+wce.getMessage()); + log.error(LOG_PREFIX+ "status code::"+wce.getStatusCode().value()); + log.error(LOG_PREFIX+ "response body::"+wce.getResponseBodyAsString()); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "SocketTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "InterruptedException::"+rae.getMessage()); + } + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.getMessage()); + e.printStackTrace(); + } + + return luanchUrl; + } + + @Override + public String getDetail(String LOG_PREFIX, HashMap apiInfo) { + LOG_PREFIX = LOG_PREFIX + "getDetail::"; + String detailUrl = ""; + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8"))); + String apiKey = "Bearer "+apiInfo.get("apiKey").toString(); + headers.set("Authorization", apiKey); + + String apiUrl = apiInfo.get("apiBaseUrl").toString() + "/transaction/transaction/"+apiInfo.get("tranId"); + log.info(LOG_PREFIX+ "apiUrl::"+apiUrl); + + try { + ResponseEntity resEntity = webClient.get() + .uri(apiUrl) + .headers(h -> h.addAll(headers)) + .retrieve() + .toEntity(String.class) + .block(); + if(resEntity != null && resEntity.getStatusCode() == HttpStatus.OK) { + JSONObject responseObj = new JSONObject(resEntity.getBody()); + log.info(LOG_PREFIX+ "Response : " + responseObj.toString()); + + JSONArray data = responseObj.optJSONArray("data"); + if(data != null) { + detailUrl = data.optJSONObject(0).optJSONObject("dynamo_raw").optJSONObject("external").optJSONObject("detail").getString("url"); + } + } + } catch (WebClientResponseException wce) { + log.error(LOG_PREFIX+ "WebClientResponseException::"+wce.getMessage()); + log.error(LOG_PREFIX+ "status code::"+wce.getStatusCode().value()); + log.error(LOG_PREFIX+ "response body::"+wce.getResponseBodyAsString()); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "SocketTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "InterruptedException::"+rae.getMessage()); + } + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.getMessage()); + e.printStackTrace(); + } + + return detailUrl; + } + +} diff --git a/src/main/java/com/bb/service/PointAsyncService.java b/src/main/java/com/bb/service/PointAsyncService.java new file mode 100644 index 0000000..8d0f1bd --- /dev/null +++ b/src/main/java/com/bb/service/PointAsyncService.java @@ -0,0 +1,28 @@ +package com.bb.service; + +import com.bb.dao.CreditDao; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import java.util.HashMap; + +@Service +@RequiredArgsConstructor +@Slf4j +public class PointAsyncService { + + private final CreditDao creditDao; + + @Async("pointTaskExecutor") + public void processPointAsync(HashMap pointParam, String methodName, String tranId) { + try { + log.info("[{}]::{} pointParam::{}", tranId, methodName, pointParam.toString()); + creditDao.insertCreditPoint(pointParam); + log.info("[{}]::{} creditDao.insertCreditPoint() completed", tranId, methodName); + } catch (Exception e) { + log.error("[{}]::{} Exception::{}", tranId, methodName, e.getMessage()); + } + } +} diff --git a/src/main/java/com/bb/service/PowerBallService.java b/src/main/java/com/bb/service/PowerBallService.java new file mode 100644 index 0000000..79eb94e --- /dev/null +++ b/src/main/java/com/bb/service/PowerBallService.java @@ -0,0 +1,14 @@ +package com.bb.service; + +import java.util.HashMap; + +import org.codehaus.jettison.json.JSONObject; + +public interface PowerBallService { + + //JSONObject registSite(HashMap param, final String LOG_PREFIX); + + //String getLaunchUrl(HashMap param, final String LOG_PREFIX); + + String getGameUrl(HashMap venderInfo, String lOG_PREFIX); +} diff --git a/src/main/java/com/bb/service/PowerBallServiceImpl.java b/src/main/java/com/bb/service/PowerBallServiceImpl.java new file mode 100644 index 0000000..7547c09 --- /dev/null +++ b/src/main/java/com/bb/service/PowerBallServiceImpl.java @@ -0,0 +1,388 @@ +package com.bb.service; + +import java.net.SocketTimeoutException; +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; + +import org.apache.http.conn.ConnectTimeoutException; +import io.netty.handler.timeout.ReadTimeoutException; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.WebClientRequestException; +import org.springframework.web.reactive.function.client.WebClientResponseException; + +import lombok.extern.slf4j.Slf4j; +@Slf4j +@Service +public class PowerBallServiceImpl implements PowerBallService { + + @Autowired + WebClient webClient; +/* + @Override + public JSONObject registSite(HashMap param, String LOG_PREFIX) { + JSONObject jsonObj = null; + // https://api.tpower.cc + final String apiBaseUrl = "https://api.tpower.cc"; + + try { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.set("User-Agent", "PostmanRuntime/7.28.4"); + headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8"))); + + JSONObject params = new JSONObject(); + params.put("siteName", param.get("apiSiteId").toString()); + params.put("siteUrl", "http://lbc.toserver.cc/api/callback/powerball"); + params.put("callbackUrl", "http://lbc.toserver.cc/api/callback/powerball"); + params.put("apiKey", param.get("apiKey").toString()); + + // String apiUrl = param.get("apiBaseUrl").toString() + "/registSite"; + String apiUrl = apiBaseUrl + "/registSite"; + log.info(LOG_PREFIX+ "PowerBall::registSite::"+ "Url: " + apiUrl); + log.info(LOG_PREFIX+ "PowerBall::registSite::"+ "Headers: " + headers.toString()); + log.info(LOG_PREFIX+ "PowerBall::registSite::"+ "Params: " + params.toString()); + + HttpEntity entity = new HttpEntity(params.toString(), headers); + ResponseEntity res = restTemplate.exchange(apiUrl, HttpMethod.POST, entity, String.class); + log.info(LOG_PREFIX+ "PowerBall::registSite::"+ "response : " + res.getBody()); + jsonObj = new JSONObject(res.getBody()); + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "PowerBall::registSite::"+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "PowerBall::registSite::"+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "PowerBall::registSite::"+ "[InterruptedException]"+rae.getMessage()); + } + } catch(HttpClientErrorException hee) { + String str = hee.getResponseBodyAsString(); + log.error(LOG_PREFIX+ "PowerBall::registSite::"+ "[HttpClientErrorException]"+str); + } catch (Exception e) { + log.error(LOG_PREFIX+ "PowerBall::registSite::"+ "[Exception]"+e.toString()); + e.printStackTrace(); + } + + return jsonObj; + } + + @Override + public String getLaunchUrl(HashMap param, String LOG_PREFIX) { + String gameUrl = null; + // https://user.tpower.cc + final String apiBaseUrl = "https://user.tpower.cc"; + + try { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.set("User-Agent", "PostmanRuntime/7.28.4"); + headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8"))); + headers.set("apikey", param.get("apiKey").toString()); + + JSONObject params = new JSONObject(); + params.put("id", param.get("apiUserId").toString()); + params.put("siteName", param.get("apiSiteId").toString()); + params.put("device", param.get("device").toString()); + + // String apiUrl = param.get("apiBaseUrl").toString() + "/auth/" + param.get("apiGameName").toString(); + String apiUrl = apiBaseUrl + "/auth/" + param.get("apiGameName").toString(); + log.info(LOG_PREFIX+ "PowerBall::getLaunchUrl::"+ "Url: " + apiUrl); + log.info(LOG_PREFIX+ "PowerBall::getLaunchUrl::"+ "Headers: " + headers.toString()); + log.info(LOG_PREFIX+ "PowerBall::getLaunchUrl::"+ "Params: " + params.toString()); + + HttpEntity entity = new HttpEntity(params.toString(), headers); + ResponseEntity res = restTemplate.exchange(apiUrl, HttpMethod.POST, entity, String.class); + + JSONObject resObj = new JSONObject(res.getBody()); + if(resObj.getString("result").equals("SUCCESS")) { + JSONObject dataObj = resObj.getJSONObject("data"); + gameUrl = dataObj.getString("url"); + log.info(LOG_PREFIX+ "PowerBall::getLaunchUrl::"+ "gameUrl: " + gameUrl); + } else { + log.error(LOG_PREFIX+ "PowerBall::getLaunchUrl::"+ "ERROR::result : " + resObj.getString("result") + ", message: " + resObj.getString("message")); + } + + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "PowerBall::getLaunchUrl::"+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "PowerBall::getLaunchUrl::"+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "PowerBall::getLaunchUrl::"+ "[InterruptedException]"+rae.getMessage()); + } + } catch(HttpClientErrorException hee) { + String str = hee.getResponseBodyAsString(); + log.error(LOG_PREFIX+ "PowerBall::getLaunchUrl::"+ "[HttpClientErrorException]"+str); + } catch (Exception e) { + log.error(LOG_PREFIX+ "PowerBall::getLaunchUrl::"+ "[Exception]"+e.toString()); + e.printStackTrace(); + } + + return gameUrl; + } +*/ + @Override + public String getGameUrl(HashMap venderInfo, String lOG_PREFIX) { + String gameUrl = ""; + try { + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8"))); + + // 실제 브라우저와 동일한 헤더 순서와 값으로 설정 + headers.set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"); + headers.set("Accept", "application/json, text/plain, */*"); + headers.set("Accept-Language", "ko-KR,ko;q=0.9,en;q=0.8"); + // Accept-Encoding 헤더 제거 또는 단순화 (압축 해제 문제 방지) + // headers.set("Accept-Encoding", "gzip, deflate, br"); + headers.set("Connection", "keep-alive"); + + // Cloudflare 우회를 위한 추가 헤더 + headers.set("Cache-Control", "no-cache"); + headers.set("Pragma", "no-cache"); + headers.set("DNT", "1"); + + // 실제 POST 요청에 맞는 Sec-Fetch 헤더 + headers.set("Sec-Fetch-Dest", "empty"); + headers.set("Sec-Fetch-Mode", "cors"); + headers.set("Sec-Fetch-Site", "same-origin"); + + // Origin과 Referer를 더 구체적으로 설정 + headers.set("Origin", "https://api.tpower.cc"); + headers.set("Referer", "https://api.tpower.cc/api/v1/auth"); + + // JA3 fingerprint 우회를 위한 추가 헤더 + headers.set("sec-ch-ua", "\"Not_A Brand\";v=\"8\", \"Chromium\";v=\"120\", \"Google Chrome\";v=\"120\""); + headers.set("sec-ch-ua-mobile", "?0"); + headers.set("sec-ch-ua-platform", "\"Windows\""); + + + JSONObject params = new JSONObject(); + params.put("userId", venderInfo.get("userId").toString()); + params.put("siteKey", venderInfo.get("vendorApiId").toString()); + params.put("gameKey", venderInfo.get("vendorGameCode").toString()); + + log.info(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "venderInfo: " + venderInfo.toString()); + + HttpEntity entity = new HttpEntity(params.toString(), headers); + + // 307 리다이렉트 처리를 위한 수정된 로직 + ResponseEntity res = null; + int maxRetries = 3; + int retryCount = 0; + + while (retryCount < maxRetries) { + try { + if (retryCount > 0) { + Thread.sleep(2000); // 2초 대기 + log.info(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "Retrying... attempt: " + (retryCount + 1)); + } + + // 307 리다이렉트를 수동으로 처리 + // res = restTemplate.exchange("https://api.tpower.cc/api/v1/auth", HttpMethod.POST, entity, String.class); + + res = webClient.post() + .uri("https://api.tpower.cc/api/v1/auth") + .headers(h -> h.addAll(headers)) + .bodyValue(params.toString()) + .retrieve() + .toEntity(String.class) + .block(); + + log.info(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "Response status: " + res.getStatusCode()); + log.info(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "Response headers: " + res.getHeaders()); + + // 307 리다이렉트 처리 + if (res.getStatusCode().value() == 307) { + String locationHeader = res.getHeaders().getFirst("Location"); + log.info(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "307 Redirect to: " + locationHeader); + + if (locationHeader != null && !locationHeader.isEmpty()) { + // 리다이렉트된 URL로 다시 요청 + log.info(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "Following redirect to: " + locationHeader); + + // 새로운 URL이 상대 경로인 경우 절대 경로로 변환 + String redirectUrl = locationHeader; + if (locationHeader.startsWith("/")) { + redirectUrl = "https://api.tpower.cc" + locationHeader; + } + + // HTTP를 HTTPS로 변경 (보안상 더 안전) + if (redirectUrl.startsWith("http://")) { + redirectUrl = redirectUrl.replace("http://", "https://"); + } + + // 인코딩 문제 해결을 위한 새로운 헤더 설정 + HttpHeaders redirectHeaders = new HttpHeaders(); + redirectHeaders.setContentType(MediaType.APPLICATION_JSON); + redirectHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + redirectHeaders.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8"))); + redirectHeaders.set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"); + redirectHeaders.set("Accept", "application/json, text/plain, */*"); + redirectHeaders.set("Accept-Language", "ko-KR,ko;q=0.9,en;q=0.8"); + redirectHeaders.set("Connection", "keep-alive"); + redirectHeaders.set("Cache-Control", "no-cache"); + + // HttpEntity redirectEntity = new HttpEntity(params.toString(), redirectHeaders); + + // 리다이렉트된 URL로 재요청 + // res = restTemplate.exchange(redirectUrl, HttpMethod.POST, redirectEntity, String.class); + + res = webClient.post() + .uri(redirectUrl) + .headers(h -> h.addAll(redirectHeaders)) + .bodyValue(params.toString()) + .retrieve() + .toEntity(String.class) + .block(); + + log.info(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "Redirect response status: " + res.getStatusCode()); + + // 응답 본문 길이 체크 후 로그 출력 + String responseBody = res.getBody(); + if (responseBody != null) { + // UTF-8으로 다시 디코딩 시도 + try { + byte[] bytes = responseBody.getBytes("ISO-8859-1"); + String utf8Body = new String(bytes, "UTF-8"); + log.info(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "UTF-8 decoded response body: " + + (utf8Body.length() > 1000 ? utf8Body.substring(0, 1000) + "..." : utf8Body)); + responseBody = utf8Body; + } catch (Exception encodingEx) { + log.warn(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "UTF-8 decoding failed, using original: " + + (responseBody.length() > 1000 ? responseBody.substring(0, 1000) + "..." : responseBody)); + } + } + + // 수정된 응답을 다시 설정 + if (responseBody != null) { + res = new ResponseEntity<>(responseBody, res.getHeaders(), res.getStatusCode()); + } + + } else { + log.error(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "307 Redirect but no Location header found"); + retryCount++; + continue; + } + } + + break; // 성공하면 루프 탈출 + + } catch (WebClientResponseException e) { + retryCount++; + if (e.getStatusCode().is5xxServerError()) { + log.warn(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "Server error. Status: " + e.getStatusCode() + ", attempt: " + retryCount); + if (retryCount >= maxRetries) { + log.error(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "Max retries reached. Server error: " + e.getStatusCode()); + throw e; + } + continue; + } else if (e.getStatusCode().is4xxClientError()) { + log.warn(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "Client error. Status: " + e.getStatusCode() + ", attempt: " + retryCount); + if (e.getStatusCode().value() == 403 || e.getStatusCode().value() == 429) { + if (retryCount >= maxRetries) { + throw e; + } + continue; + } else { + throw e; + } + } else { + throw e; + } + } catch (Exception e) { + retryCount++; + log.error(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "Exception in retry loop: " + e.getMessage()); + if (retryCount >= maxRetries) { + throw e; + } + } + } + + // 응답 처리 + if (res != null && res.getBody() != null) { + log.info(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "Final response body: " + res.getBody()); + + JSONObject resObj = new JSONObject(res.getBody()); + if (resObj.has("success") && resObj.getBoolean("success")) { + JSONObject dataObj = resObj.getJSONObject("data"); + gameUrl = dataObj.getString("url"); + log.info(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "gameUrl: " + gameUrl); + } else { + // success가 false인 경우 상세 에러 로그 + log.error(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "API returned success=false"); + if (resObj.has("result")) { + log.error(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "result: " + resObj.getString("result")); + } + if (resObj.has("message")) { + log.error(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "message: " + resObj.getString("message")); + } + if (resObj.has("error")) { + log.error(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "error: " + resObj.getString("error")); + } + } + } else { + log.error(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "Response is null or empty"); + } + + } catch (WebClientResponseException e) { + String str = e.getResponseBodyAsString(); + if (e.getStatusCode().is5xxServerError()) { + log.error(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "[HttpServerErrorException] Status: " + + e.getStatusCode() + ", Body: " + (str != null && str.length() > 500 ? str.substring(0, 500) + "..." : str)); + + // Cloudflare 502 에러 감지 + if (str != null && (str.contains("cloudflare") || str.contains("Bad Gateway") || str.contains("502"))) { + log.error(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "Cloudflare 502 Bad Gateway detected!"); + } + } else if (e.getStatusCode().is4xxClientError()) { + log.error(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "[HttpClientErrorException] Status: " + + e.getStatusCode() + ", Body: " + str); + + // Cloudflare 차단 여부 확인 + if (str != null && (str.contains("cloudflare") || str.contains("Access denied") || str.contains("blocked"))) { + log.error(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "Cloudflare protection detected!"); + } + } + + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(lOG_PREFIX+ "PowerBall::getLaunchUrl::"+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof ReadTimeoutException) { + log.error(lOG_PREFIX+ "PowerBall::getLaunchUrl::"+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(lOG_PREFIX+ "PowerBall::getLaunchUrl::"+ "[InterruptedException]"+rae.getMessage()); + } + } catch (Exception e) { + log.error(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "[Exception]" + e.toString()); + e.printStackTrace(); + } + + return gameUrl; + } +} \ No newline at end of file diff --git a/src/main/java/com/bb/service/PracpService.java b/src/main/java/com/bb/service/PracpService.java new file mode 100644 index 0000000..6a6bcef --- /dev/null +++ b/src/main/java/com/bb/service/PracpService.java @@ -0,0 +1,15 @@ +package com.bb.service; + +import java.util.HashMap; +import java.util.List; + +import org.codehaus.jettison.json.JSONObject; + +import com.bb.model.Game; + +public interface PracpService { + + List getGameList(String LOG_PREFIX, HashMap apiInfo); + String getLaunchUrl(String LOG_PREFIX, HashMap apiInfo); + JSONObject getDetail(String LOG_PREFIX, HashMap apiInfo); +} diff --git a/src/main/java/com/bb/service/PracpServiceImpl.java b/src/main/java/com/bb/service/PracpServiceImpl.java new file mode 100644 index 0000000..f2c0f8d --- /dev/null +++ b/src/main/java/com/bb/service/PracpServiceImpl.java @@ -0,0 +1,277 @@ +package com.bb.service; +import java.util.Arrays; +import java.nio.charset.Charset; + +import java.math.BigInteger; +import java.security.MessageDigest; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; + +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.WebClientRequestException; +import org.springframework.web.reactive.function.client.WebClientResponseException; + +import com.bb.model.Game; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class PracpServiceImpl implements PracpService { + + @Autowired + WebClient webClient; + + private String getAPI_KEY(String LOG_PREFIX, HashMap apiInfo) { + LOG_PREFIX = LOG_PREFIX + "::getAPI_KEY::"; + + String apiKey = ""; + String apiAgentCode = apiInfo.get("apiAgentCode"); + String apiToken = apiInfo.get("apiToken"); + String timeStamp = apiInfo.get("timeStamp"); + + log.info(LOG_PREFIX+ "apiAgentCode::"+apiAgentCode); + log.info(LOG_PREFIX+ "apiToken::"+apiToken); + log.info(LOG_PREFIX+ "timeStamp::"+timeStamp); + + String textA = apiAgentCode+apiToken+timeStamp; + String salt = apiToken; + String textB = textA+salt; + log.info(LOG_PREFIX+ "textB::"+textB); + + try { + MessageDigest md = MessageDigest.getInstance("SHA-256"); + md.update(textB.getBytes("UTF-8")); + byte[] digest = md.digest(); + + StringBuilder sb = new StringBuilder(); + for (byte b : digest) { + sb.append(String.format("%02x", b)); // 항상 2자리(앞에 0 포함) + } + + apiKey = sb.toString(); + log.info(LOG_PREFIX+ "apiKey::"+apiKey); + } catch(Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.getMessage()); + } + + return apiKey; + } + + @Override + public List getGameList(String LOG_PREFIX, HashMap apiInfo) { + LOG_PREFIX = LOG_PREFIX + "getGameList::"; + List gameList = null; + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8"))); + + String apiUrl = apiInfo.get("apiBaseUrl").toString() + "/app/game/list?"; + + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); + long timeStampL = System.currentTimeMillis(); + String timeStamp = sdf.format(timeStampL); + apiInfo.put("timeStamp", timeStamp); + String apiKey = getAPI_KEY(LOG_PREFIX, apiInfo); + String param = "api_key="+apiKey+"×tamp="+timeStamp + +"&agent_code="+apiInfo.get("apiAgentCode")+"&provider_code="+apiInfo.get("apiProviderCode"); + apiUrl = apiUrl + param; + log.info(LOG_PREFIX+ "apiUrl::"+apiUrl); + + try { + ResponseEntity resEntity = webClient.get() + .uri(apiUrl) + .headers(h -> h.addAll(headers)) + .retrieve() + .toEntity(String.class) + .block(); + + if(resEntity != null && resEntity.getStatusCode() == HttpStatus.OK) { + JSONObject responseObj = new JSONObject(resEntity.getBody()); + //log.info(LOG_PREFIX+ "Response : " + responseObj.toString()); + + JSONArray games = responseObj.getJSONArray("data"); + int length = games.length(); + gameList = new ArrayList<>(); + + for(int i=0; i apiInfo) { + LOG_PREFIX = LOG_PREFIX + "getLaunchUrl::"; + String luanchUrl = ""; + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + + String apiUrl = apiInfo.get("apiBaseUrl").toString() + "/app/game/launch"; + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); + long timeStampL = System.currentTimeMillis(); + String timeStamp = sdf.format(timeStampL); + apiInfo.put("timeStamp", timeStamp); + String apiKey = getAPI_KEY(LOG_PREFIX, apiInfo); + + log.info(LOG_PREFIX+ "apiUrl::"+apiUrl); + + try { + JSONObject params = new JSONObject(); + params.put("api_key", apiKey); + params.put("timestamp", timeStamp); + params.put("player_code", apiInfo.get("apiPlayerCode")); + params.put("game_code", apiInfo.get("apiGameCode")); + params.put("agent_code", apiInfo.get("apiAgentCode")); + params.put("provider_code", apiInfo.get("apiProviderCode")); + params.put("country_code", "KR"); + params.put("locale_code", "ko"); + log.info(LOG_PREFIX+ "params::"+params.toString()); + + ResponseEntity resEntity = webClient.post() + .uri(apiUrl) + .headers(h -> h.addAll(headers)) + .bodyValue(params.toString()) + .retrieve() + .toEntity(String.class) + .block(); + + if(resEntity != null && resEntity.getStatusCode() == HttpStatus.OK) { + JSONObject responseObj = new JSONObject(resEntity.getBody()); + log.info(LOG_PREFIX+ "Response : " + responseObj.toString()); + JSONObject dataObj = responseObj.getJSONObject("data"); + luanchUrl = dataObj.getString("game_url"); + } + } catch (WebClientResponseException wce) { + log.error(LOG_PREFIX+ "WebClientResponseException::"+wce.getMessage()); + log.error(LOG_PREFIX+ "status code::"+wce.getStatusCode().value()); + log.error(LOG_PREFIX+ "response body::"+wce.getResponseBodyAsString()); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "SocketTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "InterruptedException::"+rae.getMessage()); + } + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.getMessage()); + e.printStackTrace(); + } + + return luanchUrl; + } + + @Override + public JSONObject getDetail(String LOG_PREFIX, HashMap apiInfo) { + LOG_PREFIX = LOG_PREFIX + "getDetail::"; + JSONObject detailObj = null; + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + + String apiUrl = apiInfo.get("apiBaseUrl").toString() + "/app/game/detail-url?"; + + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); + long timeStampL = System.currentTimeMillis(); + String timeStamp = sdf.format(timeStampL); + apiInfo.put("timeStamp", timeStamp); + String apiKey = getAPI_KEY(LOG_PREFIX, apiInfo); + String param = "api_key="+apiKey+"×tamp="+timeStamp + +"&agent_code="+apiInfo.get("apiAgentCode")+"&uuid="+apiInfo.get("uuid")+"&round_id="+apiInfo.get("round_id")+"&country_code=KR&locale_code=ko"; + apiUrl = apiUrl + param; + log.info(LOG_PREFIX+ "apiUrl::"+apiUrl); + + try { + ResponseEntity resEntity = webClient.get() + .uri(apiUrl) + .headers(h -> h.addAll(headers)) + .retrieve() + .toEntity(String.class) + .block(); + + if(resEntity != null && resEntity.getStatusCode() == HttpStatus.OK) { + JSONObject responseObj = new JSONObject(resEntity.getBody()); + log.info(LOG_PREFIX+ "Response : " + responseObj.toString()); + + detailObj = responseObj.getJSONObject("data"); + } + } catch (WebClientResponseException wce) { + log.error(LOG_PREFIX+ "WebClientResponseException::"+wce.getMessage()); + log.error(LOG_PREFIX+ "status code::"+wce.getStatusCode().value()); + log.error(LOG_PREFIX+ "response body::"+wce.getResponseBodyAsString()); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "SocketTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "InterruptedException::"+rae.getMessage()); + } + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.getMessage()); + e.printStackTrace(); + } + + return detailObj; + } + +} diff --git a/src/main/java/com/bb/service/PragmaticService.java b/src/main/java/com/bb/service/PragmaticService.java new file mode 100644 index 0000000..00198bd --- /dev/null +++ b/src/main/java/com/bb/service/PragmaticService.java @@ -0,0 +1,20 @@ +package com.bb.service; + + + +import java.util.HashMap; +import java.util.List; + +import com.bb.model.Game; +import com.bb.model.PlayParam; + +public interface PragmaticService { + + String getLaunchUrl(String LOG_PREFIX, String token, HashMap venderInfo, PlayParam param, String string) throws Exception ; + + List getGameList(String LOG_PREFIX, HashMap venderInfo) throws Exception; + + String getDetails(String LOG_PREFIX, HashMap betInfo); + + +} diff --git a/src/main/java/com/bb/service/PragmaticServiceImpl.java b/src/main/java/com/bb/service/PragmaticServiceImpl.java new file mode 100644 index 0000000..60cc2f7 --- /dev/null +++ b/src/main/java/com/bb/service/PragmaticServiceImpl.java @@ -0,0 +1,276 @@ +package com.bb.service; + +import com.bb.jwt.JwtManager; +import com.bb.model.Game; +import com.bb.model.PlayParam; +import com.bb.model.Site; +import com.bb.util.StringUtils; + + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.ExpiredJwtException; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONException; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.*; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.stereotype.Service; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.WebClientResponseException; +import org.springframework.web.reactive.function.client.WebClientRequestException; + + + +import java.math.BigDecimal; +import java.util.*; + + + +@Slf4j +@EnableScheduling +@RequiredArgsConstructor +@Service +public class PragmaticServiceImpl implements PragmaticService { + + + @Autowired + WebClient webClient; + + + @Override + public String getLaunchUrl(String LOG_PREFIX, String token, HashMap venderInfo, PlayParam param, String hexMemberId) throws Exception { + String gameUrl = venderInfo.get("vendorApiUrl").toString()+"/IntegrationService/v3/http/CasinoGameAPI/game/url/"; + + //body + MultiValueMap parameters = new LinkedMultiValueMap<>(); + String language = param.getLanguage(); + if(language == null || language.isEmpty()) { + language = "en"; + } else { + language = language.toLowerCase(); + if(language.equals("kr")) { + language = "en"; + } + } + + // String currency = venderInfo.get("currency").toString(); + parameters.add("currency", "VND"); + parameters.add("language", language); + parameters.add("secureLogin", venderInfo.get("vendorApiId").toString()); + parameters.add("externalPlayerId", hexMemberId); + parameters.add("symbol", param.getGameKey()); + parameters.add("token", hexMemberId); + + // hash + String hashString = "currency="+"VND" + + "&externalPlayerId="+hexMemberId + + "&language="+language + + "&secureLogin="+ venderInfo.get("vendorApiId").toString() + + "&symbol="+param.getGameKey() + + "&token="+hexMemberId; + + log.info(LOG_PREFIX+ "Pragmatic hash string:{}", hashString); + parameters.add("hash", StringUtils.md5AndHex(hashString+ venderInfo.get("vendorApiKey").toString())); + log.info(LOG_PREFIX+ "org_pragmatic_gameUrl parameters:{}", parameters.toString()); + //header + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/x-www-form-urlencoded"); + + try { + String responseBody = webClient.post() + .uri(gameUrl) + .headers(h -> h.addAll(header)) + .bodyValue(parameters) + .retrieve() + .bodyToMono(String.class) + .block(); + + JSONObject resdata = new JSONObject(responseBody); + log.info(LOG_PREFIX+ "org_pragmatic_gameUrl res:{}", resdata.toString()); + + return resdata.get("gameURL").toString(); + } catch(WebClientResponseException e) { + log.error(LOG_PREFIX+ "getLaunchUrl HttpClientErrorException : " + e.getMessage()); + log.error(LOG_PREFIX+ "getLaunchUrl status code : " + e.getStatusCode().value()); + log.error(LOG_PREFIX+ "getLaunchUrl response body : " + e.getResponseBodyAsString()); + throw e; + } catch(WebClientRequestException rae) { + if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "getLaunchUrl ConnectTimeoutException::"+rae.getMessage()); + } + if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "getLaunchUrl SocketTimeoutException::"+rae.getMessage()); + } + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "getLaunchUrl InterruptedException::"+rae.getMessage()); + } + throw rae; + } + } + + + @Override + public List getGameList(String LOG_PREFIX, HashMap venderInfo) throws Exception{ + String apiUrl = venderInfo.get("vendorApiUrl").toString()+"/IntegrationService/v3/http/CasinoGameAPI/getCasinoGames"; + MultiValueMap parameters = new LinkedMultiValueMap<>(); + parameters.add("secureLogin", venderInfo.get("vendorApiId").toString()); + List gameList = null; + + log.info(LOG_PREFIX+ "apiUrl:"+apiUrl); + String hashString = "secureLogin="+ venderInfo.get("vendorApiId").toString(); + log.info(hashString); + String hash = StringUtils.md5AndHex(hashString+ venderInfo.get("vendorApiKey").toString()); + parameters.add("hash", hash); + log.info(LOG_PREFIX+ "hash:"+hash); + //header + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/x-www-form-urlencoded"); + + try { + String responseBody = webClient.post() + .uri(apiUrl) + .headers(h -> h.addAll(header)) + .bodyValue(parameters) + .retrieve() + .bodyToMono(String.class) + .block(); + + log.info(LOG_PREFIX+ "res"+ responseBody); + JSONObject resdata = new JSONObject(responseBody); + log.info(LOG_PREFIX+ resdata.toString()); + JSONArray games = resdata.getJSONArray("gameList"); + int length = games.length(); + gameList = new ArrayList<>(); + + for(int i=0; i parameters = new LinkedMultiValueMap<>(); + + + parameters.add("secureLogin", betInfo.get("vendorApiId").toString()); + parameters.add("playerId", playerId); + parameters.add("gameId", betInfo.get("gameIdx").toString()); + parameters.add("roundId", roundId); + + // hash + String hashString = "secureLogin="+ betInfo.get("vendorApiId").toString() + + "&playerId="+playerId + + "&gameId="+betInfo.get("gameIdx").toString() + + "&roundId="+ roundId; + + log.info("Pragmatic hash string:{}", hashString); + parameters.add("hash", StringUtils.md5AndHex(hashString+ betInfo.get("vendorApiKey").toString())); + //header + + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/x-www-form-urlencoded"); + + try { + String responseBody = webClient.post() + .uri(historyUrl) + .headers(h -> h.addAll(header)) + .bodyValue(parameters) + .retrieve() + .bodyToMono(String.class) + .block(); + + JSONObject resdata = new JSONObject(responseBody); + + if(resdata != null) { + return resdata.getString("url"); + } else { + return ""; + } + } catch(WebClientResponseException e) { + log.error(LOG_PREFIX+ "getDetails HttpClientErrorException : " + e.getMessage()); + log.error(LOG_PREFIX+ "getDetails status code : " + e.getStatusCode().value()); + log.error(LOG_PREFIX+ "getDetails response body : " + e.getResponseBodyAsString()); + return ""; + } catch(WebClientRequestException rae) { + if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "getDetails ConnectTimeoutException::"+rae.getMessage()); + } + if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "getDetails SocketTimeoutException::"+rae.getMessage()); + } + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "getDetails InterruptedException::"+rae.getMessage()); + } + return ""; + } + } catch(Exception e) { + log.error("OpenHistoryExtended Exception: ", e); + return ""; + } + } + + +} diff --git a/src/main/java/com/bb/service/SettingService.java b/src/main/java/com/bb/service/SettingService.java new file mode 100644 index 0000000..d9611fe --- /dev/null +++ b/src/main/java/com/bb/service/SettingService.java @@ -0,0 +1,34 @@ +package com.bb.service; + +import java.util.HashMap; +import java.util.List; + +import com.bb.model.BlockGameVO; +import com.bb.model.CmnSearch; +import com.bb.model.SiteVendorSkinVO; + +public interface SettingService { + + List> getSettingVendorList(CmnSearch search); + + List> getSettingSkinList(CmnSearch search); + + int settingVendorSkinSave(SiteVendorSkinVO item); + + List getWhiteIpList(CmnSearch search); + + List> getBlockVendorSelectBoxList(String category); + + List> getBlockVendorSelectBoxList2(CmnSearch search); + + List> getBlockTableSelectBoxList(CmnSearch search); + + String getBlockTableIds(CmnSearch search); + + int blockTableIdSave(BlockGameVO blockGameVO); + + String getVendorTitle(CmnSearch search); + + HashMap getBetRadarApiInfo(String siteId); + +} diff --git a/src/main/java/com/bb/service/SettingServiceImpl.java b/src/main/java/com/bb/service/SettingServiceImpl.java new file mode 100644 index 0000000..f37600e --- /dev/null +++ b/src/main/java/com/bb/service/SettingServiceImpl.java @@ -0,0 +1,108 @@ +package com.bb.service; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.bb.dao.SettingDao; +import com.bb.model.BlockGameVO; +import com.bb.model.CmnSearch; +import com.bb.model.SiteVendorSkinVO; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class SettingServiceImpl implements SettingService { + + @Autowired + SettingDao settingDao; + + + @Override + public List> getSettingVendorList(CmnSearch search) { + // TODO Auto-generated method stub + return settingDao.getSettingVendorList(search); + } + + + @Override + public List> getSettingSkinList(CmnSearch search) { + // TODO Auto-generated method stub + return settingDao.getSettingSkinList(search); + } + + + @Override + public int settingVendorSkinSave(SiteVendorSkinVO item) { + // TODO Auto-generated method stub + return settingDao.settingVendorSkinSave(item); + } + + + @Override + public List getWhiteIpList(CmnSearch search) { + // TODO Auto-generated method stub + String ipListStr = settingDao.getWhiteIpListStr(search); + List ipList = null; + try { + ipList = Arrays.asList(ipListStr.split(",")); + } catch (Exception e) { + log.error("#-API::SETTING::whiteIpList::"+search.getSiteIdx()+"::::" + "Exception::"+e.getMessage()); + } + + return ipList; + } + + + @Override + public List> getBlockVendorSelectBoxList(String category) { + // TODO Auto-generated method stub + return settingDao.getBlockVendorSelectBoxList(category); + } + + + @Override + public List> getBlockVendorSelectBoxList2(CmnSearch search) { + // TODO Auto-generated method stub + return settingDao.getBlockVendorSelectBoxList2(search); + } + + + @Override + public List> getBlockTableSelectBoxList(CmnSearch search) { + // TODO Auto-generated method stub + return settingDao.getBlockTableSelectBoxList(search); + } + + + @Override + public String getBlockTableIds(CmnSearch search) { + // TODO Auto-generated method stub + return settingDao.getBlockTableIds(search); + } + + + @Override + public int blockTableIdSave(BlockGameVO blockGameVO) { + // TODO Auto-generated method stub + return settingDao.blockTableIdSave(blockGameVO); + } + + + @Override + public String getVendorTitle(CmnSearch search) { + // TODO Auto-generated method stub + return settingDao.getVendorTitle(search); + } + + + @Override + public HashMap getBetRadarApiInfo(String siteId) { + // TODO Auto-generated method stub + return settingDao.getBetRadarApiInfo(siteId); + } +} diff --git a/src/main/java/com/bb/service/SiteService.java b/src/main/java/com/bb/service/SiteService.java new file mode 100644 index 0000000..8e2d3e2 --- /dev/null +++ b/src/main/java/com/bb/service/SiteService.java @@ -0,0 +1,460 @@ +package com.bb.service; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import jakarta.servlet.http.HttpServletRequest; + +import org.springframework.security.core.Authentication; + +import com.bb.model.BalanceParam; +import com.bb.model.BetParam; +import com.bb.model.BoardSearch; +import com.bb.model.CashParam; +import com.bb.model.CommonParam; +import com.bb.model.Game; +import com.bb.model.Member; +import com.bb.model.OTPInfo; +import com.bb.model.Site; +import com.bb.model.SitePwdVO; +import com.bb.model.SiteSearch; +import com.bb.model.TrfApiInfo; +import com.bb.model.UserSearch; +import com.bb.model.Vendor; +import com.bb.model.VendorChangeBalanceLogVo; + +public interface SiteService { + + Site getSiteInfo(HttpServletRequest request); + + Site getSiteInfoAPI(HttpServletRequest request); + + Member getMember(CommonParam commonParam); + + Member getMember2(CashParam param); + + void insertMember(CommonParam commonParam); + + HashMap getVenderApiInfo(CommonParam commonParam); + + void commonBetinsert(HashMap tranParam); + + void commonBetinsert2(HashMap tranParam); + + List getCbList(); + + int updateCbApi(HashMap upParam); + + HashMap getSiteApiInfo(HashMap sParam); + + HashMap getSiteApiInfo2(HashMap sParam); + + Site getSiteLogin(Authentication authentication); + + Site getSiteLoginApi(Map loginParam); + + Site getGuestLogin(); + + int getSiteListCnt(SiteSearch search); + List getSiteList(SiteSearch search); + + void addProc(Site site); + + void addProcAPI(Site site); + + Site getSiteInfoMypage(Site loginSite); + + long getSiteCredit(String siteId); + + long getUnderSiteCredit(String siteId); + + long getSitePoint(String siteId); + + HashMap getCreditWait(int i); + + int getSiteUserListCnt(SiteSearch search); + + List getSiteUserList(SiteSearch search); + + int getTranCheck(String tranId); + + void insertError(HashMap eParam); + + int getFinalErr(String refId); + + void updateSid(Member member); + + long getInsureAmt(String siteId); + + long getInsurePointAmt(String siteId); + + List getVenderRateList(Site loginSite); + + int getBetCancelCount(String betId); + + void updateBombKey(Member member); + + Member getMemByBombAccId(HashMap memParam); + + String getBetInfo(BetParam param); + + String getMergedBetRadarLog(String betId); + + List getSiteFlow(Site loginSite); + + void saveVendorRate(HashMap paramMap); + + HashMap getEvoApiInfo(); + + String getSiteIdByRefId(String refId); + + void updateDetailLastTime(HashMap evoInfo); + + void insertBetDetail(Map paramDerail); + + Site getSiteDetail(SiteSearch search); + + Site getSiteSimpleDetail(SiteSearch search); + + HashMap getVenderApiInfoByToken(Map paramV); + + Site getSiteBypassword(Map siteParam); + + void updatePass(Map siteParam); + + void siteUpdate(String LOG_PREFIX, Site site); + + void saveVendorInsurePointRate(HashMap paramMap); + + HashMap getDashInfo(Site loginSite); + + HashMap getDashInfo2(Site loginSite); + + HashMap getMicroApiInfo(); + + int getApiStatus(HashMap tranParam); + + void saveVendorInsureRate(HashMap paramMap); + + void updateVendorUseYn(HashMap paramMap); + + List getSiteVendorList(SiteSearch search); + + List getVendorList(SiteSearch search); + + void siteVenderUpdate(Vendor vendor); + + HashMap getDowinApiInfo(); + + long getSiteMaxBet(HashMap sParam); + + Long getUserMaxBet(HashMap sParam); + + int getBetCheckByHc(String refId); + + void updatePragmaticId(Member member); + + HashMap getProgmaticApiInfo(); + + HashMap getProgmaticApiInfo2(); + + HashMap getSiteApiInfoByPra(HashMap sParam); + + String getlastDepostId(HashMap dParam); + + List getNotUseMemberListProgama(); + + List getGameList(HashMap param); + + HashMap getOnlyVenderInfo(CommonParam commonParam); + + int getBotaAutoCancelCnt(String tranId); + + int getBotaBetCnt(String tranId); + + List getBotaBetListMinute(); + + String getSiteIdByRefId2(String string); + + int getTranIdCheck(String string); + + int getTranIdCheck2(String string); + + HashMap getSiteMember(String string); + + void updateDebitCancel(String refId); + + void insertSiteCallBackLog(HashMap logParam); + + List getBetList(BetParam param); + + List getMonsterGameList(); + + HashMap getProgmaticApiInfo3(String string); + + long getBetCancelAmt(String string); + + int getBetIdCheck(String refId); + + int getBetIdCheck2(String refId); + + int getTranCheck2(String string); + + void insertSlotCity(HashMap slotMap); + + void botaAutoCancel(HashMap tranParam); + + void seattleCredit(); + + void updateDecimal(HashMap decimalParam); + + List getonlyDebitList(); + + void insertAutoLose(HashMap loseCredit); + + HashMap getBetCheck(BetParam param); + + int callbackTokenCheck(String header); + + HashMap getVenderInfo(BalanceParam param); + + String getRefIdByTranId(String string); + + List getCreditReSendList(); + + void updateMemCancelCnt(long memberIdx); + + Long getMemberIdx(HashMap memParam); + + int insertVendorChangeBalanceLog(VendorChangeBalanceLogVo logVo); + + HashMap getGsoftVendorInfo(String gameID); + + HashMap getDemoByBombAccId(HashMap memParam); + + void inserDemoUSer(String bombToken); + + void updateDemoUSer(HashMap memParam); + + List getTrasferVendorList(); + + List getAllMember(); + + int gethourBetCheck(long member); + + List getAllMember2(); + + HashMap getUserVendorInfo(HashMap memParam); + + Member getMemberByToken(Map authParam); + + HashMap getSiteApiInfoByToken(Map authParam); + + double getBetDepositAmt(String string); + + void insertSplusTran(Map trxParam); + + void updateSplusTran(Map trxParam); + + String getCbData(String reserve_id); + + void updatesPurchaseId(Map trxParam); + + double getBetGapAmt(String string); + + void insertToken(String base64Token); + + int getSplusToken(String base64Token); + + String getRefIdByPurchaseId(String purchase_id); + + List getSplusDetailData(BetParam param); + + String getKorName(String string, String homeTeam); + + void forDefaultProc(Site site); + + HashMap getBetInfoByTranId(String reference); + + int getSuccDebitCnt(String betId); + + HashMap getSiteVendorInfo(HashMap param); + + int updatePowerballApiInfo(HashMap registParam); + + List> getPowerBallInfoList(String gameType); + + HashMap getSiteApiInfoByApiKey(HashMap param); + + HashMap getSiteApiInfoByCallbackKey(HashMap param); + + int updMemLastVendorIdx(HashMap memParam); + + List getVendorListByVendorKey(HashMap venderInfo); + + void vendorUpdate(HashMap venderInfo); + + List getNexusSkinListByVendorKey(HashMap venderInfo); + + void nexusSkinUpdate(HashMap venderInfo); + + String getParseTarget(); + + String getParseTargetExtr(); + + HashMap getParseUseYn(int siteIdx); + + void insertParseUse(HashMap parseParam); + + List getApiBetVendorList(int siteIdx); + + int getApiBetTransactionCnt(BetParam param); + + List getApiBetTransactionList(BetParam param); + + HashMap getParseUserYn(HashMap pum); + + void setParseUserYn(HashMap pum); + + OTPInfo getOtpInfo(long siteIdx); + + OTPInfo getOtpInfoByManger(long siteIdx); + + int registSuperOtp(OTPInfo param); + + HashMap getSiteOnlyVendorInfo(HashMap vendorParam); + + TrfApiInfo getTrfApiInfo(HashMap mapParam); + + void agentIpsUpdate(Site site); + + int insertEvoDetail(HashMap detailMap); + + HashMap getCommonApiInfo(HashMap commonParam); + + HashMap getBeforeTranInfo(String vendorTranKey); + + List getParseTargetGame(String gameType); + + String getOrgDetailData(BetParam param); + + String getParDetailData(BetParam param); + + HashMap getBetInfoByTranKey(String vendorTranKey); + + HashMap getParseInfo(HashMap param); + + int getBlockParseGameId(String gameId); + + HashMap getBeforeTranInfo2(String vendorTranKey); + + String getMemberByIdx(HashMap memParam); + + List getSiteVendorList2(int siteIdx); + + List getVendorList2(int siteIdx); + + void saveSvcr(HashMap paramMap, int type); + + String getSiteKey(HashMap paramMap); + + String getVendorTitle(HashMap paramMap); + + Long getUserTimeout(HashMap accLog); + + int updateUserTimeout(HashMap accLog); + + String getGameKeyByNexusGameId(String gameId); + + String getDebitIsParse(String betId); + + int updateParseUseYN(String useYn); + + int insertTheaTrxId(HashMap param); + + HashMap getApiKeyInfo(String vendorTitle); + + HashMap getApiKeyInfo2(HashMap keyParam); + + HashMap getRefBetInfoByTranId(String tranId); + + int updMemberBalance(HashMap balanceMap); + + int getMemberBalance(HashMap balanceMap); + + HashMap getMemberId(String vendorUsername); + + int checkMemberId(String vendorUsername); + + HashMap getNewSiteApiInfo(String vendorUsername); + + HashMap getNewSiteVendorInfo(HashMap param); + + int updateTestCnt(Site site); + + int updateParseEvoYn(HashMap param); + + int saveParsEvoAmount(SiteSearch param); + + int getUserBalance(HashMap balanceMap); + + List getMyDownSite(SiteSearch search); + + HashMap getCreditInfo(String siteId); + + int checkDownSite(Map checkDown); + + List getSiteTreeList(String siteId); + + int getMyDownSiteCheck(Site targetsite); + + void siteUpdateForAPI(Site site); + + int updateSitePwd(SitePwdVO sitePwdVO); + + Site getSite(Site addsite); + + void siteVenderLobbyUpdate(Vendor vendor); + + List getVendorMapList(SiteSearch search); + + String siteVenderRate(Vendor vendor); + + int getBoardListCnt(BoardSearch search); + + List> getBoardList(BoardSearch search); + + HashMap getBoardDetail(long boardIdx); + + int getSiteCallbackErrLogListCnt(SiteSearch search); + + List getSiteCallbackErrLogList(SiteSearch search); + + int getUserListCnt(UserSearch search); + + List> getUserList(UserSearch search); + + HashMap getUserDetail(UserSearch search); + + int getSiteListCntForApi(SiteSearch search); + + List getSiteListForApi(SiteSearch search); + + Site getSiteDetailForApi(SiteSearch search); + + List getVendorListForApi(SiteSearch search); + + List getSiteVendorListForApi(SiteSearch search); + + HashMap getRefIdByVendorTranKey(String vendorTranKey); + + int updateUserMaxBet(HashMap param); + + int insertTranLog(HashMap logParam); + + HashMap getSiteSubCredit(String siteId); + + String getBetAmountByTranParam(HashMap param); + +} diff --git a/src/main/java/com/bb/service/SiteServiceImpl.java b/src/main/java/com/bb/service/SiteServiceImpl.java new file mode 100644 index 0000000..d99d350 --- /dev/null +++ b/src/main/java/com/bb/service/SiteServiceImpl.java @@ -0,0 +1,1943 @@ +package com.bb.service; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import jakarta.servlet.http.HttpServletRequest; + +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.scheduling.annotation.Async; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Service; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.support.DefaultTransactionDefinition; + +import com.bb.dao.CallBackDao; +import com.bb.dao.CreditDao; +import com.bb.dao.SiteDao; +import com.bb.model.BalanceParam; +import com.bb.model.BetParam; +import com.bb.model.BoardSearch; +import com.bb.model.CashParam; +import com.bb.model.CommonParam; +import com.bb.model.Credit; +import com.bb.model.Game; +import com.bb.model.Member; +import com.bb.model.OTPInfo; +import com.bb.model.Site; +import com.bb.model.SitePwdVO; +import com.bb.model.SiteSearch; +import com.bb.model.TrfApiInfo; +import com.bb.model.UserSearch; +import com.bb.model.Vendor; +import com.bb.model.VendorChangeBalanceLogVo; +import com.bb.util.IPKit; + +import lombok.extern.slf4j.Slf4j; + + +@Slf4j +@Service +public class SiteServiceImpl implements SiteService{ + + @Autowired + private SiteDao siteDao; + + @Autowired + private CreditDao creditDao; + + @Autowired + private CallBackDao callBackDao; + + @Autowired + private PointAsyncService pointAsyncService; + + @Autowired + private DataSourceTransactionManager transactionManager; + + + public Site getSiteInfo(HttpServletRequest request) { + String Authorization = request.getHeader("Authorization").toString(); + Site site = siteDao.getSiteInfo(Authorization); + return site; + } + + + public Site getSiteInfoAPI(HttpServletRequest request) { + String Authorization = request.getHeader("Authorization").toString(); + Site site = siteDao.getSiteInfoAPI(Authorization); + return site; + } + + + @Override + public Member getMember(CommonParam commonParam) { + // TODO Auto-generated method stub + return siteDao.getMember(commonParam); + } + + @Override + public Member getMember2(CashParam param) { + // TODO Auto-generated method stub + return siteDao.getMember2(param); + } + + @Override + public void insertMember(CommonParam commonParam) { + // TODO Auto-generated method stub + siteDao.insertMember(commonParam); + } + + + @Override + public HashMap getVenderApiInfo(CommonParam commonParam) { + return siteDao.getVenderApiInfo(commonParam); + } + + + @Override + public List getCbList() { + // TODO Auto-generated method stub + return siteDao.getCbList(); + } + + + @Override + public int updateCbApi(HashMap upParam) { + //TransactionStatus txStatus = transactionManager.getTransaction(new DefaultTransactionDefinition()); + int res =0; + try { + + if("debit".equals(upParam.get("tranType"))) { + updateCbApiDebit(upParam); + } else { + updateCbApiCredit(upParam); + } + + } catch(Exception e) { + System.out.println(e.toString()); + //transactionManager.rollback(txStatus); + res =-1; + }finally { + return res; + } + } + + @Async + public void updateCbApiDebit(HashMap upParam) throws Exception { + log.info("["+upParam.get("tranId").toString()+"]::"+"updateCbApiDebit() start"); + + long siteCredit = siteDao.getSiteCredit((String)upParam.get("siteId")); + + String creditRate = siteDao.getCreditRate(upParam); + + // ##--isTransfer 처리-## + String isTransfer = "N"; + if(upParam.containsKey("isTransfer")) isTransfer = upParam.get("isTransfer").toString(); + String isTie = upParam.get("isTie").toString(); // N:정품, P:파싱 + String vendorCetegory = upParam.get("vendorCetegory").toString(); + + int gameCategory = 0; + if(vendorCetegory.equals("CASINO") && isTie.equals("N")) { + gameCategory = 1; // 카지노A + } else if(vendorCetegory.equals("CASINO") && isTie.equals("P")) { + gameCategory = 2; // 카지노B + } else if(vendorCetegory.equals("SLOT") && isTie.equals("N")) { + gameCategory = 3; // 슬롯A + } else if(vendorCetegory.equals("SLOT") && isTie.equals("P")) { + gameCategory = 4; // 슬롯B + } else { + gameCategory = 5; + } + + Credit credit = new Credit(); + credit.setSiteIdx(Integer.parseInt(upParam.get("siteIdx").toString())); + credit.setSiteId(upParam.get("siteId").toString()); + credit.setTranId((String)upParam.get("tranId")); + credit.setPreCreditAmt(siteCredit); + credit.setCreditRate(creditRate); + credit.setCreditStatus(1); + credit.setRefId(upParam.get("refId").toString()); + + if(isTransfer.equals("N")) { + credit.setTargetSiteIdx(Integer.parseInt(upParam.get("siteIdx").toString())); + credit.setTargetSiteId(upParam.get("siteId").toString()); + credit.setCreditType("DP"); + credit.setInOut("OUT"); + credit.setCreditAmt((long) Math.ceil(Double.parseDouble(upParam.get("depositAmt").toString()))); + credit.setGameCategory(gameCategory); + creditDao.insertCredit(credit); + log.info("["+upParam.get("tranId").toString()+"]::"+"updateCbApiDebit() creditDao.insertCredit()"); + } else { + credit.setTargetSiteIdx(Integer.parseInt(upParam.get("memberIdx").toString())); + credit.setTargetSiteId(upParam.get("memberId").toString()); + credit.setCreditType("MDP"); + credit.setInOut("OUT"); + credit.setCreditAmt((long) Math.ceil(Double.parseDouble(upParam.get("depositAmt").toString()))); + credit.setUserAmt((long) Math.ceil(Double.parseDouble(upParam.get("depositAmt").toString()))); + credit.setPreBalance(Long.parseLong(upParam.get("preBalance").toString())); + credit.setGameCategory(gameCategory); + creditDao.insertCreditByCash(credit); + log.info("["+upParam.get("tranId").toString()+"]::"+"updateCbApiDebit() creditDao.insertCredit()"); + } + + // 포인트 처리 비동기 실행 + if(credit.getCreditAmt() > 0 && isTransfer.equals("N")) { + HashMap pointParam = new HashMap(); + pointParam.put("siteIdx", Long.parseLong(upParam.get("siteIdx").toString())); + pointParam.put("siteId", upParam.get("siteId").toString()); + pointParam.put("memberIdx", Long.parseLong(upParam.get("memberIdx").toString())); + pointParam.put("memberId", upParam.get("memberId").toString()); + pointParam.put("vendor", upParam.get("vendorCode").toString()); + pointParam.put("vendorIdx", Integer.parseInt(upParam.get("vendorIdx").toString())); + pointParam.put("tranId", upParam.get("tranId").toString()); + pointParam.put("betId", upParam.get("refId").toString()); + pointParam.put("amount", (credit.getCreditAmt()*-1)); + + pointAsyncService.processPointAsync(pointParam, "updateCbApiDebit", upParam.get("tranId").toString()); + } + + siteDao.updateCbApi(upParam); + log.info("["+upParam.get("tranId").toString()+"]::"+"updateCbApiDebit() end"); + } + + @Async + public void updateCbApiCredit(HashMap upParam) throws Exception { + + log.info("["+upParam.get("tranId").toString()+"]::"+"updateCbApiCredit() start"); + + long siteCredit = siteDao.getSiteCredit((String)upParam.get("siteId")); + + String creditRate = siteDao.getCreditRate(upParam); + + // ##--isTransfer 처리-## + String isTransfer = "N"; + if(upParam.containsKey("isTransfer")) isTransfer = upParam.get("isTransfer").toString(); + String isTie = upParam.get("isTie").toString(); // N:정품, P:파싱 + String vendorCetegory = upParam.get("vendorCetegory").toString(); + + int gameCategory = 0; + if(vendorCetegory.equals("CASINO") && isTie.equals("N")) { + gameCategory = 1; // 카지노A + } else if(vendorCetegory.equals("CASINO") && isTie.equals("P")) { + gameCategory = 2; // 카지노B + } else if(vendorCetegory.equals("SLOT") && isTie.equals("N")) { + gameCategory = 3; // 슬롯A + } else if(vendorCetegory.equals("SLOT") && isTie.equals("P")) { + gameCategory = 4; // 슬롯B + } else { + gameCategory = 5; + } + + Credit credit = new Credit(); + credit.setSiteIdx(Integer.parseInt(upParam.get("siteIdx").toString())); + credit.setSiteId(upParam.get("siteId").toString()); + credit.setTranId((String)upParam.get("tranId")); + credit.setPreCreditAmt(siteCredit); + credit.setCreditRate(creditRate); + credit.setCreditStatus(1); + credit.setRefId(upParam.get("refId").toString()); + + if(isTransfer.equals("N")) { + credit.setTargetSiteIdx(Integer.parseInt(upParam.get("siteIdx").toString())); + credit.setTargetSiteId(upParam.get("siteId").toString()); + long creditAmt = 0; + long overCreditAmt = 0; + credit.setCreditType("CD"); + credit.setInOut("IN"); + if(upParam.containsKey("overCreditAmt")) { + log.info("["+upParam.get("tranId").toString()+"]::"+"초과당첨금처리 start"); + creditAmt = (long) Math.ceil(Double.parseDouble(upParam.get("creditAmt").toString())); + overCreditAmt = (long) Math.ceil(Double.parseDouble(upParam.get("overCreditAmt").toString())); + log.info("["+upParam.get("tranId").toString()+"]::"+"creditAmt : " + creditAmt); + log.info("["+upParam.get("tranId").toString()+"]::"+"overCreditAmt : " + overCreditAmt); + creditAmt = creditAmt + overCreditAmt; + log.info("["+upParam.get("tranId").toString()+"]::"+"합계 : " + creditAmt); + credit.setCreditAmt(creditAmt); + log.info("["+upParam.get("tranId").toString()+"]::"+"초과당첨금처리 end"); + } else { + credit.setCreditAmt((long) Math.ceil(Double.parseDouble(upParam.get("creditAmt").toString()))); + } + credit.setGameCategory(gameCategory); + creditDao.updateCreditYn(credit); + creditDao.insertCredit(credit); + log.info("["+upParam.get("tranId").toString()+"]::"+"updateCbApiCredit() creditDao.insertCredit()"); + } else { + credit.setTargetSiteIdx(Integer.parseInt(upParam.get("memberIdx").toString())); + credit.setTargetSiteId(upParam.get("memberId").toString()); + long creditAmt = 0; + long userAmt = 0; + long overCreditAmt = 0; + credit.setCreditType("MCD"); + credit.setInOut("IN"); + if(upParam.containsKey("overCreditAmt")) { + log.info("["+upParam.get("tranId").toString()+"]::"+"초과당첨금처리 start"); + creditAmt = (long) Math.ceil(Double.parseDouble(upParam.get("creditAmt").toString())); + userAmt = (long) Math.ceil(Double.parseDouble(upParam.get("creditAmt").toString())); + overCreditAmt = (long) Math.ceil(Double.parseDouble(upParam.get("overCreditAmt").toString())); + log.info("["+upParam.get("tranId").toString()+"]::"+"creditAmt : " + creditAmt); + log.info("["+upParam.get("tranId").toString()+"]::"+"userAmt : " + userAmt); + log.info("["+upParam.get("tranId").toString()+"]::"+"overCreditAmt : " + overCreditAmt); + creditAmt = creditAmt + overCreditAmt; + credit.setUserAmt(userAmt); + log.info("["+upParam.get("tranId").toString()+"]::"+"creditAmt 합계 : " + creditAmt); + log.info("["+upParam.get("tranId").toString()+"]::"+"userAmt 합계 : " + userAmt); + credit.setCreditAmt(creditAmt); + log.info("["+upParam.get("tranId").toString()+"]::"+"초과당첨금처리 end"); + } else { + credit.setCreditAmt((long) Math.ceil(Double.parseDouble(upParam.get("creditAmt").toString()))); + credit.setUserAmt((long) Math.ceil(Double.parseDouble(upParam.get("creditAmt").toString()))); + } + credit.setPreBalance(Long.parseLong(upParam.get("preBalance").toString())); + credit.setGameCategory(gameCategory); + creditDao.updateCreditYn(credit); + creditDao.insertCreditByCash(credit); + log.info("["+upParam.get("tranId").toString()+"]::"+"updateCbApiCredit() creditDao.insertCredit()"); + } + + // 포인트 처리 비동기 실행 + if(credit.getCreditAmt() > 0 && isTransfer.equals("N")) { + HashMap pointParam = new HashMap(); + pointParam.put("siteIdx", Long.parseLong(upParam.get("siteIdx").toString())); + pointParam.put("siteId", upParam.get("siteId").toString()); + pointParam.put("memberIdx", Long.parseLong(upParam.get("memberIdx").toString())); + pointParam.put("memberId", upParam.get("memberId").toString()); + pointParam.put("vendor", upParam.get("vendorCode").toString()); + pointParam.put("vendorIdx", Integer.parseInt(upParam.get("vendorIdx").toString())); + pointParam.put("tranId", upParam.get("tranId").toString()); + pointParam.put("betId", upParam.get("refId").toString()); + pointParam.put("amount", credit.getCreditAmt()); + + pointAsyncService.processPointAsync(pointParam, "updateCbApiCredit", upParam.get("tranId").toString()); + } + + siteDao.updateCbApi(upParam); + log.info("["+upParam.get("tranId").toString()+"]::"+"updateCbApiCredit() end"); + } + + + @Override + public HashMap getSiteApiInfo(HashMap sParam) { + return siteDao.getSiteApiInfo(sParam); + } + + + @Override + public HashMap getSiteApiInfo2(HashMap sParam) { + return siteDao.getSiteApiInfo2(sParam); + } + + + @Override + public void commonBetinsert(HashMap tranParam) { + // TODO Auto-generated method stub + siteDao.commonBetinsert(tranParam); + + if("credit".equals(tranParam.get("tranType").toString())) { + if(tranParam.get("detail") != null) { + siteDao.insertBetDetail(tranParam); + } + } + } + + + @Override + public void commonBetinsert2(HashMap tranParam) { + // TODO Auto-generated method stub + siteDao.commonBetinsert2(tranParam); + } + + + @Override + public Site getSiteLogin(Authentication authentication) { + return siteDao.getSiteLogin(authentication); + } + + @Override + public Site getSiteLoginApi(Map site) { + return siteDao.getSiteLoginApi(site); + } + + + @Override + public Site getGuestLogin() { + return siteDao.getGuestLogin(); + } + + + @Override + public int getSiteListCnt(SiteSearch search) { + return siteDao.getSiteListCnt(search); + } + + + @Override + public List getSiteList(SiteSearch search) { + return siteDao.getSiteList(search); + } + + + @Override + public void addProc(Site site) { + + TransactionStatus txStatus = transactionManager.getTransaction(new DefaultTransactionDefinition()); + try { + siteDao.addProc(site); + siteDao.addCreditInfo(site); + siteDao.addPointInfo(site); + siteDao.addsiteFlow(site); + + //벤더 설정 + siteDao.insertVendors(site); + siteDao.insertVendorsRate(site); + siteDao.insertVendorsCodeRate(site); + + //보험관련 + siteDao.insertinsurance(site); + siteDao.insertinsurancePoint(site); + + // Add Firewall rule + try { + if (site.getSiteIp() != null && !site.getSiteIp().equals("")) { + log.info("#-super::SITE_ADD_PROC:::Call IPKit.allowInboundTraffic() ips: " + site.getSiteIp()); + IPKit.allowInboundTraffic("#-super::SITE_ADD_PROC:::", site.getSiteIp()); + log.info("#-super::SITE_ADD_PROC:::Call IPKit.allowInboundTraffic() end:"); + } + } catch (Exception e) { + System.out.println(e.toString()); + log.error("#-super::SITE_ADD_PROC:::"+ "Exception: "+e.getMessage()); + log.error("#-super::SITE_ADD_PROC:::"+ "Exception: "+e.toString()); + } + + transactionManager.commit(txStatus); + } catch(Exception e) { + System.out.println(e.toString()); + transactionManager.rollback(txStatus); + } + } + + @Override + public void addProcAPI(Site site) { + + TransactionStatus txStatus = transactionManager.getTransaction(new DefaultTransactionDefinition()); + try { + siteDao.addProc(site); + siteDao.addCreditInfo(site); + siteDao.addPointInfo(site); + siteDao.addsiteFlow(site); + + //벤더 설정 + siteDao.insertVendors(site); + siteDao.insertVendorsRate(site); + siteDao.insertVendorsCodeRate(site); + + + //보험관련 + siteDao.insertinsurance(site); + siteDao.insertinsurancePoint(site); + + //IP테이블 생성 + siteDao.insertCmsIp(site); + transactionManager.commit(txStatus); + } catch(Exception e) { + System.out.println(e.toString()); + transactionManager.rollback(txStatus); + } + } + + + @Override + public Site getSiteInfoMypage(Site site) { + return siteDao.getSiteInfoMypage(site); + } + + + @Override + public long getSiteCredit(String siteId) { + return siteDao.getSiteCredit(siteId); + } + + + @Override + public long getUnderSiteCredit(String siteId) { + return siteDao.getUnderSiteCredit(siteId); + } + + @Override + public long getSitePoint(String siteId) { + return siteDao.getSitePoint(siteId); + } + + + @Override + public HashMap getCreditWait(int siteIdx) { + return siteDao.getCreditWait(siteIdx); + } + + + @Override + public int getSiteUserListCnt(SiteSearch search) { + return siteDao.getSiteUserListCnt(search); + } + + + @Override + public List getSiteUserList(SiteSearch search) { + return siteDao.getSiteUserList(search); + } + + + @Override + public int getTranCheck(String tranId) { + // TODO Auto-generated method stub + return siteDao.getTranCheck(tranId); + } + + + @Override + public void insertError(HashMap eParam) { + // TODO Auto-generated method stub + siteDao.insertError(eParam); + } + + + @Override + public int getFinalErr(String refId) { + // TODO Auto-generated method stub + return siteDao.getFinalErr(refId); + } + + + @Override + public void updateSid(Member member) { + siteDao.updateSid(member); + } + + + @Override + public long getInsureAmt(String siteId) { + return siteDao.getInsureAmt(siteId); + } + + + @Override + public long getInsurePointAmt(String siteId) { + return siteDao.getInsurePointAmt(siteId); + } + + + @Override + public List getVenderRateList(Site loginSite) { + // TODO Auto-generated method stub + return siteDao.getVenderRateList(loginSite); + } + + + @Override + public synchronized int getBetCancelCount(String betId) { + // TODO Auto-generated method stub + return siteDao.getBetCancelCount(betId); + } + + + @Override + public void updateBombKey(Member member) { + // TODO Auto-generated method stub + siteDao.updateBombKey(member); + } + + + @Override + public Member getMemByBombAccId(HashMap memParam) { + return siteDao.getMemByBombAccId(memParam); + } + + + @Override + public String getBetInfo(BetParam param) { + // TODO Auto-generated method stub + return siteDao.getBetInfo(param); + } + + + @Override + public String getMergedBetRadarLog(String betId) { + try { + List radarLogs = callBackDao.getBetRadarLogByBetId(betId); + if(radarLogs == null || radarLogs.isEmpty()) { + return null; + } + + // 베팅과 결과를 구분하여 반환 + JSONObject responseJson = new JSONObject(); + + // 첫 번째 row: 베팅 데이터 + if(radarLogs.size() >= 1) { + String bettingStr = (String) radarLogs.get(0).get("jsonstr"); + if(bettingStr != null && !bettingStr.isEmpty()) { + JSONObject bettingJson = new JSONObject(bettingStr); + responseJson.put("betting", bettingJson); + } + } + + // 두 번째 row: 결과 데이터 (있는 경우만) + if(radarLogs.size() >= 2) { + String resultStr = (String) radarLogs.get(1).get("jsonstr"); + if(resultStr != null && !resultStr.isEmpty()) { + JSONObject resultJson = new JSONObject(resultStr); + responseJson.put("result", resultJson); + } + } + + return responseJson.toString(); + } catch(Exception e) { + log.error("getMergedBetRadarLog error: " + e.getMessage()); + return null; + } + } + + + @Override + public List getSiteFlow(Site loginSite) { + // TODO Auto-generated method stub + return siteDao.getSiteFlow(loginSite); + + } + + + @Override + public void saveVendorRate(HashMap paramMap) { + // TODO Auto-generated method stub + siteDao.saveVendorRate(paramMap); + } + + + @Override + public HashMap getEvoApiInfo() { + // TODO Auto-generated method stub + return siteDao.getEvoApiInfo(); + } + + + @Override + public String getSiteIdByRefId(String refId) { + // TODO Auto-generated method stub + return siteDao.getSiteIdByRefId(refId); + } + + + @Override + public void updateDetailLastTime(HashMap evoInfo) { + // TODO Auto-generated method stub + siteDao.updateDetailLastTime(evoInfo); + } + + + @Override + public void insertBetDetail(Map paramDerail) { + siteDao.insertBetDetail(paramDerail); + + } + + + @Override + public Site getSiteDetail(SiteSearch search) { + // TODO Auto-generated method stub + return siteDao.getSiteDetail(search); + } + + + @Override + public Site getSiteSimpleDetail(SiteSearch search) { + // TODO Auto-generated method stub + return siteDao.getSiteSimpleDetail(search); + } + + + @Override + public HashMap getVenderApiInfoByToken(Map paramV) { + // TODO Auto-generated method stub + return siteDao.getVenderApiInfoByToken(paramV); + } + + + @Override + public Site getSiteBypassword(Map siteParam) { + // TODO Auto-generated method stub + return siteDao.getSiteBypassword(siteParam); + } + + + @Override + public void updatePass(Map siteParam) { + siteDao.updatePass(siteParam); + + } + + + @Override + public void siteUpdate(String LOG_PREFIX, Site site) { + // TODO Auto-generated method stub + siteDao.siteUpdate(site); + + // Add Firewall rule + try { + if (site.getSiteIp() != null && !site.getSiteIp().equals("")) { + log.info(LOG_PREFIX+ "Call IPKit.allowInboundTraffic() ips: " + site.getSiteIp()); + IPKit.allowInboundTraffic(LOG_PREFIX, site.getSiteIp()); + log.info(LOG_PREFIX+ "Call IPKit.allowInboundTraffic() end:"); + } + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception: "+e.getMessage()); + log.error(LOG_PREFIX+ "Exception: "+e.toString()); + } + } + + + @Override + public void saveVendorInsurePointRate(HashMap paramMap) { + // TODO Auto-generated method stub + siteDao.saveVendorInsurePointRate(paramMap); + } + + + @Override + public HashMap getDashInfo(Site loginSite) { + // TODO Auto-generated method stub + return siteDao.getDashInfo(loginSite); + } + + @Override + public HashMap getDashInfo2(Site loginSite) { + // TODO Auto-generated method stub + return siteDao.getDashInfo2(loginSite); + } + + + @Override + public HashMap getMicroApiInfo() { + // TODO Auto-generated method stub + return siteDao.getMicroApiInfo(); + } + + + @Override + public int getApiStatus(HashMap tranParam) { + // TODO Auto-generated method stub + return siteDao.getApiStatus(tranParam); + } + + + @Override + public void saveVendorInsureRate(HashMap paramMap) { + // TODO Auto-generated method stub + siteDao.saveVendorInsureRate(paramMap); + } + + + @Override + public void updateVendorUseYn(HashMap paramMap) { + // TODO Auto-generated method stub + siteDao.updateVendorUseYn(paramMap); + + } + + + @Override + public List getSiteVendorList(SiteSearch search) { + // TODO Auto-generated method stub + return siteDao.getSiteVendorList(search); + } + + + @Override + public List getVendorList(SiteSearch search) { + // TODO Auto-generated method stub + return siteDao.getVendorList(search); + } + + + @Override + public void siteVenderUpdate(Vendor vendor) { + // TODO Auto-generated method stub + siteDao.siteVenderUpdate(vendor); + } + + + @Override + public HashMap getDowinApiInfo() { + // TODO Auto-generated method stub + return siteDao.getDowinApiInfo(); + } + + + @Override + public long getSiteMaxBet(HashMap sParam) { + // TODO Auto-generated method stub + return siteDao.getSiteMaxBet(sParam); + } + + @Override + public Long getUserMaxBet(HashMap sParam) { + // TODO Auto-generated method stub + return siteDao.getUserMaxBet(sParam); + } + + @Override + public synchronized int getBetCheckByHc(String refId) { + // TODO Auto-generated method stub + return siteDao.getBetCheckByHc(refId); + } + + + @Override + public void updatePragmaticId(Member member) { + // TODO Auto-generated method stub + siteDao.updatePragmaticId(member); + } + + + @Override + public HashMap getProgmaticApiInfo() { + // TODO Auto-generated method stub + return siteDao.getProgmaticApiInfo(); + } + + @Override + public HashMap getProgmaticApiInfo2() { + // TODO Auto-generated method stub + return siteDao.getProgmaticApiInfo2(); + } + + + @Override + public HashMap getSiteApiInfoByPra(HashMap sParam) { + // TODO Auto-generated method stub + return siteDao.getSiteApiInfoByPra(sParam); + } + + + @Override + public String getlastDepostId(HashMap dParam) { + // TODO Auto-generated method stub + return siteDao.getlastDepostId(dParam); + } + + + @Override + public List getNotUseMemberListProgama() { + // TODO Auto-generated method stub + return siteDao.getNotUseMemberListProgama(); + } + + + @Override + public List getGameList(HashMap param) { + // TODO Auto-generated method stub + return siteDao.getGameList(param); + } + + + @Override + public HashMap getOnlyVenderInfo(CommonParam commonParam) { + // TODO Auto-generated method stub + return siteDao.getOnlyVenderInfo(commonParam); + } + + + @Override + public synchronized int getBotaAutoCancelCnt(String tranId) { + // TODO Auto-generated method stub + return siteDao.getBotaAutoCancelCnt(tranId); + } + + + @Override + public synchronized int getBotaBetCnt(String tranId) { + // TODO Auto-generated method stub + return siteDao.getBotaBetCnt(tranId); + } + + + @Override + public List getBotaBetListMinute() { + // TODO Auto-generated method stub + return siteDao.getBotaBetListMinute(); + } + + + @Override + public String getSiteIdByRefId2(String string) { + // TODO Auto-generated method stub + return siteDao.getSiteIdByRefId2(string); + } + + + @Override + public int getTranIdCheck(String string) { + // TODO Auto-generated method stub + return siteDao.getTranIdCheck(string); + } + + + @Override + public int getTranIdCheck2(String string) { + // TODO Auto-generated method stub + return siteDao.getTranIdCheck2(string); + } + + + @Override + public HashMap getSiteMember(String string) { + // TODO Auto-generated method stub + return siteDao.getSiteMember(string); + } + + + @Override + public void updateDebitCancel(String refId) { + // TODO Auto-generated method stub + siteDao.updateDebitCancel(refId); + } + + + @Override + public void insertSiteCallBackLog(HashMap logParam) { + // TODO Auto-generated method stub + siteDao.insertSiteCallBackLog(logParam); + } + + + @Override + public List getBetList(BetParam param) { + // TODO Auto-generated method stub + return siteDao.getBetList(param); + } + + + @Override + public List getMonsterGameList() { + return siteDao.getMonsterGameList(); + } + + + @Override + public HashMap getProgmaticApiInfo3(String code) { + // TODO Auto-generated method stub + return siteDao.getProgmaticApiInfo3(code); + } + + + @Override + public long getBetCancelAmt(String string) { + // TODO Auto-generated method stub + return siteDao.getBetCancelAmt(string); + } + + + @Override + public int getBetIdCheck(String refId) { + // TODO Auto-generated method stub + return siteDao.getBetIdCheck(refId); + } + + + @Override + public int getBetIdCheck2(String refId) { + // TODO Auto-generated method stub + return siteDao.getBetIdCheck2(refId); + } + + + @Override + public int getTranCheck2(String betId) { + // TODO Auto-generated method stub + return siteDao.getTranCheck2(betId); + } + + + @Override + public void insertSlotCity(HashMap slotMap) { + // TODO Auto-generated method stub + siteDao.insertSlotCity(slotMap); + } + + + @Override + public void botaAutoCancel(HashMap tranParam) { + // TODO Auto-generated method stub + siteDao.botaAutoCancel(tranParam); + } + + + @Override + public void seattleCredit() { + // TODO Auto-generated method stub + siteDao.seattleCredit(); + } + + + @Override + public void updateDecimal(HashMap decimalParam) { + // TODO Auto-generated method stub + siteDao.updateDecimal(decimalParam); + } + + + @Override + public List getonlyDebitList() { + // TODO Auto-generated method stub + return siteDao.getonlyDebitList(); + } + + + @Override + public void insertAutoLose(HashMap loseCredit) { + // TODO Auto-generated method stub + siteDao.insertAutoLose(loseCredit); + } + + + @Override + public HashMap getBetCheck(BetParam param) { + // TODO Auto-generated method stub + return siteDao.getBetCheck(param); + } + + + @Override + public int callbackTokenCheck(String token) { + // TODO Auto-generated method stub + return siteDao.callbackTokenCheck(token); + } + + + @Override + public HashMap getVenderInfo(BalanceParam param) { + // TODO Auto-generated method stub + return siteDao.getVenderInfo(param); + } + + + @Override + public String getRefIdByTranId(String tranId) { + // TODO Auto-generated method stub + return siteDao.getRefIdByTranId(tranId); + } + + + @Override + public List getCreditReSendList() { + // TODO Auto-generated method stub + return siteDao.getCreditReSendList(); + } + + + @Override + public void updateMemCancelCnt(long memberIdx) { + // TODO Auto-generated method stub + siteDao.updateMemCancelCnt(memberIdx); + } + + + @Override + public Long getMemberIdx(HashMap memParam) { + // TODO Auto-generated method stub + return siteDao.getMemberIdx(memParam); + } + + + @Override + public int insertVendorChangeBalanceLog(VendorChangeBalanceLogVo logVo) { + // TODO Auto-generated method stub + return siteDao.insertVendorChangeBalanceLog(logVo); + } + + + @Override + public HashMap getGsoftVendorInfo(String gameID) { + // TODO Auto-generated method stub + return siteDao.getGsoftVendorInfo(gameID); + } + + + @Override + public HashMap getDemoByBombAccId(HashMap memParam) { + + return siteDao.getDemoByBombAccId(memParam); + } + + + @Override + public void inserDemoUSer(String bombToken) { + + siteDao.inserDemoUSer(bombToken); + } + + + @Override + public void updateDemoUSer(HashMap memParam) { + siteDao.updateDemoUSer(memParam); + + } + + + @Override + public List getTrasferVendorList() { + + return siteDao.getTrasferVendorList(); + } + + + @Override + public List getAllMember() { + + return siteDao.getAllMember(); + } + + @Override + public List getAllMember2() { + return siteDao.getAllMember2(); + } + + + + @Override + public int gethourBetCheck(long member) { + + return siteDao.gethourBetCheck(member); + } + + + @Override + public HashMap getUserVendorInfo(HashMap memParam) { + // TODO Auto-generated method stub + return siteDao.getUserVendorInfo(memParam); + } + + + + @Override + public Member getMemberByToken(Map authParam) { + // TODO Auto-generated method stub + return siteDao.getMemberByToken(authParam); + } + + + @Override + public HashMap getSiteApiInfoByToken(Map authParam) { + // TODO Auto-generated method stub + return siteDao.getSiteApiInfoByToken(authParam); + } + + + @Override + public double getBetDepositAmt(String tranId) { + return siteDao.getBetDepositAmt(tranId); + } + + + @Override + public void insertSplusTran(Map trxParam) { + try { + siteDao.insertSplusTran(trxParam); + }catch(Exception e) { + log.info(e.toString()); + } + + } + + + @Override + public void updateSplusTran(Map trxParam) { + try { + siteDao.updateSplusTran(trxParam); + }catch(Exception e) { + log.info(e.toString()); + } + + } + + + @Override + public String getCbData(String reserve_id) { + // TODO Auto-generated method stub + return siteDao.getCbData(reserve_id); + } + + + @Override + public void updatesPurchaseId(Map trxParam) { + siteDao.updatesPurchaseId(trxParam); + + } + + + @Override + public double getBetGapAmt(String pid) { + // TODO Auto-generated method stub + return siteDao.getBetGapAmt(pid); + } + + + @Override + public void insertToken(String base64Token) { + siteDao.insertToken(base64Token); + } + + + @Override + public int getSplusToken(String base64Token) { + return siteDao.getSplusToken(base64Token); + } + + + @Override + public String getRefIdByPurchaseId(String purchase_id) { + return siteDao.getRefIdByPurchaseId(purchase_id); + } + + + @Override + public List getSplusDetailData(BetParam param) { + // TODO Auto-generated method stub + return siteDao.getSplusDetailData(param); + } + + + @Override + public String getKorName(String t, String txt) { + String resTxt = txt; + // TODO Auto-generated method stub + if("T".equals(t)) { + resTxt= siteDao.getKorNameTeam(txt); + if(resTxt==null)resTxt = txt; + }else { + resTxt= siteDao.getKorNameLeague(txt); + if(resTxt==null)resTxt = txt; + } + return resTxt; + } + + + @Override + public void forDefaultProc(Site site) { + // TODO Auto-generated method stub + TransactionStatus txStatus = transactionManager.getTransaction(new DefaultTransactionDefinition()); + + try { + siteDao.updVendorMapForDefault(site); + siteDao.updVendorCreditRateForDefault(site); + siteDao.deleteVendorAccountForDefault(site); + + transactionManager.commit(txStatus); + } catch(Exception e) { + System.out.println(e.toString()); + transactionManager.rollback(txStatus); + } + } + + + @Override + public HashMap getBetInfoByTranId(String reference) { + return siteDao.getBetInfoByTranId(reference); + } + + + @Override + public int getSuccDebitCnt(String betId) { + // TODO Auto-generated method stub + return siteDao.getSuccDebitCnt(betId); + } + + + @Override + public HashMap getSiteVendorInfo(HashMap param) { + // TODO Auto-generated method stub + return siteDao.getSiteVendorInfo(param); + } + + + @Override + public int updatePowerballApiInfo(HashMap registParam) { + // TODO Auto-generated method stub + return siteDao.updatePowerballApiInfo(registParam); + } + + + @Override + public List> getPowerBallInfoList(String gameType) { + // TODO Auto-generated method stub + return siteDao.getPowerBallInfoList(gameType); + } + + @Override + public HashMap getSiteApiInfoByApiKey(HashMap param) { + // TODO Auto-generated method stub + return siteDao.getSiteApiInfoByApiKey(param); + } + + @Override + public HashMap getSiteApiInfoByCallbackKey(HashMap param) { + // TODO Auto-generated method stub + return siteDao.getSiteApiInfoByCallbackKey(param); + } + + + @Override + public int updMemLastVendorIdx(HashMap memParam) { + // TODO Auto-generated method stub + return siteDao.updMemLastVendorIdx(memParam); + } + + + @Override + public List getVendorListByVendorKey(HashMap venderInfo) { + // TODO Auto-generated method stub + return siteDao.getVendorListByVendorKey(venderInfo); + } + + + @Override + public void vendorUpdate(HashMap venderInfo) { + siteDao.vendorUpdate(venderInfo); + + } + + + @Override + public List getNexusSkinListByVendorKey(HashMap venderInfo) { + // TODO Auto-generated method stub + return siteDao.getNexusSkinListByVendorKey(venderInfo); + } + + + @Override + public void nexusSkinUpdate(HashMap venderInfo) { + siteDao.nexusSkinUpdate(venderInfo); + } + + + @Override + public String getParseTarget() { + return siteDao.getParseTarget(); + } + + + @Override + public String getParseTargetExtr() { + return siteDao.getParseTargetExtr(); + } + + + @Override + public HashMap getParseUseYn(int siteIdx) { + return siteDao.getParseUseYn(siteIdx); + } + + + @Override + public void insertParseUse(HashMap parseParam) { + siteDao.insertParseUse(parseParam); + + } + + + @Override + public List getApiBetVendorList(int siteIdx) { + // TODO Auto-generated method stub + return siteDao.getApiBetVendorList(siteIdx); + } + + + @Override + public int getApiBetTransactionCnt(BetParam param) { + // TODO Auto-generated method stub + return siteDao.getApiBetTransactionCnt(param); + } + + + @Override + public List getApiBetTransactionList(BetParam param) { + // TODO Auto-generated method stub + return siteDao.getApiBetTransactionList(param); + } + + + @Override + public HashMap getParseUserYn(HashMap pum) { + return siteDao.getParseUserYn(pum); + } + + + @Override + public void setParseUserYn(HashMap pum) { + siteDao.setParseUserYn(pum); + } + + + @Override + public OTPInfo getOtpInfo(long siteIdx) { + // TODO Auto-generated method stub + return siteDao.getOtpInfo(siteIdx); + } + + + @Override + public OTPInfo getOtpInfoByManger(long siteIdx) { + // TODO Auto-generated method stub + return siteDao.getOtpInfoByManger(siteIdx); + } + + + @Override + public int registSuperOtp(OTPInfo param) { + // TODO Auto-generated method stub + return siteDao.registSuperOtp(param); + } + + + @Override + public HashMap getSiteOnlyVendorInfo(HashMap vendorParam) { + // TODO Auto-generated method stub + return siteDao.getSiteOnlyVendorInfo(vendorParam); + } + + + @Override + public TrfApiInfo getTrfApiInfo(HashMap mapParam) { + // TODO Auto-generated method stub + return siteDao.getTrfApiInfo(mapParam); + } + + + @Override + public void agentIpsUpdate(Site site) { + siteDao.agentIpsUpdate(site); + + } + + + @Override + public int insertEvoDetail(HashMap detailMap) { + // TODO Auto-generated method stub + return siteDao.insertEvoDetail(detailMap); + } + + + @Override + public HashMap getCommonApiInfo(HashMap commonParam) { + // TODO Auto-generated method stub + return siteDao.getCommonApiInfo(commonParam); + } + + + @Override + public HashMap getBeforeTranInfo(String vendorTranKey) { + // TODO Auto-generated method stub + return siteDao.getBeforeTranInfo(vendorTranKey); + } + + + @Override + public List getParseTargetGame(String gameType) { + return siteDao.getParseTargetGame(gameType); + } + + + @Override + public String getOrgDetailData(BetParam param) { + // TODO Auto-generated method stub + return siteDao.getOrgDetailData(param); + } + + + @Override + public String getParDetailData(BetParam param) { + // TODO Auto-generated method stub + return siteDao.getParDetailData(param); + } + + + @Override + public HashMap getBetInfoByTranKey(String vendorTranKey) { + // TODO Auto-generated method stub + return siteDao.getBetInfoByTranKey(vendorTranKey); + } + + + @Override + public HashMap getParseInfo(HashMap param) { + // TODO Auto-generated method stub + return siteDao.getParseInfo(param); + } + + + @Override + public int getBlockParseGameId(String gameId) { + // TODO Auto-generated method stub + return siteDao.getBlockParseGameId(gameId); + } + + + @Override + public HashMap getBeforeTranInfo2(String vendorTranKey) { + // TODO Auto-generated method stub + return siteDao.getBeforeTranInfo2(vendorTranKey); + } + + + @Override + public String getMemberByIdx(HashMap memParam) { + return siteDao.getMemberByIdx(memParam); + } + + + @Override + public List getSiteVendorList2(int siteIdx) { + // TODO Auto-generated method stub + return siteDao.getSiteVendorList2(siteIdx); + } + + + @Override + public List getVendorList2(int siteIdx) { + // TODO Auto-generated method stub + return siteDao.getVendorList2(siteIdx); + } + + + @Override + public void saveSvcr(HashMap paramMap, int type) { + // TODO Auto-generated method stub + siteDao.saveSvcr(paramMap); + + if(type == 0) { + Vendor vendor = new Vendor(); + vendor.setSiteIdx(Long.parseLong(paramMap.get("siteIdx").toString())); + vendor.setVendorCode(paramMap.get("vendorCode").toString()); + vendor.setVendorIdx(Long.parseLong(paramMap.get("vendorIdx").toString())); + siteDao.siteVenderUpdate(vendor); + } else { + //현쟈 설전된 코드이면 요율 변경 + int codeCheck = siteDao.siteVenderCodeCheck(paramMap); + if(codeCheck ==1) { + siteDao.saveVendorRate2(paramMap); + } + } + } + + + @Override + public String getSiteKey(HashMap paramMap) { + // TODO Auto-generated method stub + return siteDao.getSiteKey(paramMap); + } + + + @Override + public String getVendorTitle(HashMap paramMap) { + // TODO Auto-generated method stub + return siteDao.getVendorTitle(paramMap); + } + + + @Override + public Long getUserTimeout(HashMap accLog) { + // TODO Auto-generated method stub + return siteDao.getUserTimeout(accLog); + } + + + @Override + public int updateUserTimeout(HashMap accLog) { + // TODO Auto-generated method stub + return siteDao.updateUserTimeout(accLog); + } + + + @Override + public String getGameKeyByNexusGameId(String gameId) { + // TODO Auto-generated method stub + return siteDao.getGameKeyByNexusGameId(gameId); + } + + + @Override + public String getDebitIsParse(String betId) { + // TODO Auto-generated method stub + return siteDao.getDebitIsParse(betId); + } + + + @Override + public int updateParseUseYN(String useYn) { + // TODO Auto-generated method stub + return siteDao.updateParseUseYN(useYn); + } + + + @Override + public int insertTheaTrxId(HashMap param) { + // TODO Auto-generated method stub + return siteDao.insertTheaTrxId(param); + } + + + @Override + public HashMap getApiKeyInfo(String vendorTitle) { + // TODO Auto-generated method stub + return siteDao.getApiKeyInfo(vendorTitle); + } + + + @Override + public HashMap getApiKeyInfo2(HashMap keyParam) { + // TODO Auto-generated method stub + return siteDao.getApiKeyInfo2(keyParam); + } + + + @Override + public HashMap getRefBetInfoByTranId(String tranId) { + // TODO Auto-generated method stub + return siteDao.getRefBetInfoByTranId(tranId); + } + + + @Override + public int updMemberBalance(HashMap balanceMap) { + // TODO Auto-generated method stub + return siteDao.updMemberBalance(balanceMap); + } + + + @Override + public int getMemberBalance(HashMap balanceMap) { + // TODO Auto-generated method stub + return siteDao.getMemberBalance(balanceMap); + } + + + @Override + public HashMap getMemberId(String vendorUsername) { + // TODO Auto-generated method stub + return siteDao.getMemberId(vendorUsername); + } + + + @Override + public int checkMemberId(String vendorUsername) { + // TODO Auto-generated method stub + return siteDao.checkMemberId(vendorUsername); + } + + + @Override + public HashMap getNewSiteApiInfo(String vendorUsername) { + // TODO Auto-generated method stub + return siteDao.getNewSiteApiInfo(vendorUsername); + } + + + @Override + public HashMap getNewSiteVendorInfo(HashMap param) { + // TODO Auto-generated method stub + return siteDao.getNewSiteVendorInfo(param); + } + + + @Override + public int updateTestCnt(Site site) { + // TODO Auto-generated method stub + return siteDao.updateTestCnt(site); + } + + + @Override + public int updateParseEvoYn(HashMap param) { + // TODO Auto-generated method stub + return siteDao.updateParseEvoYn(param); + } + + + @Override + public int saveParsEvoAmount(SiteSearch param) { + // TODO Auto-generated method stub + return siteDao.saveParsEvoAmount(param); + } + + + @Override + public int getUserBalance(HashMap balanceMap) { + // TODO Auto-generated method stub + return siteDao.getUserBalance(balanceMap); + } + + + @Override + public List getMyDownSite(SiteSearch search) { + // TODO Auto-generated method stub + return siteDao.getMyDownSite(search); + } + + + @Override + public HashMap getCreditInfo(String siteId) { + // TODO Auto-generated method stub + return siteDao.getCreditInfo(siteId); + } + + + @Override + public int checkDownSite(Map checkDown) { + // TODO Auto-generated method stub + return siteDao.checkDownSite(checkDown); + } + + + @Override + public List getSiteTreeList(String siteId) { + // TODO Auto-generated method stub + return siteDao.getSiteTreeList(siteId); + } + + + @Override + public int getMyDownSiteCheck(Site targetsite) { + // TODO Auto-generated method stub + return siteDao.getMyDownSiteCheck(targetsite); + } + + + @Override + public void siteUpdateForAPI(Site site) { + // TODO Auto-generated method stub + siteDao.siteUpdate(site); + siteDao.insertParseUseYn(site); + } + + + @Override + public int updateSitePwd(SitePwdVO sitePwdVO) { + // TODO Auto-generated method stub + return siteDao.updateSitePwd(sitePwdVO); + } + + + @Override + public Site getSite(Site addsite) { + // TODO Auto-generated method stub + return siteDao.getSite(addsite); + } + + + @Override + public void siteVenderLobbyUpdate(Vendor vendor) { + // TODO Auto-generated method stub + siteDao.siteVenderLobbyUpdate(vendor); + } + + + @Override + public List getVendorMapList(SiteSearch search) { + // TODO Auto-generated method stub + List getVendorMapList = siteDao.getVendorMapList(search); + for(HashMap vendorMap : getVendorMapList) { + + search.setSearchValue(vendorMap.get("vendorCode").toString());; + List lobbylist = siteDao.geLobbyList(search); + + for(HashMap lobbyinfo : lobbylist) { + + //log.info(lobbyinfo.get("lobbyCode").toString()+ ","+ vendorMap.get("unionGameKey").toString()); + if(lobbyinfo.get("lobbyCode").toString().equals(vendorMap.getOrDefault("unionGameKey", "").toString())){ + + lobbyinfo.put("selected", "Y"); + }else { + lobbyinfo.put("selected", "N"); + } + } + vendorMap.put("lobbylist", lobbylist); + } + + + return getVendorMapList; + } + + + @Override + public String siteVenderRate(Vendor vendor) { + // TODO Auto-generated method stub + return siteDao.siteVenderRate(vendor); + } + + @Override + public int getBoardListCnt(BoardSearch search) { + // TODO Auto-generated method stub + return siteDao.getBoardListCnt(search); + } + + + @Override + public List> getBoardList(BoardSearch search) { + // TODO Auto-generated method stub + return siteDao.getBoardList(search); + } + + + @Override + public HashMap getBoardDetail(long boardIdx) { + // TODO Auto-generated method stub + return siteDao.getBoardDetail(boardIdx); + } + + + @Override + public int getSiteCallbackErrLogListCnt(SiteSearch search) { + // TODO Auto-generated method stub + return siteDao.getSiteCallbackErrLogListCnt(search); + } + + + @Override + public List getSiteCallbackErrLogList(SiteSearch search) { + // TODO Auto-generated method stub + List list = siteDao.getSiteCallbackErrLogList(search); + + if(search.getTopId() != null && !search.getTopId().equals("")) { + for(HashMap item : list) { + HashMap param = new HashMap<>(); + param.put("topId", search.getTopId()); + param.put("siteId", item.get("siteId").toString()); + List treeInfo = siteDao.getSiteTreeInfo(param); + log.info("treeInfo::"+treeInfo.toString()); + item.put("treeInfo", treeInfo); + } + } + + return list; + } + + + @Override + public int getUserListCnt(UserSearch search) { + // TODO Auto-generated method stub + return siteDao.getUserListCnt(search); + } + + + @Override + public List> getUserList(UserSearch search) { + List> list = siteDao.getUserList(search); + + if(search.getTopId() != null && !search.getTopId().equals("")) { + for(HashMap item : list) { + HashMap param = new HashMap<>(); + param.put("topId", search.getTopId()); + param.put("siteId", item.get("siteId").toString()); + List treeInfo = siteDao.getSiteTreeInfo(param); + item.put("treeInfo", treeInfo); + } + } + + return list; + } + + + @Override + public HashMap getUserDetail(UserSearch search) { + HashMap user = siteDao.getUserDetail(search); + + if(search.getTopId() != null && !search.getTopId().equals("")) { + HashMap param = new HashMap<>(); + param.put("topId", search.getTopId()); + param.put("siteId", user.get("siteId").toString()); + List treeInfo = siteDao.getSiteTreeInfo(param); + log.info("treeInfo::"+treeInfo.toString()); + user.put("treeInfo", treeInfo); + } + + return user; + } + + + @Override + public int getSiteListCntForApi(SiteSearch search) { + // TODO Auto-generated method stub + return siteDao.getSiteListCntForApi(search); + } + + + @Override + public List getSiteListForApi(SiteSearch search) { + // TODO Auto-generated method stub + return siteDao.getSiteListForApi(search); + } + + + @Override + public Site getSiteDetailForApi(SiteSearch search) { + Site site = siteDao.getSiteDetailForApi(search); + + if(search.getTopId() != null && !search.getTopId().equals("")) { + HashMap param = new HashMap<>(); + param.put("topId", search.getTopId()); + param.put("siteId", site.getSiteId()); + List treeInfo = siteDao.getSiteTreeInfo(param); + log.info("treeInfo::"+treeInfo.toString()); + site.setTreeInfo(treeInfo); + } + + return site; + } + + + @Override + public List getVendorListForApi(SiteSearch search) { + // TODO Auto-generated method stub + return siteDao.getVendorListForApi(search); + } + + + @Override + public List getSiteVendorListForApi(SiteSearch search) { + // TODO Auto-generated method stub + return siteDao.getSiteVendorListForApi(search); + } + + + @Override + public HashMap getRefIdByVendorTranKey(String vendorTranKey) { + // TODO Auto-generated method stub + return siteDao.getRefIdByVendorTranKey(vendorTranKey); + } + + @Override + public int updateUserMaxBet(HashMap param) { + return siteDao.updateUserMaxBet(param); + } + + @Override + public int insertTranLog(HashMap logParam) { + return siteDao.insertTranLog(logParam); + } + + + @Override + public HashMap getSiteSubCredit(String siteId) { + // TODO Auto-generated method stub + return siteDao.getSiteSubCredit(siteId); + } + + + @Override + public String getBetAmountByTranParam(HashMap param) { + // TODO Auto-generated method stub + return siteDao.getBetAmountByTranParam(param); + } + +} diff --git a/src/main/java/com/bb/service/SplusService.java b/src/main/java/com/bb/service/SplusService.java new file mode 100644 index 0000000..2966b98 --- /dev/null +++ b/src/main/java/com/bb/service/SplusService.java @@ -0,0 +1,24 @@ +package com.bb.service; + +import java.util.HashMap; +import java.util.Map; + +import org.json.JSONObject; + +public interface SplusService { + + void insertSplus(HashMap tranParam, JSONObject paramjson); + + void updateSplus(HashMap tranParam, JSONObject paramjson); + + void cancelSplus(HashMap tranParam); + + int getReserveCnt(Map trxParam); + + int getCommitCnt(Map trxParam); + + int getDeReverseCnt(Map trxParam); + + int getCustomerCnt(Map trxParam); + +} diff --git a/src/main/java/com/bb/service/SplusServiceImpl.java b/src/main/java/com/bb/service/SplusServiceImpl.java new file mode 100644 index 0000000..97aabca --- /dev/null +++ b/src/main/java/com/bb/service/SplusServiceImpl.java @@ -0,0 +1,242 @@ +package com.bb.service; + +import java.util.HashMap; +import java.util.Map; + +import org.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.bb.dao.SplusDao; + +import lombok.extern.slf4j.Slf4j; +@Slf4j +@Service +public class SplusServiceImpl implements SplusService { + + @Autowired + SplusDao splusDao; + + @Override + public void insertSplus(HashMap tranParam, JSONObject paramjson) { + + Map splusBetParam = new HashMap(); + + splusBetParam.put("refId", tranParam.get("refId").toString()); + splusBetParam.put("siteIdx", tranParam.get("siteIdx")); + splusBetParam.put("memberIdx", tranParam.get("memberIdx")); + splusBetParam.put("memberId", tranParam.get("memberId").toString()); + splusBetParam.put("betStatus", 0); + + + + try { + //한글 치환 + org.json.JSONObject bets = paramjson.getJSONObject("Bets"); + org.json.JSONObject bet = bets.getJSONObject("Bet"); + splusBetParam.put("realAmount", bet.get("RealAmount").toString()); + splusBetParam.put("creationDate", bet.get("CreationDate").toString()); + splusBetParam.put("betOdds", bet.getDouble("OddsDec")); + splusBetParam.put("gain", bet.get("Gain").toString()); + + //싱글 베팅 + if(bet.has("Lines")) { + + splusBetParam.put("betType", "M"); + + + org.json.JSONArray lines = bet.getJSONArray("Lines"); + for(int i=0;i 0) { + splusBetParam.put("betStatus", 1); + }else { + splusBetParam.put("betStatus", -1); + } + org.json.JSONObject purchases = credits.getJSONObject("Purchases"); + org.json.JSONObject purchase = purchases.getJSONObject("Purchase"); + org.json.JSONObject selections = purchase.getJSONObject("Selections"); + //싱글 베팅 + + org.json.JSONObject selection = selections.getJSONObject("Selection"); + if(selection ==null) { // 경기 결과 여러개 + org.json.JSONArray selectionArray = selections.getJSONArray("Selection"); + for(int i=0;i getSiteDailyReportList(SiteSearch search); + + int getVendorDailyReportListCnt(SiteSearch search); + + List getVendorDailyReportList(SiteSearch search); + + List getBottomSiteDailyReportList(SiteSearch search); + + HashMap getMonthCredit(SiteSearch search); + + List getUserDailyReportList(SiteSearch search); + + List getUserReportSum(SiteSearch search); + + List getAdminPushInfo(); + + int getAgentReportCnt(SiteSearch search); + + List getAgentReportList(SiteSearch search); + + int getAgentReportCnt2(SiteSearch search); + + List getAgentReportList2(SiteSearch search); + + HashMap getAgentReportTotal(SiteSearch search); + + + + String getlastMonth(SiteSearch search); + + List getVendorDailyReportListDay(SiteSearch search); + + List getVendorDailyReportListMonth(SiteSearch search); + + List getVendorDailyReportListDaySUM(SiteSearch search); + + List getVendorDailyReportListMonthSUM(SiteSearch search); + + List getSiteReportList(SiteSearch search); + + List getSiteReportListSum(SiteSearch search); + + List getSiteReportMemList(SiteSearch search); + + List getSiteReportMemListSum(SiteSearch search); + + List getSiteReportListToDay(SiteSearch search); + + List getSiteReportListSumToDay(SiteSearch search); + + List getDashBoardList(SiteSearch search); + + List getDashBoardMonth(SiteSearch search); + + HashMap getYdayBetInfoBySite(Site targetSite); + + HashMap getMonthBetInfoBySite(Site targetSite); + + HashMap getYdayBetInfoByUser(HashMap targetUser); + + HashMap getMonthBetInfoByUser(HashMap targetUser); + + HashMap getVendorDailyReportMonthByParse(SiteSearch search); + + List getVendorDailyReportListDayByParse(SiteSearch search); + + HashMap getHybridReport(ReportSearch search); + + List getHybridReportList(@Valid ReportSearch search); + + HashMap getHybridReportTotal(@Valid ReportSearch search); + +} diff --git a/src/main/java/com/bb/service/StatServiceImpl.java b/src/main/java/com/bb/service/StatServiceImpl.java new file mode 100644 index 0000000..668a028 --- /dev/null +++ b/src/main/java/com/bb/service/StatServiceImpl.java @@ -0,0 +1,229 @@ +package com.bb.service; + +import java.util.HashMap; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.bb.dao.StatDao; +import com.bb.model.ReportSearch; +import com.bb.model.Site; +import com.bb.model.SiteSearch; + +import jakarta.validation.Valid; +import lombok.extern.slf4j.Slf4j; + + +@Slf4j +@Service +public class StatServiceImpl implements StatService{ + + @Autowired + private StatDao statDao; + + @Override + public int getSiteDailyReportListCnt(SiteSearch search) { + // TODO Auto-generated method stub + return statDao.getSiteDailyReportListCnt(search); + } + + @Override + public List getSiteDailyReportList(SiteSearch search) { + // TODO Auto-generated method stub + return statDao.getSiteDailyReportList(search); + } + + @Override + public int getVendorDailyReportListCnt(SiteSearch search) { + // TODO Auto-generated method stub + return statDao.getVendorDailyReportListCnt(search); + } + + @Override + public List getVendorDailyReportList(SiteSearch search) { + // TODO Auto-generated method stub + return statDao.getVendorDailyReportList(search); + } + + @Override + public List getBottomSiteDailyReportList(SiteSearch search) { + // TODO Auto-generated method stub + return statDao.getBottomSiteDailyReportList(search); + } + + @Override + public HashMap getMonthCredit(SiteSearch search) { + // TODO Auto-generated method stub + return statDao.getMonthCredit(search); + } + + @Override + public List getUserDailyReportList(SiteSearch search) { + // TODO Auto-generated method stub + return statDao.getUserDailyReportList(search); + } + + @Override + public List getUserReportSum(SiteSearch search) { + // TODO Auto-generated method stub + return statDao.getUserReportSum(search); + } + + @Override + public List getAdminPushInfo() { + // TODO Auto-generated method stub + return statDao.getAdminPushInfo(); + } + + @Override + public int getAgentReportCnt(SiteSearch search) { + // TODO Auto-generated method stub + return statDao.getAgentReportCnt(search); + } + + @Override + public List getAgentReportList(SiteSearch search) { + // TODO Auto-generated method stub + return statDao.getAgentReportList(search); + } + + @Override + public int getAgentReportCnt2(SiteSearch search) { + // TODO Auto-generated method stub + return statDao.getAgentReportCnt2(search); + } + + @Override + public List getAgentReportList2(SiteSearch search) { + // TODO Auto-generated method stub + return statDao.getAgentReportList2(search); + } + + @Override + public HashMap getAgentReportTotal(SiteSearch search) { + // TODO Auto-generated method stub + return statDao.getAgentReportTotal(search); + } + + @Override + public String getlastMonth(SiteSearch search) { + // TODO Auto-generated method stub + return statDao.getlastMonth(search); + } + + @Override + public List getVendorDailyReportListDay(SiteSearch search) { + // TODO Auto-generated method stub + return statDao.getVendorDailyReportListDay(search); + } + + @Override + public List getVendorDailyReportListMonth(SiteSearch search) { + // TODO Auto-generated method stub + return statDao.getVendorDailyReportListMonth(search); + } + + @Override + public List getVendorDailyReportListDaySUM(SiteSearch search) { + // TODO Auto-generated method stub + return statDao.getVendorDailyReportListDaySUM(search); + } + + @Override + public List getVendorDailyReportListMonthSUM(SiteSearch search) { + // TODO Auto-generated method stub + return statDao.getVendorDailyReportListMonthSUM(search); + } + + @Override + public List getSiteReportList(SiteSearch search) { + return statDao.getSiteReportList(search); + } + + @Override + public List getSiteReportListSum(SiteSearch search) { + return statDao.getSiteReportListSum(search); + } + + @Override + public List getSiteReportMemList(SiteSearch search) { + return statDao.getSiteReportMemList(search); + } + + @Override + public List getSiteReportMemListSum(SiteSearch search) { + return statDao.getSiteReportMemListSum(search); + } + + @Override + public List getSiteReportListToDay(SiteSearch search) { + return statDao.getSiteReportListToDay(search); + } + + @Override + public List getSiteReportListSumToDay(SiteSearch search) { + return statDao.getSiteReportListSumToDay(search); + } + + @Override + public List getDashBoardList(SiteSearch search) { + return statDao.getDashBoardList(search); + } + + @Override + public List getDashBoardMonth(SiteSearch search) { + return statDao.getDashBoardMonth(search); + } + + @Override + public HashMap getYdayBetInfoBySite(Site targetSite) { + return statDao.getYdayBetInfoBySite(targetSite); + } + + @Override + public HashMap getMonthBetInfoBySite(Site targetSite) { + return statDao.getMonthBetInfoBySite(targetSite); + } + + @Override + public HashMap getYdayBetInfoByUser(HashMap targetUser) { + return statDao.getYdayBetInfoByUser(targetUser); + } + + @Override + public HashMap getMonthBetInfoByUser(HashMap targetUser) { + return statDao.getMonthBetInfoByUser(targetUser); + } + + @Override + public HashMap getVendorDailyReportMonthByParse(SiteSearch search) { + // TODO Auto-generated method stub + return statDao.getVendorDailyReportMonthByParse(search); + } + + @Override + public List getVendorDailyReportListDayByParse(SiteSearch search) { + // TODO Auto-generated method stub + return statDao.getVendorDailyReportListDayByParse(search); + } + + @Override + public HashMap getHybridReport(ReportSearch search) { + // TODO Auto-generated method stub + return statDao.getHybridReport(search); + } + + @Override + public List getHybridReportList(@Valid ReportSearch search) { + // TODO Auto-generated method stub + return statDao.getHybridReportList(search); + } + + @Override + public HashMap getHybridReportTotal(@Valid ReportSearch search) { + // TODO Auto-generated method stub + return statDao.getHybridReportTotal(search); + } + +} diff --git a/src/main/java/com/bb/service/SvendorService.java b/src/main/java/com/bb/service/SvendorService.java new file mode 100644 index 0000000..7a95a43 --- /dev/null +++ b/src/main/java/com/bb/service/SvendorService.java @@ -0,0 +1,19 @@ +package com.bb.service; + +import java.util.HashMap; +import java.util.List; + +import com.bb.model.Game; + +import org.codehaus.jettison.json.JSONException; +import org.codehaus.jettison.json.JSONObject; + +public interface SvendorService { + + JSONObject getDetail(HashMap betInfo) throws JSONException; + + JSONObject create(String LOG_PREFIX, HashMap apiInfo); + List gameList(String LOG_PREFIX, HashMap apiInfo); + String playUrl(String LOG_PREFIX, HashMap apiInfo); + JSONObject getDetail(String LOG_PREFIX, HashMap apiInfo); +} diff --git a/src/main/java/com/bb/service/SvendorServiceImpl.java b/src/main/java/com/bb/service/SvendorServiceImpl.java new file mode 100644 index 0000000..d9cd9eb --- /dev/null +++ b/src/main/java/com/bb/service/SvendorServiceImpl.java @@ -0,0 +1,291 @@ +package com.bb.service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import io.netty.channel.ConnectTimeoutException; +import io.netty.handler.timeout.ReadTimeoutException; +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONException; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.WebClientRequestException; +import org.springframework.web.reactive.function.client.WebClientResponseException; + +import com.bb.model.Game; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class SvendorServiceImpl implements SvendorService { + + @Autowired + WebClient webClient; + + + @Override + public JSONObject getDetail(HashMap betInfo) throws JSONException { + JSONObject resJson = new JSONObject(); + //body + MultiValueMap parameters = new LinkedMultiValueMap<>(); + parameters.add("trid", betInfo.get("vendorTranKey").toString()); + + HttpHeaders header = new HttpHeaders(); + header.set("Authorization", betInfo.get("vendorApiKey").toString()); + header.set("Content-Type", "application/x-www-form-urlencoded"); + + try { + ResponseEntity responseEntity = webClient.post() + .uri(betInfo.get("vendorApiUrl").toString()+"/transaction-single") + .headers(h -> h.addAll(header)) + .bodyValue(parameters) + .retrieve() + .toEntity(String.class) + .block(); + + log.info(responseEntity.getBody()); + resJson = new JSONObject(responseEntity.getBody()); + + } catch(WebClientResponseException e) { + log.error("getDetail WebClientResponseException: " + e.getMessage()); + log.error("getDetail status code: " + e.getStatusCode().value()); + log.error("getDetail response body: " + e.getResponseBodyAsString()); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error("getDetail ConnectTimeoutException::"+rae.getMessage()); + } + if(rae.getCause() instanceof ReadTimeoutException) { + log.error("getDetail ReadTimeoutException::"+rae.getMessage()); + } + if(rae.getCause() instanceof InterruptedException) { + log.error("getDetail InterruptedException::"+rae.getMessage()); + } + } catch (Exception e) { + log.error("getDetail Exception::"+e.getMessage()); + } + return resJson.getJSONObject("data").getJSONObject("gameDetail"); + } + + + @Override + public JSONObject create(String LOG_PREFIX, HashMap apiInfo) { + JSONObject resJson = new JSONObject(); + + //body + MultiValueMap parameters = new LinkedMultiValueMap<>(); + parameters.add("userid", apiInfo.get("userid").toString()); + parameters.add("nickname", apiInfo.get("nickname").toString()); + + HttpHeaders header = new HttpHeaders(); + header.set("Content-Type", "application/x-www-form-urlencoded"); + header.set("Authorization", apiInfo.get("apiKey").toString()); + log.info(LOG_PREFIX+ "create::Request::"+parameters.toString()); + + try { + ResponseEntity responseEntity = webClient.post() + .uri(apiInfo.get("apiBaseUrl").toString()+"/create") + .headers(h -> h.addAll(header)) + .bodyValue(parameters) + .retrieve() + .toEntity(String.class) + .block(); + log.info(LOG_PREFIX+ "create::Response::"+responseEntity.getBody()); + resJson = new JSONObject(responseEntity.getBody()); + } catch(WebClientResponseException e) { + log.error(LOG_PREFIX+ "create WebClientResponseException: " + e.getMessage()); + log.error(LOG_PREFIX+ "create status code: " + e.getStatusCode().value()); + log.error(LOG_PREFIX+ "create response body: " + e.getResponseBodyAsString()); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "create ConnectTimeoutException::"+rae.getMessage()); + } + if(rae.getCause() instanceof ReadTimeoutException) { + log.error(LOG_PREFIX+ "create ReadTimeoutException::"+rae.getMessage()); + } + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "create InterruptedException::"+rae.getMessage()); + } + } catch (Exception e) { + log.info(LOG_PREFIX+ "create::Exception::"+e.getMessage()); + } + + return resJson; + } + + + @Override + public List gameList(String LOG_PREFIX, HashMap apiInfo) { + List gameList = null; + + //body + MultiValueMap parameters = new LinkedMultiValueMap<>(); + parameters.add("vendor", apiInfo.get("vendor").toString()); + + HttpHeaders header = new HttpHeaders(); + header.set("Content-Type", "application/x-www-form-urlencoded"); + header.set("Authorization", apiInfo.get("apiKey").toString()); + log.info(LOG_PREFIX+ "gameList::Request::"+parameters.toString()); + + try { + ResponseEntity responseEntity = webClient.post() + .uri(apiInfo.get("apiBaseUrl").toString()+"/gamelist") + .headers(h -> h.addAll(header)) + .bodyValue(parameters) + .retrieve() + .toEntity(String.class) + .block(); + JSONObject resJson = new JSONObject(responseEntity.getBody()); + if(resJson.getInt("code") == 0) { + log.info(LOG_PREFIX+ "gameList::Response::code::"+resJson.getInt("code")); + log.info(LOG_PREFIX+ "gameList::Response::msg::"+resJson.getString("msg")); + JSONArray games = resJson.getJSONArray("data"); + int length = games.length(); + gameList = new ArrayList<>(); + + for(int i=0; i apiInfo) { + String url = null; + + //body + MultiValueMap parameters = new LinkedMultiValueMap<>(); + parameters.add("userid", apiInfo.get("userid").toString()); + parameters.add("userip", apiInfo.get("userip").toString()); + parameters.add("vendor", apiInfo.get("vendor").toString()); + parameters.add("game", apiInfo.get("game").toString()); + if("Evolution".equals(apiInfo.get("vendor").toString())) { + parameters.add("skin", apiInfo.get("skin").toString()); + } + + HttpHeaders header = new HttpHeaders(); + header.set("Content-Type", "application/x-www-form-urlencoded"); + header.set("Authorization", apiInfo.get("apiKey").toString()); + log.info(LOG_PREFIX+ "playUrl::Request::"+parameters.toString()); + + try { + ResponseEntity responseEntity = webClient.post() + .uri(apiInfo.get("apiBaseUrl").toString()+"/play") + .headers(h -> h.addAll(header)) + .bodyValue(parameters) + .retrieve() + .toEntity(String.class) + .block(); + log.info(LOG_PREFIX+ "playUrl::Response::"+responseEntity.getBody()); + JSONObject resJson = new JSONObject(responseEntity.getBody()); + if(resJson.getInt("code") == 0) { + url = resJson.getString("URL"); + } + } catch(WebClientResponseException e) { + log.error(LOG_PREFIX+ "playUrl WebClientResponseException: " + e.getMessage()); + log.error(LOG_PREFIX+ "playUrl status code: " + e.getStatusCode().value()); + log.error(LOG_PREFIX+ "playUrl response body: " + e.getResponseBodyAsString()); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "playUrl ConnectTimeoutException::"+rae.getMessage()); + } + if(rae.getCause() instanceof ReadTimeoutException) { + log.error(LOG_PREFIX+ "playUrl ReadTimeoutException::"+rae.getMessage()); + } + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "playUrl InterruptedException::"+rae.getMessage()); + } + } catch (Exception e) { + log.info(LOG_PREFIX+ "playUrl::Exception::"+e.getMessage()); + } + + return url; + } + + + @Override + public JSONObject getDetail(String LOG_PREFIX, HashMap apiInfo) { + JSONObject dataObj = null; + + //body + MultiValueMap parameters = new LinkedMultiValueMap<>(); + parameters.add("trid", apiInfo.get("uuid").toString()); + + HttpHeaders header = new HttpHeaders(); + header.set("Content-Type", "application/x-www-form-urlencoded"); + header.set("Authorization", apiInfo.get("vendorApiKey").toString()); + log.info(LOG_PREFIX+ "getDetail::Request::"+parameters.toString()); + + try { + ResponseEntity responseEntity = webClient.post() + .uri(apiInfo.get("vendorApiUrl").toString()+"/transaction-single") + .headers(h -> h.addAll(header)) + .bodyValue(parameters) + .retrieve() + .toEntity(String.class) + .block(); + JSONObject resJson = new JSONObject(responseEntity.getBody()); + log.info(LOG_PREFIX+ "getDetail::Response::"+resJson); + int resCode = resJson.getInt("code"); + String resMsg = resJson.getString("msg"); + log.info(LOG_PREFIX+ "getDetail::Response::Code::"+resCode); + log.info(LOG_PREFIX+ "getDetail::Response::Message::"+resMsg); + if(resCode == 0) { + dataObj = resJson.getJSONObject("data"); + } + } catch(WebClientResponseException e) { + log.error(LOG_PREFIX+ "getDetail WebClientResponseException: " + e.getMessage()); + log.error(LOG_PREFIX+ "getDetail status code: " + e.getStatusCode().value()); + log.error(LOG_PREFIX+ "getDetail response body: " + e.getResponseBodyAsString()); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "getDetail ConnectTimeoutException::"+rae.getMessage()); + } + if(rae.getCause() instanceof ReadTimeoutException) { + log.error(LOG_PREFIX+ "getDetail ReadTimeoutException::"+rae.getMessage()); + } + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "getDetail InterruptedException::"+rae.getMessage()); + } + } catch (Exception e) { + log.info(LOG_PREFIX+ "getDetail::Exception::"+e.getMessage()); + } + + return dataObj; + } +} diff --git a/src/main/java/com/bb/service/ThenutService.java b/src/main/java/com/bb/service/ThenutService.java new file mode 100644 index 0000000..8d8ac6f --- /dev/null +++ b/src/main/java/com/bb/service/ThenutService.java @@ -0,0 +1,27 @@ +package com.bb.service; + +import java.util.HashMap; +import java.util.List; + +import org.codehaus.jettison.json.JSONObject; + +import com.bb.model.Game; + +public interface ThenutService { + + JSONObject getAgent(String LOG_PREFIX, HashMap apiInfo); + + JSONObject getUser(String LOG_PREFIX, HashMap apiInfo); + + JSONObject createUser(String LOG_PREFIX, HashMap apiInfo); + + String createUserToken(String LOG_PREFIX, HashMap apiInfo); + + List getGameList(String LOG_PREFIX, HashMap apiInfo); + + String getGameUrl(String LOG_PREFIX, HashMap apiInfo); + + JSONObject getBetDetail(String LOG_PREFIX, HashMap apiInfo); + + String getBetDetailUrl(String LOG_PREFIX, HashMap apiInfo); +} diff --git a/src/main/java/com/bb/service/ThenutServiceImpl.java b/src/main/java/com/bb/service/ThenutServiceImpl.java new file mode 100644 index 0000000..fecf497 --- /dev/null +++ b/src/main/java/com/bb/service/ThenutServiceImpl.java @@ -0,0 +1,470 @@ +package com.bb.service; + +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; + +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.WebClientRequestException; +import org.springframework.web.reactive.function.client.WebClientResponseException; + +import com.bb.model.Game; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class ThenutServiceImpl implements ThenutService { + + @Autowired + WebClient webClient; + + @Override + public JSONObject getAgent(String LOG_PREFIX, HashMap apiInfo) { + LOG_PREFIX = LOG_PREFIX + "getAgent::"; + JSONObject responseObj = null; + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8"))); + String apiKey = "Bearer "+apiInfo.get("apiKey").toString(); + headers.set("Authorization", apiKey); + + String apiUrl = apiInfo.get("apiBaseUrl").toString() + "/agent"; + log.info(LOG_PREFIX+ "apiUrl::"+apiUrl); + + try { + ResponseEntity resEntity = webClient.get() + .uri(apiUrl) + .headers(h -> h.addAll(headers)) + .retrieve() + .toEntity(String.class) + .block(); + if(resEntity != null && resEntity.getStatusCode() == HttpStatus.OK) { + responseObj = new JSONObject(resEntity.getBody()); + log.info(LOG_PREFIX+ "Response : " + responseObj.toString()); + } + } catch (WebClientResponseException wce) { + log.error(LOG_PREFIX+ "WebClientResponseException::"+wce.getMessage()); + log.error(LOG_PREFIX+ "status code::"+wce.getStatusCode().value()); + log.error(LOG_PREFIX+ "response body::"+wce.getResponseBodyAsString()); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "SocketTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "InterruptedException::"+rae.getMessage()); + } + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.getMessage()); + e.printStackTrace(); + } + + return responseObj; + } + + @Override + public JSONObject getUser(String LOG_PREFIX, HashMap apiInfo) { + LOG_PREFIX = LOG_PREFIX + "getUser::"; + JSONObject responseObj = null; + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8"))); + String apiKey = "Bearer "+apiInfo.get("apiKey").toString(); + headers.set("Authorization", apiKey); + + String apiUrl = apiInfo.get("apiBaseUrl").toString() + "/user?"; + String param = "username="+apiInfo.get("apiUsername"); + apiUrl = apiUrl + param; + log.info(LOG_PREFIX+ "apiUrl::"+apiUrl); + + try { + ResponseEntity resEntity = webClient.get() + .uri(apiUrl) + .headers(h -> h.addAll(headers)) + .retrieve() + .toEntity(String.class) + .block(); + if(resEntity != null && resEntity.getStatusCode() == HttpStatus.OK) { + responseObj = new JSONObject(resEntity.getBody()); + log.info(LOG_PREFIX+ "Response : " + responseObj.toString()); + } + } catch (WebClientResponseException wce) { + log.error(LOG_PREFIX+ "WebClientResponseException::"+wce.getMessage()); + log.error(LOG_PREFIX+ "status code::"+wce.getStatusCode().value()); + log.error(LOG_PREFIX+ "response body::"+wce.getResponseBodyAsString()); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "SocketTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "InterruptedException::"+rae.getMessage()); + } + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.getMessage()); + e.printStackTrace(); + } + + return responseObj; + } + + @Override + public JSONObject createUser(String LOG_PREFIX, HashMap apiInfo) { + LOG_PREFIX = LOG_PREFIX + "createUser::"; + JSONObject responseObj = null; + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8"))); + String apiKey = "Bearer "+apiInfo.get("apiKey").toString(); + headers.set("Authorization", apiKey); + + String apiUrl = apiInfo.get("apiBaseUrl").toString() + "/user"; + + try { + JSONObject params = new JSONObject(); + params.put("username", apiInfo.get("apiUsername")); + params.put("nickname", apiInfo.get("apiNickname")); + log.info(LOG_PREFIX+ "apiUrl::"+apiUrl); + log.info(LOG_PREFIX+ "params::"+params.toString()); + + ResponseEntity resEntity = webClient.post() + .uri(apiUrl) + .headers(h -> h.addAll(headers)) + .bodyValue(params.toString()) + .retrieve() + .toEntity(String.class) + .block(); + if(resEntity != null && resEntity.getStatusCode() == HttpStatus.OK) { + responseObj = new JSONObject(resEntity.getBody()); + log.info(LOG_PREFIX+ "Response : " + responseObj.toString()); + } + } catch (WebClientResponseException wce) { + log.error(LOG_PREFIX+ "WebClientResponseException::"+wce.getMessage()); + log.error(LOG_PREFIX+ "status code::"+wce.getStatusCode().value()); + log.error(LOG_PREFIX+ "response body::"+wce.getResponseBodyAsString()); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "SocketTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "InterruptedException::"+rae.getMessage()); + } + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.getMessage()); + e.printStackTrace(); + } + + return responseObj; + } + + @Override + public String createUserToken(String LOG_PREFIX, HashMap apiInfo) { + LOG_PREFIX = LOG_PREFIX + "createUserToken::"; + String token = null; + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8"))); + String apiKey = "Bearer "+apiInfo.get("apiKey").toString(); + headers.set("Authorization", apiKey); + + String apiUrl = apiInfo.get("apiBaseUrl").toString() + "/user/token"; + + try { + JSONObject params = new JSONObject(); + params.put("vendorCode", apiInfo.get("apiVendor")); + params.put("username", apiInfo.get("apiUsername")); + log.info(LOG_PREFIX+ "apiUrl::"+apiUrl); + log.info(LOG_PREFIX+ "params::"+params.toString()); + + ResponseEntity resEntity = webClient.patch() + .uri(apiUrl) + .headers(h -> h.addAll(headers)) + .bodyValue(params.toString()) + .retrieve() + .toEntity(String.class) + .block(); + if(resEntity != null && resEntity.getStatusCode() == HttpStatus.OK) { + JSONObject responseObj = new JSONObject(resEntity.getBody()); + log.info(LOG_PREFIX+ "Response : " + responseObj.toString()); + token = responseObj.getString("token"); + } + } catch (WebClientResponseException wce) { + log.error(LOG_PREFIX+ "WebClientResponseException::"+wce.getMessage()); + log.error(LOG_PREFIX+ "status code::"+wce.getStatusCode().value()); + log.error(LOG_PREFIX+ "response body::"+wce.getResponseBodyAsString()); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "SocketTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "InterruptedException::"+rae.getMessage()); + } + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.getMessage()); + e.printStackTrace(); + } + + return token; + } + + @Override + public List getGameList(String LOG_PREFIX, HashMap apiInfo) { + LOG_PREFIX = LOG_PREFIX + "getGameList::"; + List gameList = null; + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8"))); + String apiKey = "Bearer "+apiInfo.get("apiKey").toString(); + headers.set("Authorization", apiKey); + + String apiUrl = apiInfo.get("apiBaseUrl").toString() + "/game?"; + String param = "vendorCode="+apiInfo.get("apiVendor"); + apiUrl = apiUrl + param; + log.info(LOG_PREFIX+ "apiUrl::"+apiUrl); + + try { + ResponseEntity resEntity = webClient.get() + .uri(apiUrl) + .headers(h -> h.addAll(headers)) + .retrieve() + .toEntity(String.class) + .block(); + if(resEntity != null && resEntity.getStatusCode() == HttpStatus.OK) { + JSONArray jsonArr = new JSONArray(resEntity.getBody()); + int length = jsonArr.length(); + gameList = new ArrayList<>(); + + for(int i=0; i apiInfo) { + LOG_PREFIX = LOG_PREFIX + "getGameUrl::"; + String gameUrl = null; + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8"))); + String apiKey = "Bearer "+apiInfo.get("apiKey").toString(); + headers.set("Authorization", apiKey); + + String apiUrl = apiInfo.get("apiBaseUrl").toString() + "/game/url?"; + String param = "gameCode="+apiInfo.get("apiGameCode")+"&vendorCode="+apiInfo.get("apiVendor") + +"&token="+apiInfo.get("apiUserToken"); + apiUrl = apiUrl + param; + log.info(LOG_PREFIX+ "apiUrl::"+apiUrl); + + try { + ResponseEntity resEntity = webClient.get() + .uri(apiUrl) + .headers(h -> h.addAll(headers)) + .retrieve() + .toEntity(String.class) + .block(); + if(resEntity != null && resEntity.getStatusCode() == HttpStatus.OK) { + JSONObject responseObj = new JSONObject(resEntity.getBody()); + log.info(LOG_PREFIX+ "Response : " + responseObj.toString()); + gameUrl = responseObj.getString("url"); + } + } catch (WebClientResponseException wce) { + log.error(LOG_PREFIX+ "WebClientResponseException::"+wce.getMessage()); + log.error(LOG_PREFIX+ "status code::"+wce.getStatusCode().value()); + log.error(LOG_PREFIX+ "response body::"+wce.getResponseBodyAsString()); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "SocketTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "InterruptedException::"+rae.getMessage()); + } + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.getMessage()); + e.printStackTrace(); + } + + return gameUrl; + } + + @Override + public JSONObject getBetDetail(String LOG_PREFIX, HashMap apiInfo) { + LOG_PREFIX = LOG_PREFIX + "getBetDetail::"; + JSONObject detailObj = null; + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8"))); + String apiKey = "Bearer "+apiInfo.get("apiKey").toString(); + headers.set("Authorization", apiKey); + + String apiUrl = apiInfo.get("apiBaseUrl").toString() + "/bet/"+apiInfo.get("betId")+"/result"; + log.info(LOG_PREFIX+ "apiUrl::"+apiUrl); + + try { + ResponseEntity resEntity = webClient.get() + .uri(apiUrl) + .headers(h -> h.addAll(headers)) + .retrieve() + .toEntity(String.class) + .block(); + if(resEntity != null && resEntity.getStatusCode() == HttpStatus.OK) { + JSONObject responseObj = new JSONObject(resEntity.getBody()); + String value = responseObj.getString("value"); + JSONObject valueObj = new JSONObject(value); + detailObj = valueObj.optJSONObject("detail").optJSONObject("data"); + log.info(LOG_PREFIX+ "Detail Obj : " + detailObj.toString()); + } + } catch (WebClientResponseException wce) { + log.error(LOG_PREFIX+ "WebClientResponseException::"+wce.getMessage()); + log.error(LOG_PREFIX+ "status code::"+wce.getStatusCode().value()); + log.error(LOG_PREFIX+ "response body::"+wce.getResponseBodyAsString()); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "SocketTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "InterruptedException::"+rae.getMessage()); + } + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.getMessage()); + e.printStackTrace(); + } + + return detailObj; + } + + @Override + public String getBetDetailUrl(String LOG_PREFIX, HashMap apiInfo) { + LOG_PREFIX = LOG_PREFIX + "getBetDetailUrl::"; + String detailUrl = null; + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8"))); + String apiKey = "Bearer "+apiInfo.get("apiKey").toString(); + headers.set("Authorization", apiKey); + + String apiUrl = apiInfo.get("apiBaseUrl").toString() + "/bet/"+apiInfo.get("betId")+"/result/url"; + log.info(LOG_PREFIX+ "apiUrl::"+apiUrl); + + try { + ResponseEntity resEntity = webClient.get() + .uri(apiUrl) + .headers(h -> h.addAll(headers)) + .retrieve() + .toEntity(String.class) + .block(); + if(resEntity != null && resEntity.getStatusCode() == HttpStatus.OK) { + JSONObject responseObj = new JSONObject(resEntity.getBody()); + detailUrl = responseObj.getString("value"); + log.info(LOG_PREFIX+ "Detail Url : " + detailUrl); + } + } catch (WebClientResponseException wce) { + log.error(LOG_PREFIX+ "WebClientResponseException::"+wce.getMessage()); + log.error(LOG_PREFIX+ "status code::"+wce.getStatusCode().value()); + log.error(LOG_PREFIX+ "response body::"+wce.getResponseBodyAsString()); + } catch (WebClientRequestException rae) { + if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "SocketTimeoutException::"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "InterruptedException::"+rae.getMessage()); + } + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.getMessage()); + e.printStackTrace(); + } + + return detailUrl; + } + +} diff --git a/src/main/java/com/bb/service/TowerService.java b/src/main/java/com/bb/service/TowerService.java new file mode 100644 index 0000000..e724a15 --- /dev/null +++ b/src/main/java/com/bb/service/TowerService.java @@ -0,0 +1,14 @@ +package com.bb.service; + +import java.util.HashMap; +import java.util.List; + +import com.bb.model.Game; + +public interface TowerService { + + String getLaunchUrl(HashMap venderInfo); + + List getGameList(HashMap venderInfo); + +} diff --git a/src/main/java/com/bb/service/TowerServiceImpl.java b/src/main/java/com/bb/service/TowerServiceImpl.java new file mode 100644 index 0000000..40f5b20 --- /dev/null +++ b/src/main/java/com/bb/service/TowerServiceImpl.java @@ -0,0 +1,137 @@ +package com.bb.service; + +import java.net.SocketTimeoutException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; + +import org.apache.http.conn.ConnectTimeoutException; +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONException; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.ResourceAccessException; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.WebClientRequestException; +import org.springframework.web.reactive.function.client.WebClientResponseException; + +import com.bb.model.Game; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class TowerServiceImpl implements TowerService { + + @Autowired + WebClient webClient; + + + @Override + public String getLaunchUrl(HashMap venderInfo) { + String launchUrl=""; + try { + String responseBody = webClient.get() + .uri(venderInfo.get("gameApiUrl").toString()) + .header("Authorization", venderInfo.get("vendorApiKey").toString()) + .retrieve() + .bodyToMono(String.class) + .block(); + + log.info(responseBody); + JSONObject resJson = new JSONObject(responseBody); + launchUrl = resJson.getString("url"); + } catch (WebClientRequestException wcre) { + Throwable cause = wcre.getCause(); + if(cause instanceof org.apache.http.conn.ConnectTimeoutException) { + log.error("TOWER_API::getLaunchUrl::[ConnectTimeoutException]"+wcre.getMessage()); + } else if(cause instanceof java.net.SocketTimeoutException) { + log.error("TOWER_API::getLaunchUrl::[SocketTimeoutException]"+wcre.getMessage()); + } else if(cause instanceof InterruptedException) { + log.error("TOWER_API::getLaunchUrl::[InterruptedException]"+wcre.getMessage()); + } else { + log.error("TOWER_API::getLaunchUrl::WebClientRequestException::"+wcre.toString()); + } + } catch (WebClientResponseException wre) { + String str = wre.getResponseBodyAsString(); + log.error("TOWER_API::getLaunchUrl::WebClientResponseException::"+str); + } catch (JSONException je) { + je.printStackTrace(); + } catch (Exception e) { + log.error("TOWER_API::getLaunchUrl::Exception::"+e.toString()); + e.printStackTrace(); + } + return launchUrl; + } + + + @Override + public List getGameList(HashMap venderInfo) { + // https://to-api.com/v2/games?site_code=tripleopr01&vendorCode=pp + List gameList = null; + try { + String url = venderInfo.get("vendorApiUrl").toString()+"/v2/games?site_code="+venderInfo.get("vendorApiId").toString()+"&vendorCode="+venderInfo.get("vendorGameCode").toString(); + + String responseBody = webClient.get() + .uri(url) + .header("Authorization", venderInfo.get("vendorApiKey").toString()) + .retrieve() + .bodyToMono(String.class) + .block(); + + JSONArray games = new JSONArray(responseBody); + int length = games.length(); + log.info("TOWER_API::gameList::Game List length: " + length); + + if(length > 0) { + gameList = new ArrayList<>(); + for(int i=0; i gameList(String LOG_PREFIX, TplusApiInfo apiInfo); + + String getGameLink(String LOG_PREFIX, TplusApiInfo apiInfo); + + String getComanyBalance(HashMap vendor); + + String getDetails(String LOG_PREFIX, TplusApiInfo apiInfo); +} diff --git a/src/main/java/com/bb/service/TplusServiceImpl.java b/src/main/java/com/bb/service/TplusServiceImpl.java new file mode 100644 index 0000000..b6b9b19 --- /dev/null +++ b/src/main/java/com/bb/service/TplusServiceImpl.java @@ -0,0 +1,655 @@ +package com.bb.service; + +import java.net.SocketTimeoutException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; + +import org.apache.http.conn.ConnectTimeoutException; +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.ResourceAccessException; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.util.UriComponentsBuilder; + +import com.bb.dao.SiteDao; +import com.bb.dao.TplusDao; +import com.bb.model.Game; +import com.bb.model.TplusApiInfo; +import com.bb.model.VendorChangeBalanceLogVo; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class TplusServiceImpl implements TplusService { + + @Autowired + private TplusDao tplusDao; + + @Autowired + private SiteDao siteDao; + + @Autowired + WebClient webClient; + + + @Override + public Long getBalanceUser(String LOG_PREFIX, TplusApiInfo apiInfo) { + JSONObject resJson = null; + Long balance = null; + LOG_PREFIX = LOG_PREFIX+"tplus::getBalanceUser::"; + + try { + HttpHeaders header = new HttpHeaders(); + header.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + header.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + header.set("Authorization", "Bearer "+apiInfo.getApiAuthKey()); + + UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(apiInfo.getApiBaseUrl() + "/Balance"); + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("username", apiInfo.getApiUsername()); + + HttpEntity> entity = new HttpEntity<>(params, header); + ResponseEntity response = null; + try { + response = webClient.post() + .uri(builder.toUriString()) + .headers(h -> h.addAll(header)) + .bodyValue(params) + .retrieve() + .toEntity(String.class) + .block(); + resJson = new JSONObject(response != null ? response.getBody() : "{}"); + } catch (Exception ex) { + Throwable cause = ex.getCause(); + if (cause instanceof ConnectTimeoutException || cause instanceof java.net.SocketTimeoutException || cause instanceof InterruptedException) { + throw new ResourceAccessException(ex.getMessage(), new java.io.IOException(cause)); + } + throw ex; + } + if(resJson.getInt("code") == 0) { + log.info(LOG_PREFIX+ "code: " + resJson.getInt("code")); + log.info(LOG_PREFIX+ "message: " + resJson.getString("message")); + balance = resJson.getLong("total_balance"); + } else { + balance = 0L; + log.error(LOG_PREFIX+ "code: " + resJson.getInt("code")); + log.error(LOG_PREFIX+ "message: " + resJson.getString("message")); + } + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + balance = 0L; + } catch(HttpClientErrorException hee) { + String str = hee.getResponseBodyAsString(); + log.error(LOG_PREFIX+ "HttpClientErrorException::"+str); + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.toString()); + e.printStackTrace(); + } + + return balance; + } + + @Override + public String depositUser(String LOG_PREFIX, TplusApiInfo apiInfo, Long amount) { + JSONObject resJson = null; + String resultCode = "0"; + + + try { + HttpHeaders header = new HttpHeaders(); + header.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + header.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + header.set("Authorization", "Bearer "+apiInfo.getApiAuthKey()); + + UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(apiInfo.getApiBaseUrl() + "/Deposit"); + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("username", apiInfo.getApiUsername()); + params.add("amount", amount.longValue()); + params.add("unique_key", String.valueOf(System.currentTimeMillis())); + HttpEntity> entity = new HttpEntity<>(params, header); + log.error("#-depositProc::"+apiInfo.getSiteIdx()+"::"+apiInfo.getMemberIdx()+"::"+apiInfo.getReqAt()+"::tplus::"+ "depositParams::"+params.toString()); + + ResponseEntity response = null; + try { + response = webClient.post() + .uri(builder.toUriString()) + .headers(h -> h.addAll(header)) + .bodyValue(params) + .retrieve() + .toEntity(String.class) + .block(); + resJson = new JSONObject(response != null ? response.getBody() : "{}"); + } catch (Exception ex) { + Throwable cause = ex.getCause(); + if (cause instanceof ConnectTimeoutException || cause instanceof java.net.SocketTimeoutException || cause instanceof InterruptedException) { + throw new ResourceAccessException(ex.getMessage(), new java.io.IOException(cause)); + } + throw ex; + } + if(resJson.getInt("code") == 0) { + log.info("## Tplus API ## depositUser() code: " + resJson.getInt("code")); + log.info("## Tplus API ## depositUser() message: " + resJson.getString("message")); + + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("tplus") + .vendorApiId(apiInfo.getClientId()) + .reqType("deposit") + .amount(amount.intValue()) + .reqAt(apiInfo.getReqAt()) + .reqStatus("SUCC") + .reqMsg(resJson.getString("message")) + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + + } else { + resultCode = Integer.toString(resJson.getInt("code")); + log.info("## Tplus API ## depositUser() code: " + resJson.getInt("code")); + log.info("## Tplus API ## depositUser() message: " + resJson.getString("message")); + + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("tplus") + .vendorApiId(apiInfo.getClientId()) + .reqType("deposit") + .amount(amount.intValue()) + .reqAt(apiInfo.getReqAt()) + .reqStatus("FAIL") + .reqMsg(resJson.getString("message")) + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + } + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error("#-depositProc::"+apiInfo.getSiteIdx()+"::"+apiInfo.getMemberIdx()+"::"+apiInfo.getReqAt()+"::tplus::"+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error("#-depositProc::"+apiInfo.getSiteIdx()+"::"+apiInfo.getMemberIdx()+"::"+apiInfo.getReqAt()+"::tplus::"+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error("#-depositProc::"+apiInfo.getSiteIdx()+"::"+apiInfo.getMemberIdx()+"::"+apiInfo.getReqAt()+"::tplus::"+ "[InterruptedException]"+rae.getMessage()); + } + + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("tplus") + .vendorApiId(apiInfo.getClientId()) + .reqType("deposit") + .amount(amount.intValue()) + .reqAt(apiInfo.getReqAt()) + .reqStatus("FAIL") + .reqMsg("TimeoutException") + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + resultCode = "-1"; + } catch(HttpClientErrorException hee) { + String str = hee.getResponseBodyAsString(); + log.error("#-depositProc::"+apiInfo.getSiteIdx()+"::"+apiInfo.getMemberIdx()+"::"+apiInfo.getReqAt()+"::tplus::"+ "[HttpClientErrorException]"+str); + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("tplus") + .vendorApiId(apiInfo.getClientId()) + .reqType("deposit") + .amount(amount.intValue()) + .reqAt(apiInfo.getReqAt()) + .reqStatus("FAIL") + .reqMsg(str) + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + resultCode = "-1"; + } catch (Exception e) { + log.error("#-depositProc::"+apiInfo.getSiteIdx()+"::"+apiInfo.getMemberIdx()+"::"+apiInfo.getReqAt()+"::tplus::"+ "[Exception]"+e.toString()); + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("tplus") + .vendorApiId(apiInfo.getClientId()) + .reqType("deposit") + .amount(amount.intValue()) + .reqAt(apiInfo.getReqAt()) + .reqStatus("FAIL") + .reqMsg("Exception e") + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + e.printStackTrace(); + resultCode = "-1"; + } + + return resultCode; + } + + @Override + public String withdrawUser(String LOG_PREFIX, TplusApiInfo apiInfo) { + JSONObject resJson = null; + String resultCode = "0"; + + + try { + HttpHeaders header = new HttpHeaders(); + header.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + header.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + header.set("Authorization", "Bearer "+apiInfo.getApiAuthKey()); + + UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(apiInfo.getApiBaseUrl() + "/Withdraw"); + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("username", apiInfo.getApiUsername()); + params.add("unique_key", String.valueOf(System.currentTimeMillis())); + HttpEntity> entity = new HttpEntity<>(params, header); + + ResponseEntity response = null; + try { + response = webClient.post() + .uri(builder.toUriString()) + .headers(h -> h.addAll(header)) + .bodyValue(params) + .retrieve() + .toEntity(String.class) + .block(); + resJson = new JSONObject(response != null ? response.getBody() : "{}"); + } catch (Exception ex) { + Throwable cause = ex.getCause(); + if (cause instanceof ConnectTimeoutException || cause instanceof java.net.SocketTimeoutException || cause instanceof InterruptedException) { + throw new ResourceAccessException(ex.getMessage(), new java.io.IOException(cause)); + } + throw ex; + } + if(resJson.getInt("code") == 0) { + log.info("## Tplus API ## withdrawUser() code: " + resJson.getInt("code")); + log.info("## Tplus API ## withdrawUser() message: " + resJson.getString("message")); + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("tplus") + .vendorApiId(apiInfo.getClientId()) + .reqType("withdrawAll") + .amount(0) + .reqAt(apiInfo.getReqAt()) + .reqStatus("SUCC") + .reqMsg(resJson.getString("message")) + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + } else { + resultCode = Integer.toString(resJson.getInt("code")); + log.info("## Tplus API ## withdrawUser() code: " + resJson.getInt("code")); + log.info("## Tplus API ## withdrawUser() message: " + resJson.getString("message")); + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("tplus") + .vendorApiId(apiInfo.getClientId()) + .reqType("withdrawAll") + .amount(0) + .reqAt(apiInfo.getReqAt()) + .reqStatus("FAIL") + .reqMsg(resJson.getString("resultMessage")) + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + } + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error("#-withdrawProc::"+apiInfo.getSiteIdx()+"::"+apiInfo.getMemberIdx()+"::"+apiInfo.getReqAt()+"::tplus::"+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error("#-withdrawProc::"+apiInfo.getSiteIdx()+"::"+apiInfo.getMemberIdx()+"::"+apiInfo.getReqAt()+"::tplus::"+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error("#-withdrawProc::"+apiInfo.getSiteIdx()+"::"+apiInfo.getMemberIdx()+"::"+apiInfo.getReqAt()+"::tplus::"+ "[InterruptedException]"+rae.getMessage()); + } + + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("tplus") + .vendorApiId(apiInfo.getClientId()) + .reqType("withdrawAll") + .amount(0) + .reqAt(apiInfo.getReqAt()) + .reqStatus("FAIL") + .reqMsg("TimeoutException") + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + resultCode = "-1"; + } catch(HttpClientErrorException hee) { + String str = hee.getResponseBodyAsString(); + log.error("#-withdrawProc::"+apiInfo.getSiteIdx()+"::"+apiInfo.getMemberIdx()+"::"+apiInfo.getReqAt()+"::tplus::"+ "[HttpClientErrorException]"+str); + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("tplus") + .vendorApiId(apiInfo.getClientId()) + .reqType("withdrawAll") + .amount(0) + .reqAt(apiInfo.getReqAt()) + .reqStatus("FAIL") + .reqMsg(str) + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + resultCode = "-1"; + } catch (Exception e) { + log.error("#-withdrawProc::"+apiInfo.getSiteIdx()+"::"+apiInfo.getMemberIdx()+"::"+apiInfo.getReqAt()+"::tplus::"+ "[Exception]"+e.toString()); + VendorChangeBalanceLogVo logVo = VendorChangeBalanceLogVo.builder() + .siteIdx(apiInfo.getSiteIdx()) + .memberIdx(apiInfo.getMemberIdx()) + .vendor("tplus") + .vendorApiId(apiInfo.getClientId()) + .reqType("withdrawAll") + .amount(0) + .reqAt(apiInfo.getReqAt()) + .reqStatus("FAIL") + .reqMsg("Exception e") + .build(); + siteDao.insertVendorChangeBalanceLog(logVo); + e.printStackTrace(); + resultCode = "-1"; + } + + return resultCode; + } + + @Override + public List gameList(String LOG_PREFIX, TplusApiInfo apiInfo) { + JSONObject resJson = null; + List gameList = null; + LOG_PREFIX = LOG_PREFIX+"tplus::gameList::"; + + try { + + HttpHeaders header = new HttpHeaders(); + header.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + header.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + header.set("Authorization", "Bearer "+apiInfo.getApiAuthKey()); + + UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(apiInfo.getApiBaseUrl() + "/Games"); + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("thirdparty", apiInfo.getThirdparty()); + HttpEntity> entity = new HttpEntity<>(params, header); + ResponseEntity response = null; + try { + response = webClient.post() + .uri(builder.toUriString()) + .headers(h -> h.addAll(header)) + .bodyValue(params) + .retrieve() + .toEntity(String.class) + .block(); + + resJson = new JSONObject(response != null ? response.getBody() : "{}"); + } catch (Exception ex) { + Throwable cause = ex.getCause(); + if (cause instanceof ConnectTimeoutException || cause instanceof java.net.SocketTimeoutException || cause instanceof InterruptedException) { + throw new ResourceAccessException(ex.getMessage(), new java.io.IOException(cause)); + } + throw ex; + } + if(resJson.getInt("code") == 0) { + log.info(LOG_PREFIX+ "result: " + resJson.getString("message")); + gameList = new ArrayList<>(); + JSONArray games = resJson.getJSONArray("data"); + int length = games.length(); + + for(int i=0; i params = new LinkedMultiValueMap<>(); + params.add("thirdparty", apiInfo.getThirdparty()); + params.add("uuid", apiInfo.getUuid()); + params.add("username", apiInfo.getApiUsername()); + HttpEntity> entity = new HttpEntity<>(params, header); + + ResponseEntity response = null; + try { + response = webClient.post() + .uri(builder.toUriString()) + .headers(h -> h.addAll(header)) + .bodyValue(params) + .retrieve() + .toEntity(String.class) + .block(); + resJson = new JSONObject(response != null ? response.getBody() : "{}"); + } catch (Exception ex) { + Throwable cause = ex.getCause(); + if (cause instanceof ConnectTimeoutException || cause instanceof java.net.SocketTimeoutException || cause instanceof InterruptedException) { + throw new ResourceAccessException(ex.getMessage(), new java.io.IOException(cause)); + } + throw ex; + } + if(resJson.getInt("code") == 0) { + log.info(LOG_PREFIX+ "message: " + resJson.getString("message")); + gameUrl = resJson.getString("url"); + } else { + log.error(LOG_PREFIX+ "code: " + resJson.getInt("code")); + log.error(LOG_PREFIX+ "message: " + resJson.getString("message")); + } + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + } catch(HttpClientErrorException hee) { + String str = hee.getResponseBodyAsString(); + log.error(LOG_PREFIX+ "HttpClientErrorException::"+str); + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.toString()); + e.printStackTrace(); + } + + return gameUrl; + } + + @Override + public String getComanyBalance(HashMap vendor) { + JSONObject resJson = null; + String balance = "0"; + + + try { + HttpHeaders header = new HttpHeaders(); + header.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + header.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + header.set("Authorization", "Bearer "+vendor.get("key").toString()); + + UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("http://api.seven-gameapi.com/AgentBalance"); + + + HttpEntity> entity = new HttpEntity<>(null, header); + ResponseEntity response = null; + try { + response = webClient.post() + .uri(builder.toUriString()) + .headers(h -> h.addAll(header)) + .bodyValue("") + .retrieve() + .toEntity(String.class) + .block(); + resJson = new JSONObject(response != null ? response.getBody() : "{}"); + } catch (Exception ex) { + Throwable cause = ex.getCause(); + if (cause instanceof ConnectTimeoutException || cause instanceof java.net.SocketTimeoutException || cause instanceof InterruptedException) { + throw new ResourceAccessException(ex.getMessage(), new java.io.IOException(cause)); + } + throw ex; + } + if(resJson.getInt("code") == 0) { + log.info("## Tplus API ## getBalanceUser() code: " + resJson.getInt("code")); + log.info("## Tplus API ## getBalanceUser() message: " + resJson.getString("message")); + balance = resJson.get("agent_balance").toString(); + } else { + balance = "0"; + log.info("## Tplus API ## getBalanceUser() code: " + resJson.getInt("code")); + log.info("## Tplus API ## getBalanceUser() message: " + resJson.getString("message")); + } + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error("[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error("[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error("[InterruptedException]"+rae.getMessage()); + } + balance = "0"; + } catch(HttpClientErrorException hee) { + String str = hee.getResponseBodyAsString(); + log.error(str); + } catch (Exception e) { + log.error(e.toString()); + e.printStackTrace(); + } + + return balance; + } + + @Override + public String getDetails(String LOG_PREFIX, TplusApiInfo apiInfo) { + JSONObject resJson = null; + String detailUrl = null; + LOG_PREFIX = LOG_PREFIX+"tplus::getDetails::"; + + try { + HttpHeaders header = new HttpHeaders(); + header.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + header.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + header.set("Authorization", "Bearer "+apiInfo.getApiAuthKey()); + + UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(apiInfo.getApiBaseUrl() + "/Details"); + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("pair_transaction_key", apiInfo.getPairTransactionKey()); + HttpEntity> entity = new HttpEntity<>(params, header); + + ResponseEntity response = null; + try { + response = webClient.post() + .uri(builder.toUriString()) + .headers(h -> h.addAll(header)) + .bodyValue(params) + .retrieve() + .toEntity(String.class) + .block(); + resJson = new JSONObject(response != null ? response.getBody() : "{}"); + } catch (Exception ex) { + Throwable cause = ex.getCause(); + if (cause instanceof ConnectTimeoutException || cause instanceof java.net.SocketTimeoutException || cause instanceof InterruptedException) { + throw new ResourceAccessException(ex.getMessage(), new java.io.IOException(cause)); + } + throw ex; + } + if(resJson.getInt("code") == 0) { + log.info(LOG_PREFIX+ "message: " + resJson.getString("message")); + detailUrl = resJson.getString("url"); + log.info(LOG_PREFIX+ "detailUrl: " + detailUrl); + } else { + log.error(LOG_PREFIX+ "code: " + resJson.getInt("code")); + log.error(LOG_PREFIX+ "message: " + resJson.getString("message")); + } + } catch (ResourceAccessException rae) { + if(rae.getCause() instanceof ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof SocketTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage()); + } + + if(rae.getCause() instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage()); + } + } catch(HttpClientErrorException hee) { + String str = hee.getResponseBodyAsString(); + log.error(LOG_PREFIX+ "HttpClientErrorException::"+str); + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.toString()); + e.printStackTrace(); + } + + return detailUrl; + } + +} diff --git a/src/main/java/com/bb/service/TransService.java b/src/main/java/com/bb/service/TransService.java new file mode 100644 index 0000000..a2376c8 --- /dev/null +++ b/src/main/java/com/bb/service/TransService.java @@ -0,0 +1,57 @@ +package com.bb.service; + +import java.util.HashMap; +import java.util.List; + +import org.codehaus.jettison.json.JSONException; +import org.codehaus.jettison.json.JSONObject; + +import com.bb.model.BetParam; +import com.bb.model.NexusApiInfo; +import com.bb.model.TransSearchVO; + +public interface TransService { + + int getTransBetListCnt(TransSearchVO search); + + List> getTransBetList(TransSearchVO search); + + HashMap getTransBetListSum(TransSearchVO search); + + int getTransBetFastListCnt(TransSearchVO search); + + List> getTransBetFastList(TransSearchVO search); + + HashMap getBetListItem(TransSearchVO search); + + HashMap getTransBetFastListSum(TransSearchVO search); + + HashMap getBetInfoByBetId(BetParam param); + + String getGsoftRoundIdByBetId(String betId); + + JSONObject getInfinitiBetDetail(String LOG_PREFIX, String apiBaseUrl, JSONObject bodyObj); + + JSONObject getNexusBetDetail(String LOG_PREFIX, NexusApiInfo nexusApiInfo, String trxId); + + JSONObject getNexusBetDetailUrl(String LOG_PREFIX, NexusApiInfo nexusApiInfo, String trxId); + + HashMap getSiteBetByRefIdFromOld(BetParam param); + + JSONObject getSvendorDetail(String LOG_PREFIX, HashMap betInfo) throws JSONException; + + HashMap getApiInfo(String vendorTitle); + + int deleteEvoDetailNull(HashMap detailMap); + + JSONObject getCncpDetailsById(String LOG_PREFIX, HashMap apiInfo); + + JSONObject getDetailByBetId(String LOG_PREFIX, HashMap apiInfo); + + JSONObject getPracpDetail(String LOG_PREFIX, HashMap apiInfo); + + String getTplusDetails(String LOG_PREFIX, HashMap apiInfo); + + String getPragmaticDetails(String lOG_PREFIX, HashMap betInfo); + +} diff --git a/src/main/java/com/bb/service/TransServiceImpl.java b/src/main/java/com/bb/service/TransServiceImpl.java new file mode 100644 index 0000000..9f881cb --- /dev/null +++ b/src/main/java/com/bb/service/TransServiceImpl.java @@ -0,0 +1,759 @@ +package com.bb.service; + +import java.math.BigInteger; +import java.nio.charset.Charset; +import java.security.MessageDigest; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Base64; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.UUID; + +import org.codehaus.jettison.json.JSONException; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.reactive.function.client.WebClientRequestException; +import org.springframework.web.reactive.function.client.WebClientResponseException; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.util.UriComponentsBuilder; + +import com.bb.dao.SiteDao; +import com.bb.dao.TransDao; +import com.bb.model.BetParam; +import com.bb.model.NexusApiInfo; +import com.bb.model.NexusTrplVO; +import com.bb.model.TransSearchVO; +import com.bb.util.SHA256WithRSA; +import com.bb.util.StringUtils; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class TransServiceImpl implements TransService { + + @Autowired + private TransDao transDao; + + @Autowired + private SiteDao siteDao; + + @Autowired + private WebClient webClient; + + @Override + public int getTransBetListCnt(TransSearchVO search) { + // TODO Auto-generated method stub + return transDao.getTransBetListCnt(search); + } + + @Override + public List> getTransBetList(TransSearchVO search) { + List> list = transDao.getTransBetList(search); + + if(search.getTopId() != null && !search.getTopId().equals("")) { + for(HashMap item : list) { + HashMap param = new HashMap<>(); + param.put("topId", search.getTopId()); + param.put("siteId", item.get("siteId").toString()); + List treeInfo = siteDao.getSiteTreeInfo(param); + item.put("treeInfo", treeInfo); + } + } + + return list; + } + + @Override + public HashMap getTransBetListSum(TransSearchVO search) { + // TODO Auto-generated method stub + return transDao.getTransBetListSum(search); + } + + @Override + public int getTransBetFastListCnt(TransSearchVO search) { + // TODO Auto-generated method stub + return transDao.getTransBetFastListCnt(search); + } + + @Override + public List> getTransBetFastList(TransSearchVO search) { + + return transDao.getTransBetFastList(search); + } + + @Override + public HashMap getBetListItem(TransSearchVO search) { + HashMap item = transDao.getBetListItem(search.getRefId()); + HashMap param = new HashMap<>(); + param.put("topId", search.getTopId()); + param.put("siteId", item.get("siteId").toString()); + List treeInfo = siteDao.getSiteTreeInfo(param); + item.put("treeInfo", treeInfo); + + return item; + } + + @Override + public HashMap getTransBetFastListSum(TransSearchVO search) { + // TODO Auto-generated method stub + return transDao.getTransBetFastListSum(search); + } + + @Override + public HashMap getBetInfoByBetId(BetParam param) { + // TODO Auto-generated method stub + return transDao.getBetInfoByBetId(param); + } + + @Override + public String getGsoftRoundIdByBetId(String betId) { + // TODO Auto-generated method stub + return transDao.getGsoftRoundIdByBetId(betId); + } + + private HttpHeaders getInfinitiHeader(String LOG_PREFIX) { + LOG_PREFIX = LOG_PREFIX + "getInfinitiHeader::"; + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8"))); + + return headers; + } + + @Override + public JSONObject getInfinitiBetDetail(String LOG_PREFIX, String apiBaseUrl, JSONObject bodyObj) { + JSONObject jsonObj = null; + LOG_PREFIX = LOG_PREFIX + "getInfinitiBetDetail::"; + + try { + HttpHeaders headers = getInfinitiHeader(LOG_PREFIX); + String apiUrl = apiBaseUrl + "/get/history/datafeed"; + + log.info(LOG_PREFIX+ "ApiUrl::"+apiUrl); + log.info(LOG_PREFIX+ "HttpHeaders::"+headers.toString()); + log.info(LOG_PREFIX+ "BodyJson::"+bodyObj); + + ResponseEntity response = webClient.post() + .uri(apiUrl) + .headers(h -> h.addAll(headers)) + .bodyValue(bodyObj.toString()) + .retrieve() + .toEntity(String.class) + .block(); + + jsonObj = new JSONObject(response.getBody()); + log.info(LOG_PREFIX+ "response::"+jsonObj.toString()); + + + } catch (WebClientResponseException e) { + log.error(LOG_PREFIX+ "WebClientResponseException::" + e.getStatusCode().value()); + log.error(LOG_PREFIX+ "WebClientResponseException Body::" + e.getResponseBodyAsString()); + } catch (WebClientRequestException e) { + Throwable cause = e.getCause(); + if (cause instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectTimeoutException::" + e.getMessage()); + } else if (cause instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "SocketTimeoutException::" + e.getMessage()); + } else if (cause instanceof InterruptedException) { + log.error(LOG_PREFIX+ "InterruptedException::" + e.getMessage()); + } else { + log.error(LOG_PREFIX+ "WebClientRequestException::" + e.getMessage()); + } + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::" + e.getMessage()); + e.printStackTrace(); + } + + return jsonObj; + } + + private HttpHeaders getNexusHeader(String LOG_PREFIX, NexusApiInfo apiInfo, String bodyJson) { + LOG_PREFIX = LOG_PREFIX + "getNexusHeader::"; + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8"))); + + String hashCode = getNexusHashCode(LOG_PREFIX, bodyJson, apiInfo.getAgentSecretKey()); + headers.set("hash", hashCode); + headers.set("agent", apiInfo.getAgentId()); + log.info(LOG_PREFIX+ "HttpHeaders::"+headers.toString()); + + return headers; + } + + private String getNexusHashCode(String LOG_PREFIX, String body, String secretKey) { + String hashCode = ""; + LOG_PREFIX = LOG_PREFIX + "getNexusHashCode::"; + try { + // Json String Body + Secret Key + String result = body + secretKey; + // String result = "{\"username\":\"057007mptest01\",\"nickname\":\"007mptest01\",\"siteUsername\":\"057007mptest01\"}"; + log.info(LOG_PREFIX+ "Body + Secret Key::"+result); + // SHA-256 Hash make + MessageDigest digestObj = MessageDigest.getInstance("SHA-256"); + byte[] hash_data = digestObj.digest(result.getBytes("UTF-8")); + + // Base64 encoding + hashCode = Base64.getEncoder().encodeToString(hash_data); + log.info(LOG_PREFIX+ "hashCode::"+hashCode); + } catch(Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.getMessage()); + } + + return hashCode; + } + + @Override + public JSONObject getNexusBetDetail(String LOG_PREFIX, NexusApiInfo nexusApiInfo, String trxId) { + JSONObject jsonObj = null; + LOG_PREFIX = LOG_PREFIX + "getNexusBetDetail::"; + + try { + JSONObject bodyObj = new JSONObject(); + bodyObj.put("transactionKeys", trxId); + String bodyJson = bodyObj.toString(); + log.info(LOG_PREFIX+ "bodyJson::" + bodyJson); + + HttpHeaders headers = getNexusHeader(LOG_PREFIX, nexusApiInfo, bodyJson); + String apiUrl = nexusApiInfo.getApiBaseUrl() + "/transaction/detail"; + + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("transactionKeys", trxId); + + ResponseEntity response = webClient.post() + .uri(apiUrl) + .headers(h -> h.addAll(headers)) + .bodyValue(params) + .retrieve() + .toEntity(String.class) + .block(); + + jsonObj = new JSONObject(response.getBody()); + + } catch (WebClientResponseException e) { + log.error(LOG_PREFIX+ "WebClientResponseException::" + e.getStatusCode().value()); + log.error(LOG_PREFIX+ "WebClientResponseException Body::" + e.getResponseBodyAsString()); + } catch (WebClientRequestException e) { + Throwable cause = e.getCause(); + if (cause instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectTimeoutException::" + e.getMessage()); + } else if (cause instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "SocketTimeoutException::" + e.getMessage()); + } else if (cause instanceof InterruptedException) { + log.error(LOG_PREFIX+ "InterruptedException::" + e.getMessage()); + } else { + log.error(LOG_PREFIX+ "WebClientRequestException::" + e.getMessage()); + } + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::" + e.getMessage()); + e.printStackTrace(); + } + + return jsonObj; + } + + @Override + public JSONObject getNexusBetDetailUrl(String LOG_PREFIX, NexusApiInfo nexusApiInfo, String trxId) { + JSONObject jsonObj = null; + LOG_PREFIX = LOG_PREFIX + "getNexusBetDetailUrl::"; + + try { + JSONObject bodyObj = new JSONObject(); + bodyObj.put("transactionKey", trxId); + bodyObj.put("lang", "ko"); + String bodyJson = bodyObj.toString(); + log.info(LOG_PREFIX+ "bodyJson::" + bodyJson); + + HttpHeaders headers = getNexusHeader(LOG_PREFIX, nexusApiInfo, bodyJson); + String apiUrl = nexusApiInfo.getApiBaseUrl() + "/getdetailurl"; + + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("transactionKey", trxId); + params.add("lang", "ko"); + + ResponseEntity response = webClient.post() + .uri(apiUrl) + .headers(h -> h.addAll(headers)) + .bodyValue(params) + .retrieve() + .toEntity(String.class) + .block(); + + jsonObj = new JSONObject(response.getBody()); + + } catch (WebClientResponseException e) { + log.error(LOG_PREFIX+ "WebClientResponseException::" + e.getStatusCode().value()); + log.error(LOG_PREFIX+ "WebClientResponseException Body::" + e.getResponseBodyAsString()); + } catch (WebClientRequestException e) { + Throwable cause = e.getCause(); + if (cause instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectTimeoutException::" + e.getMessage()); + } else if (cause instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "SocketTimeoutException::" + e.getMessage()); + } else if (cause instanceof InterruptedException) { + log.error(LOG_PREFIX+ "InterruptedException::" + e.getMessage()); + } else { + log.error(LOG_PREFIX+ "WebClientRequestException::" + e.getMessage()); + } + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::" + e.getMessage()); + e.printStackTrace(); + } + + return jsonObj; + } + + @Override + public HashMap getSiteBetByRefIdFromOld(BetParam param) { + // TODO Auto-generated method stub + return transDao.getSiteBetByRefIdFromOld(param); + } + + @Override + public JSONObject getSvendorDetail(String LOG_PREFIX, HashMap betInfo) throws JSONException { + JSONObject dataObj = null; + + //body + MultiValueMap parameters = new LinkedMultiValueMap<>(); + parameters.add("trid", betInfo.get("uuid").toString()); + + HttpHeaders header = new HttpHeaders(); + header.set("Authorization", betInfo.get("vendorApiKey").toString()); + header.set("Content-Type", "application/x-www-form-urlencoded"); + + log.info(LOG_PREFIX+ "SVENDOR:request url::" + betInfo.get("vendorApiUrl").toString() + "/transaction-single"); + log.info(LOG_PREFIX+ "SVENDOR:request data::" + parameters.toString()); + + try { + ResponseEntity responseEntity = webClient.post() + .uri(betInfo.get("vendorApiUrl").toString() + "/transaction-single") + .headers(h -> h.addAll(header)) + .bodyValue(parameters) + .retrieve() + .toEntity(String.class) + .block(); + + JSONObject resJson = new JSONObject(responseEntity.getBody()); + int resCode = resJson.getInt("code"); + String resMsg = resJson.getString("msg"); + log.info(LOG_PREFIX+ "SVENDOR::Response::Code" + resCode); + log.info(LOG_PREFIX+ "SVENDOR::Response::Message" + resMsg); + if(resCode == 0) { + dataObj = resJson.getJSONObject("data"); + } + } catch (WebClientResponseException e) { + log.error(LOG_PREFIX+ "SVENDOR:WebClientResponseException::" + e.getStatusCode().value()); + log.error(LOG_PREFIX+ "SVENDOR:WebClientResponseException::" + e.getResponseBodyAsString()); + } catch (WebClientRequestException e) { + Throwable cause = e.getCause(); + if (cause instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "SVENDOR:ConnectTimeoutException::" + e.getMessage()); + } else if (cause instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "SVENDOR:SocketTimeoutException::" + e.getMessage()); + } else { + log.error(LOG_PREFIX+ "SVENDOR:WebClientRequestException::" + e.getMessage()); + } + } catch (JSONException e) { + log.error(LOG_PREFIX+ "SVENDOR:error::" + e.getLocalizedMessage()); + log.error(LOG_PREFIX+ "SVENDOR:error::" + e.getMessage()); + e.printStackTrace(); + } + + return dataObj; + } + + @Override + public HashMap getApiInfo(String vendorTitle) { + // TODO Auto-generated method stub + return transDao.getApiInfo(vendorTitle); + } + + @Override + public int deleteEvoDetailNull(HashMap detailMap) { + // TODO Auto-generated method stub + return transDao.deleteEvoDetailNull(detailMap); + } + + private HttpHeaders getCncpHeader(String LOG_PREFIX, HashMap apiInfo) { + LOG_PREFIX = LOG_PREFIX + "::getCncpHeader::"; + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8"))); + + String authorization = getCncpAuthorization(LOG_PREFIX, apiInfo); + headers.set("Authorization", authorization); + log.info(LOG_PREFIX+ "HttpHeaders::"+headers.toString()); + + return headers; + } + + + private String getCncpAuthorization(String LOG_PREFIX, HashMap apiInfo) { + String authorization = ""; + LOG_PREFIX = LOG_PREFIX + "::getCncpAuthorization::"; + try { + String apiAgentId = apiInfo.get("apiAgentId").toString(); + String apiPrivateKey = apiInfo.get("apiPrivateKey").toString(); + String apiHttpVerb = apiInfo.get("apiHttpVerb").toString(); + String apiEndPoint = apiInfo.get("apiEndPoint").toString(); + long apiTimestemp = System.currentTimeMillis(); + UUID uuid = UUID.randomUUID(); + String apiNonceString = uuid.toString(); + + String inputText = apiHttpVerb + " " + apiEndPoint + " " + apiTimestemp + " " + apiNonceString; + log.info(LOG_PREFIX+ "inputText::"+inputText); + String signText = SHA256WithRSA.sign(inputText, apiPrivateKey); + log.info(LOG_PREFIX+ "signText::"+signText); + + authorization = "HERAPLAY-SHA256-RSA2048 " + apiAgentId+","+apiTimestemp+","+apiNonceString+","+signText; + log.info(LOG_PREFIX+ "Authorization::"+authorization); + + } catch(Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.getMessage()); + } + + return authorization; + } + + @Override + public JSONObject getCncpDetailsById(String LOG_PREFIX, HashMap apiInfo) { + JSONObject result = null; + LOG_PREFIX = LOG_PREFIX + "gameRoundDetailsById::"; + + apiInfo.put("apiHttpVerb", "GET"); + apiInfo.put("apiEndPoint", "datafeedapi/gamerounddetailsbyid"); + + try { + HttpHeaders headers = getCncpHeader(LOG_PREFIX, apiInfo); + String apiUrl = apiInfo.get("apiBaseUrl").toString() + "/DataFeedAPI/GameRoundDetailsById?"; + String param = "providerCode=" + apiInfo.get("providerCode").toString() + "&roundId=" + apiInfo.get("roundId").toString(); + apiUrl = apiUrl + param; + log.info(LOG_PREFIX+ "Request URL : " + apiUrl); + log.info(LOG_PREFIX+ "Request Header : " + headers.toString()); + + ResponseEntity resEntity = webClient.get() + .uri(apiUrl) + .headers(h -> h.addAll(headers)) + .retrieve() + .toEntity(String.class) + .block(); + + if(resEntity != null && resEntity.getStatusCode() == HttpStatus.OK) { + JSONObject responseObj = new JSONObject(resEntity.getBody()); + if(responseObj.has("result")) { + result = responseObj.getJSONObject("result"); + } else { + log.error(LOG_PREFIX+ "Response : Has not result"); + } + } else { + log.error(LOG_PREFIX+ "Response : unknown error"); + } + + } catch (WebClientResponseException e) { + log.error(LOG_PREFIX+ "WebClientResponseException::" + e.getStatusCode().value()); + log.error(LOG_PREFIX+ "WebClientResponseException Body::" + e.getResponseBodyAsString()); + } catch (WebClientRequestException e) { + Throwable cause = e.getCause(); + if (cause instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectTimeoutException::" + e.getMessage()); + } else if (cause instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "SocketTimeoutException::" + e.getMessage()); + } else if (cause instanceof InterruptedException) { + log.error(LOG_PREFIX+ "InterruptedException::" + e.getMessage()); + } else { + log.error(LOG_PREFIX+ "WebClientRequestException::" + e.getMessage()); + } + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::" + e.getMessage()); + e.printStackTrace(); + } + + return result; + } + + @Override + public JSONObject getDetailByBetId(String LOG_PREFIX, HashMap apiInfo) { + JSONObject result = null; + LOG_PREFIX = LOG_PREFIX + "getDetailByBetId::"; + + try { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8"))); + headers.set("Authorization", apiInfo.get("apiAuthorization").toString()); + + String apiUrl = apiInfo.get("apiBaseUrl").toString() + "/bet/" + apiInfo.get("betId").toString(); + log.info(LOG_PREFIX+ "Request URL : " + apiUrl); + log.info(LOG_PREFIX+ "Request Header : " + headers.toString()); + + ResponseEntity resEntity = webClient.get() + .uri(apiUrl) + .headers(h -> h.addAll(headers)) + .retrieve() + .toEntity(String.class) + .block(); + + if(resEntity != null && resEntity.getStatusCode() == HttpStatus.OK) { + JSONObject responseObj = new JSONObject(resEntity.getBody()); + if(responseObj.has("detail")) { + String detailStr = responseObj.getString("detail"); + JSONObject detailObj = new JSONObject(detailStr); + result = detailObj.getJSONObject("detail").getJSONObject("data"); + } else { + log.error(LOG_PREFIX+ "Response : Has not result"); + } + } else { + log.error(LOG_PREFIX+ "Response : unknown error"); + } + + } catch (WebClientResponseException e) { + log.error(LOG_PREFIX+ "WebClientResponseException::" + e.getStatusCode().value()); + log.error(LOG_PREFIX+ "WebClientResponseException Body::" + e.getResponseBodyAsString()); + } catch (WebClientRequestException e) { + Throwable cause = e.getCause(); + if (cause instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectTimeoutException::" + e.getMessage()); + } else if (cause instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "SocketTimeoutException::" + e.getMessage()); + } else if (cause instanceof InterruptedException) { + log.error(LOG_PREFIX+ "InterruptedException::" + e.getMessage()); + } else { + log.error(LOG_PREFIX+ "WebClientRequestException::" + e.getMessage()); + } + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::" + e.getMessage()); + e.printStackTrace(); + } + + + return result; + } + + private String getAPI_KEY(String LOG_PREFIX, HashMap apiInfo) { + LOG_PREFIX = LOG_PREFIX + "::getAPI_KEY::"; + + String apiKey = ""; + String apiAgentCode = apiInfo.get("apiAgentCode"); + String apiToken = apiInfo.get("apiToken"); + String timeStamp = apiInfo.get("timeStamp"); + + log.info(LOG_PREFIX+ "apiAgentCode::"+apiAgentCode); + log.info(LOG_PREFIX+ "apiToken::"+apiToken); + log.info(LOG_PREFIX+ "timeStamp::"+timeStamp); + + String textA = apiAgentCode+apiToken+timeStamp; + String salt = apiToken; + String textB = textA+salt; + log.info(LOG_PREFIX+ "textB::"+textB); + + try { + MessageDigest md = MessageDigest.getInstance("SHA-256"); + md.update(textB.getBytes("UTF-8")); + byte[] digest = md.digest(); + apiKey = new BigInteger(1, digest).toString(16).toLowerCase(); + log.info(LOG_PREFIX+ "apiKey::"+apiKey); + } catch(Exception e) { + log.error(LOG_PREFIX+ "Exception::"+e.getMessage()); + } + + return apiKey; + } + + @Override + public JSONObject getPracpDetail(String LOG_PREFIX, HashMap apiInfo) { + LOG_PREFIX = LOG_PREFIX + "getDetail::"; + JSONObject detailObj = null; + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8"))); + + String apiUrl = apiInfo.get("apiBaseUrl").toString() + "/app/game/detail-url?"; + + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); + long timeStampL = System.currentTimeMillis(); + String timeStamp = sdf.format(timeStampL); + apiInfo.put("timeStamp", timeStamp); + String apiKey = getAPI_KEY(LOG_PREFIX, apiInfo); + String param = "api_key=" + apiKey + "×tamp=" + timeStamp + + "&agent_code=" + apiInfo.get("apiAgentCode") + "&uuid=" + apiInfo.get("uuid") + "&round_id=" + apiInfo.get("round_id") + "&country_code=KR&locale_code=ko"; + apiUrl = apiUrl + param; + log.info(LOG_PREFIX+ "apiUrl::" + apiUrl); + + try { + ResponseEntity resEntity = webClient.get() + .uri(apiUrl) + .headers(h -> h.addAll(headers)) + .retrieve() + .toEntity(String.class) + .block(); + + if(resEntity != null && resEntity.getStatusCode() == HttpStatus.OK) { + JSONObject responseObj = new JSONObject(resEntity.getBody()); + log.info(LOG_PREFIX+ "Response : " + responseObj.toString()); + detailObj = responseObj.getJSONObject("data"); + } + } catch (WebClientResponseException e) { + log.error(LOG_PREFIX+ "WebClientResponseException::" + e.getStatusCode().value()); + log.error(LOG_PREFIX+ "WebClientResponseException Body::" + e.getResponseBodyAsString()); + } catch (WebClientRequestException e) { + Throwable cause = e.getCause(); + if (cause instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "ConnectTimeoutException::" + e.getMessage()); + } else if (cause instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "SocketTimeoutException::" + e.getMessage()); + } else if (cause instanceof InterruptedException) { + log.error(LOG_PREFIX+ "InterruptedException::" + e.getMessage()); + } else { + log.error(LOG_PREFIX+ "WebClientRequestException::" + e.getMessage()); + } + } catch (Exception e) { + log.error(LOG_PREFIX+ "Exception::" + e.getMessage()); + e.printStackTrace(); + } + + return detailObj; + } + + @Override + public String getTplusDetails(String LOG_PREFIX, HashMap apiInfo) { + JSONObject resJson = null; + String detailUrl = null; + LOG_PREFIX = LOG_PREFIX + "tplus::getDetails::"; + + try { + HttpHeaders header = new HttpHeaders(); + header.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + header.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + header.set("Authorization", "Bearer " + apiInfo.get("apiAuthKey")); + + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("pair_transaction_key", apiInfo.get("pairTransactionKey")); + + String apiUrl = apiInfo.get("apiBaseUrl") + "/Details"; + + ResponseEntity response = webClient.post() + .uri(apiUrl) + .headers(h -> h.addAll(header)) + .bodyValue(params) + .retrieve() + .toEntity(String.class) + .block(); + + resJson = new JSONObject(response.getBody()); + if(resJson.getInt("code") == 0) { + log.info(LOG_PREFIX+ "message: " + resJson.getString("message")); + detailUrl = resJson.getString("url"); + log.info(LOG_PREFIX+ "detailUrl: " + detailUrl); + } else { + log.error(LOG_PREFIX+ "code: " + resJson.getInt("code")); + log.error(LOG_PREFIX+ "message: " + resJson.getString("message")); + } + } catch (WebClientResponseException e) { + log.error(LOG_PREFIX+ "[WebClientResponseException]" + e.getStatusCode().value()); + log.error(LOG_PREFIX+ "[WebClientResponseException]" + e.getResponseBodyAsString()); + } catch (WebClientRequestException e) { + Throwable cause = e.getCause(); + if (cause instanceof io.netty.channel.ConnectTimeoutException) { + log.error(LOG_PREFIX+ "[ConnectTimeoutException]" + e.getMessage()); + } else if (cause instanceof io.netty.handler.timeout.ReadTimeoutException) { + log.error(LOG_PREFIX+ "[SocketTimeoutException]" + e.getMessage()); + } else if (cause instanceof InterruptedException) { + log.error(LOG_PREFIX+ "[InterruptedException]" + e.getMessage()); + } else { + log.error(LOG_PREFIX+ "[WebClientRequestException]" + e.getMessage()); + } + } catch(Exception e) { + log.error(LOG_PREFIX+ "Exception::" + e.toString()); + e.printStackTrace(); + } + + return detailUrl; + } + + private boolean hasCause(Throwable e, Class clazz) { + Throwable cause = e; + while (cause != null) { + if (clazz.isInstance(cause)) { + return true; + } + cause = cause.getCause(); + } + return false; + } + + @Override + public String getPragmaticDetails(String lOG_PREFIX, HashMap betInfo) { + try { + String historyUrl = betInfo.get("vendorApiUrl").toString() + "/IntegrationService/v3/http/HistoryAPI/OpenHistoryExtended/"; + String siteIdxStr = betInfo.get("siteHex").toString(); + String playerId = siteIdxStr.toUpperCase() + betInfo.get("memberId").toString(); + String refId = betInfo.get("refId").toString(); + String roundId = refId.replaceAll(betInfo.get("siteId").toString(), ""); + //body + MultiValueMap parameters = new LinkedMultiValueMap<>(); + + + parameters.add("secureLogin", betInfo.get("vendorApiId").toString()); + parameters.add("playerId", playerId); + parameters.add("gameId", betInfo.get("gameIdx").toString()); + parameters.add("roundId", roundId); + + // hash + String hashString = "secureLogin="+ betInfo.get("vendorApiId").toString() + + "&playerId="+playerId + + "&gameId="+betInfo.get("gameIdx").toString() + + "&roundId="+ roundId; + + log.info("Pragmatic hash string:{}", hashString); + parameters.add("hash", StringUtils.md5AndHex(hashString+ betInfo.get("vendorApiKey").toString())); + //header + + HttpHeaders header = new HttpHeaders(); + header.add("Content-Type", "application/x-www-form-urlencoded"); + + + ResponseEntity responseEntity = webClient.post() + .uri(historyUrl) + .headers(h -> h.addAll(header)) + .bodyValue(parameters) + .retrieve() + .toEntity(String.class) + .block(); + + JSONObject resdata = new JSONObject(responseEntity.getBody()); + + if(resdata != null) { + return resdata.getString("url"); + } else { + return ""; + } + } catch(WebClientResponseException e) { + log.error("OpenHistoryExtended WebClientResponseException: {}", e.getStatusCode().value()); + log.error("OpenHistoryExtended WebClientResponseException Body: {}", e.getResponseBodyAsString()); + return ""; + } catch(WebClientRequestException e) { + log.error("OpenHistoryExtended WebClientRequestException: ", e); + return ""; + } catch(Exception e) { + log.error("OpenHistoryExtended Exception: ", e); + return ""; + } + } +} diff --git a/src/main/java/com/bb/util/AesUtil.java b/src/main/java/com/bb/util/AesUtil.java new file mode 100644 index 0000000..047b674 --- /dev/null +++ b/src/main/java/com/bb/util/AesUtil.java @@ -0,0 +1,114 @@ +package com.bb.util; + +import java.nio.charset.StandardCharsets; +import java.security.SecureRandom; +import java.security.spec.AlgorithmParameterSpec; +import java.util.Arrays; +import java.util.Base64; +import java.util.Base64.Decoder; +import java.util.Base64.Encoder; + +import javax.crypto.Cipher; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +public class AesUtil { + + private static final String ALGO = "AES/GCM/NoPadding"; + private static final int IV_LENGTH = 12; // GCM 표준 + private static final int TAG_LENGTH = 128; // 인증 태그 + + // ==== [AES 암호화(인코딩) 메소드] ==== + public static String getAES128_Encode(String data) { + try { + String secretKey = "9944184563minepw"; //비밀키 선언 16바이트 + + byte ivBytes[] = new byte[16]; //AES128비트 암호화에서 16바이트는 변할 수 없다 + Arrays.fill(ivBytes, (byte)0x00); //배열에 초기값 0으로 삽입 실시 + + byte textBytes[] = data.getBytes("UTF-8"); + + AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivBytes); + SecretKeySpec newKey = new SecretKeySpec(secretKey.getBytes("UTF-8"),"AES"); + Cipher cipher = null; + cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher.init(Cipher.ENCRYPT_MODE, newKey, ivSpec); + + Encoder encoder = Base64.getEncoder(); //base64로 다시 포맷해서 인코딩 실시 (경우에 따라 아파치 base64 필요) + return encoder.encodeToString(cipher.doFinal(textBytes)); + } + catch(Exception e) { + System.out.println(e.getMessage()); + } + return ""; + } + + // ==== [AES 복호화(디코딩) 메소드] ==== + public static String getAES128_Decode(String data) { + try { + String secretKey = "9944184563minepw"; //비밀키 선언 16바이트 + + byte ivBytes[] = new byte[16]; //AES128비트 암호화에서 16바이트는 변할 수 없다 + Arrays.fill(ivBytes, (byte)0x00); //배열에 초기값 0으로 삽입 실시 + + Decoder decoder = Base64.getDecoder(); //base64로 다시 포맷해서 디코딩 실시 (경우에 따라 아파치 base64 필요) + byte textBytes[] = decoder.decode(data); + + AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivBytes); + SecretKeySpec newKey = new SecretKeySpec(secretKey.getBytes("UTF-8"),"AES"); + Cipher cipher = null; + cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher.init(Cipher.DECRYPT_MODE, newKey, ivSpec); + + return new String(cipher.doFinal(textBytes),"UTF-8"); + } + catch (Exception e) { + System.out.println(e.getMessage()); + } + return ""; + } + + public static String encrypt(String plainText) throws Exception { + String secretKey = "gwTb1FnH9RbxORzo"; // 반드시 16/24/32 byte + byte[] iv = new byte[IV_LENGTH]; + new SecureRandom().nextBytes(iv); + + Cipher cipher = Cipher.getInstance(ALGO); + SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "AES"); + GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH, iv); + + cipher.init(Cipher.ENCRYPT_MODE, keySpec, spec); + + byte[] encrypted = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8)); + + // iv + ciphertext 합쳐서 URL-safe Base64 + byte[] combined = new byte[iv.length + encrypted.length]; + System.arraycopy(iv, 0, combined, 0, iv.length); + System.arraycopy(encrypted, 0, combined, iv.length, encrypted.length); + + return Base64.getUrlEncoder().withoutPadding().encodeToString(combined); + } + + public static String decrypt(String encoded) throws Exception { + String secretKey = "gwTb1FnH9RbxORzo"; // 반드시 16/24/32 byte + byte[] combined = Base64.getUrlDecoder().decode(encoded); + + byte[] iv = new byte[IV_LENGTH]; + byte[] cipherText = new byte[combined.length - IV_LENGTH]; + + System.arraycopy(combined, 0, iv, 0, IV_LENGTH); + System.arraycopy(combined, IV_LENGTH, cipherText, 0, cipherText.length); + + Cipher cipher = Cipher.getInstance(ALGO); + SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "AES"); + GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH, iv); + + cipher.init(Cipher.DECRYPT_MODE, keySpec, spec); + + byte[] decrypted = cipher.doFinal(cipherText); + + return new String(decrypted, StandardCharsets.UTF_8); + } + +} diff --git a/src/main/java/com/bb/util/DateTimeUtils.java b/src/main/java/com/bb/util/DateTimeUtils.java new file mode 100644 index 0000000..175d5c4 --- /dev/null +++ b/src/main/java/com/bb/util/DateTimeUtils.java @@ -0,0 +1,295 @@ +package com.bb.util; + +import java.sql.Timestamp; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Locale; + +public class DateTimeUtils { + private static final long TIMEOUT = 1000 * 20; + @SuppressWarnings("unused") + private static final SimpleDateFormat FORMAT_YYYYMMDDHHMMSS = new SimpleDateFormat("yyyyMMddHHmmss"); + + public static long getValidDateTime() { + return System.currentTimeMillis() + TIMEOUT; + } + + public static long getValidDateTime(long timeout) { + return System.currentTimeMillis() + timeout; + } + + public static Date now(long time) { + return new Date(time); + } + + public static boolean isBefore(Date date){ + return date.before(new Date()); + } + + /** + * 오라클DB의 DATE형식 객체 생성(현재 년월일시간분초) + * @return Timestamp + */ + public static Timestamp getCurrentTimestamp() { + Calendar calendar = Calendar.getInstance(); + + return new Timestamp(calendar.getTime().getTime()); + } + + /** + * 현재 날짜와 시각을 yyyyMMdd 형태로 반환한다. + * @return String + */ + public static String getYyyymmdd() { + Calendar calendar = Calendar.getInstance(); + Locale currentLocale = new Locale("KOREAN", "KOREA"); + String pattern = "yyyyMMdd"; + SimpleDateFormat formatter = new SimpleDateFormat(pattern, currentLocale); + return formatter.format(calendar.getTime()); + } + + public static String getYyyymmdd2() { + Calendar calendar = Calendar.getInstance(); + Locale currentLocale = new Locale("KOREAN", "KOREA"); + String pattern = "yyyy-MM-dd"; + SimpleDateFormat formatter = new SimpleDateFormat(pattern, currentLocale); + return formatter.format(calendar.getTime()); + } + + + /** + * 현재 날짜와 시각을 Yyyymmddhhmmss 형태로 반환한다. + * + * @return + */ + public static String getYyyymmddhhmmss() { + Calendar calendar = Calendar.getInstance(); + Locale currentLocale = new Locale("KOREAN", "KOREA"); + String pattern = "yyyyMMddHHmmss"; + SimpleDateFormat formatter = new SimpleDateFormat(pattern, currentLocale); + return formatter.format(calendar.getTime()); + } + + public static String getYyyymm() { + Calendar calendar = Calendar.getInstance(); + Locale currentLocale = new Locale("KOREAN", "KOREA"); + String pattern = "yyyy-MM"; + SimpleDateFormat formatter = new SimpleDateFormat(pattern, currentLocale); + return formatter.format(calendar.getTime()); + } + + /** + * 현재 날짜와 시각을 Yyyymmdd 형태로 반환한다. + * + * @param cal + * @return + */ + public static String getYyyymmdd(Calendar cal) { + Locale currentLocale = new Locale("KOREAN", "KOREA"); + String pattern = "yyyy-MM-dd"; + SimpleDateFormat formatter = new SimpleDateFormat(pattern, currentLocale); + return formatter.format(cal.getTime()); + } + + public static String getYyyymm(Calendar cal) { + Locale currentLocale = new Locale("KOREAN", "KOREA"); + String pattern = "yyyy-MM"; + SimpleDateFormat formatter = new SimpleDateFormat(pattern, currentLocale); + return formatter.format(cal.getTime()); + } + + public static String getYyyymmdd(Calendar cal, String pattern) { + Locale currentLocale = new Locale("KOREAN", "KOREA"); + SimpleDateFormat formatter = new SimpleDateFormat(pattern, currentLocale); + return formatter.format(cal.getTime()); + } + + /** + * getGregorianCalendar + * + * @param yyyymmdd + * @return + */ + public static GregorianCalendar getGregorianCalendar(String yyyymmdd) { + + int yyyy = Integer.parseInt(yyyymmdd.substring(0, 4)); + int mm = Integer.parseInt(yyyymmdd.substring(4, 6)); + int dd = Integer.parseInt(yyyymmdd.substring(6)); + + GregorianCalendar calendar = new GregorianCalendar(yyyy, mm - 1, dd, 0, 0, 0); + + return calendar; + + } + + /** + * 지정된 플래그에 따라 연도 , 월 , 일자를 연산한다. + * - 사용 예 + * String date = DateUtil.getOpDate(java.util.Calendar.DATE , 1, "20080101") + * @return String + */ + public static String getOpDate(int field, int amount, String date) { + + GregorianCalendar calDate = getGregorianCalendar(date); + + if (field == Calendar.YEAR) { + calDate.add(GregorianCalendar.YEAR, amount); + } else if (field == Calendar.MONTH) { + calDate.add(GregorianCalendar.MONTH, amount); + } else { + calDate.add(GregorianCalendar.DATE, amount); + } + + return getYyyymmdd(calDate); + + } + + public static String getOpDate2(int field, int amount, String date) { + + GregorianCalendar calDate = getGregorianCalendar(date); + + if (field == Calendar.YEAR) { + calDate.add(GregorianCalendar.YEAR, amount); + } else if (field == Calendar.MONTH) { + calDate.add(GregorianCalendar.MONTH, amount); + } else { + calDate.add(GregorianCalendar.DATE, amount); + } + + return getYyyymmdd(calDate, "yyyyMMdd"); + + + } + + /** + * 2009-03-10 String날짜변수를 2009-03-10 00:00:00 Timestamp 형식으로 반환한다. + * + * @param dateStr + * @return + */ + public static Timestamp replaceTimestamp(String dateStr) { + if(dateStr == null || dateStr.length() != 10) return null; + + String year = dateStr.substring(0, 4); + String month = dateStr.substring(5, 7); + String day = dateStr.substring(8, 10); + + Calendar calendar = Calendar.getInstance(); + + calendar.set( + Integer.parseInt(year), + Integer.parseInt(month)-1, + Integer.parseInt(day), + 0, + 0, + 0 + ); + + return new Timestamp(calendar.getTime().getTime()); + } + + /** + * 두 날짜간의 기간(년,월,일) 계산 메소드 + * 날짜 인자가 하나인 경우 Default today로 처리 + * (나이 계산에 활용) + * + * @param fromDate java.util.String (예) YYYYMMDD + * @return String[3] - 0:Year, 1:Month, 2:Day + */ + public static int getPeriodBetween(String fromDate) + { + return getPeriodBetween(fromDate, getYyyymmdd()); + } + + /** + * 두 날짜간의 기간(년,월,일) 계산 메소드 + * @param fromDate String (예)"20000710" + * @param endDate String (예)"20001111" + * @return String[3] - 0:Year, 1:Month, 2:Day + */ + public static int getPeriodBetween(String fromDate, String endDate) + { + // fromDate가 endDate보다 클 경우 swap + if (fromDate.compareTo(endDate) > 0) + { + String temp; + temp = fromDate; + fromDate = endDate; + endDate = temp; + } + + int fromYYYY= Integer.parseInt(fromDate.substring(0,4)); + int fromMM = Integer.parseInt(fromDate.substring(4,6)); + int fromDD = Integer.parseInt(fromDate.substring(6,8)); + int endYYYY = Integer.parseInt(endDate.substring(0,4)); + int endMM = Integer.parseInt(endDate.substring(4,6)); + int endDD = Integer.parseInt(endDate.substring(6,8)); + + int iYearCount = endYYYY - fromYYYY; + int iMonthCount = 0; + int iDayCount = 0; + + if(fromDate.substring(4,8).compareTo(endDate.substring(4,8)) > 0) + { + iYearCount--; + iMonthCount = (12-fromMM) + endMM; + } + else + { + //iYearCount = iYearCount; + iMonthCount = endMM - fromMM; + } + + int lastDate = 0; + if(fromDD > endDD) + { + iMonthCount--; + lastDate = getDaysOfMonth(fromYYYY, fromMM); + iDayCount = (lastDate-fromDD) + endDD; + } + else + { + iDayCount = endDD - fromDD; + } + return iDayCount + lastDate; + } + + /** + * 입력한 달의 Day count 를 return + * + * @param year as String + * @param month as String + * @return int the count of month + */ + public static int getDaysOfMonth (String year, String month) + { + if(year == null || month == null) return -1; + return getDaysOfMonth (Integer.parseInt(year), Integer.parseInt(month)) ; + } + + /** + * 입력한 달의 Day count 를 return + * + * @param year as int + * @param month as int + * @return int the count of month + */ + public static int getDaysOfMonth (int year, int month) + { + if(month < 1 || month > 12) return -1; + + if(month == 2) + { + if ( ((year%4 == 0) && (year%100 != 0)) || (year%400 == 0) ) + return 29; + else + return 28; + } + else if(month==4||month==6||month==9||month==11) + return 30; + else + return 31; + } +} diff --git a/src/main/java/com/bb/util/GameInsert.java b/src/main/java/com/bb/util/GameInsert.java new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/com/bb/util/HmacUtils.java b/src/main/java/com/bb/util/HmacUtils.java new file mode 100644 index 0000000..71a9414 --- /dev/null +++ b/src/main/java/com/bb/util/HmacUtils.java @@ -0,0 +1,30 @@ +package com.bb.util; + +import java.nio.charset.StandardCharsets; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; + +public class HmacUtils { + + public static String hmacSha256Hex(String secret, String message) { + try { + Mac mac = Mac.getInstance("HmacSHA256"); + SecretKeySpec key = + new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); + mac.init(key); + + byte[] raw = mac.doFinal(message.getBytes(StandardCharsets.UTF_8)); + return bytesToHex(raw); + + } catch (Exception e) { + throw new RuntimeException("HMAC error", e); + } + } + + private static String bytesToHex(byte[] bytes) { + StringBuilder sb = new StringBuilder(bytes.length * 2); + for (byte b : bytes) sb.append(String.format("%02x", b)); + return sb.toString(); + } +} diff --git a/src/main/java/com/bb/util/HttpUtil.java b/src/main/java/com/bb/util/HttpUtil.java new file mode 100644 index 0000000..6550520 --- /dev/null +++ b/src/main/java/com/bb/util/HttpUtil.java @@ -0,0 +1,93 @@ +package com.bb.util; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; + +public class HttpUtil { + + + public static String httpPostBodyConnection(String UrlData, String ParamData) { + + //http 요청 시 필요한 url 주소를 변수 선언 + String totalUrl = ""; + totalUrl = UrlData.trim().toString(); + + //http 통신을 하기위한 객체 선언 실시 + URL url = null; + HttpURLConnection conn = null; + + //http 통신 요청 후 응답 받은 데이터를 담기 위한 변수 + String responseData = ""; + BufferedReader br = null; + StringBuffer sb = null; + + //메소드 호출 결과값을 반환하기 위한 변수 + String returnData = ""; + + try { + //파라미터로 들어온 url을 사용해 connection 실시 + url = new URL(totalUrl); + conn = (HttpURLConnection) url.openConnection(); + + //http 요청에 필요한 타입 정의 실시 + conn.setRequestMethod("POST"); + conn.setRequestProperty("Content-Type", "application/json; utf-8"); //post body json으로 던지기 위함 + conn.setRequestProperty("Accept", "application/json"); + conn.setDoOutput(true); //OutputStream을 사용해서 post body 데이터 전송 + try (OutputStream os = conn.getOutputStream()){ + byte request_data[] = ParamData.getBytes("utf-8"); + os.write(request_data); + os.close(); + } + catch(Exception e) { + e.printStackTrace(); + } + + //http 요청 실시 + conn.connect(); + System.out.println("http 요청 방식 : "+"POST BODY JSON"); + System.out.println("http 요청 타입 : "+"application/json"); + System.out.println("http 요청 주소 : "+UrlData); + System.out.println("http 요청 데이터 : "+ParamData); + System.out.println(""); + + //http 요청 후 응답 받은 데이터를 버퍼에 쌓는다 + br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8")); + sb = new StringBuffer(); + while ((responseData = br.readLine()) != null) { + sb.append(responseData); //StringBuffer에 응답받은 데이터 순차적으로 저장 실시 + } + + //메소드 호출 완료 시 반환하는 변수에 버퍼 데이터 삽입 실시 + returnData = sb.toString(); + + //http 요청 응답 코드 확인 실시 + String responseCode = String.valueOf(conn.getResponseCode()); + System.out.println("http 응답 코드 : "+responseCode); + System.out.println("http 응답 데이터 : "+returnData); + + + + } catch (IOException e) { + e.printStackTrace(); + } finally { + //http 요청 및 응답 완료 후 BufferedReader를 닫아줍니다 + try { + if (br != null) { + br.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + + return returnData; + } + } + + + +} diff --git a/src/main/java/com/bb/util/IPKit.java b/src/main/java/com/bb/util/IPKit.java new file mode 100644 index 0000000..e869b96 --- /dev/null +++ b/src/main/java/com/bb/util/IPKit.java @@ -0,0 +1,201 @@ +package com.bb.util; + + + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.security.MessageDigest; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpSession; + + +public class IPKit { + + public static String getIpAddressByRequest(HttpServletRequest request) { + String ip = request.getHeader("x-forwarded-for"); + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + + String[] ipArray = ip.split(","); + ip = ipArray[0]; + + return ip; + } + + public static String getIpAddressByRequest1(HttpServletRequest request) { + String ip = request.getHeader("X-Forwarded-For"); + if(!StringUtils.isEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)){ + int index = ip.indexOf(","); + if(index != -1){ + return ip.substring(0,index); + }else{ + return ip; + } + } + + ip = request.getHeader("X-Real-IP"); + if(!StringUtils.isEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)){ + return ip; + } + return request.getRemoteAddr(); + } + + public static String viewPage(HttpServletRequest request, String page) { + HttpSession session = request.getSession(true); + + String userAgent = request.getHeader("user-agent"); + String referer = request.getHeader("referer"); + String vt = ""; + if(!(request.getParameter("vt") == null || "".equals(request.getParameter("vt")))) { + vt = request.getParameter("vt"); + + if("M".equals(vt)) { + session.setAttribute("isMobile", "mobile"); + } + + if("W".equals(vt)) { + session.setAttribute("isMobile", "web"); + } + }else { + session.setAttribute("isMobile", ""); + } + + + + + + Boolean isMobile = false; + + String url = request.getRequestURI(); + String domain = request.getRequestURL().toString().replace(request.getRequestURI(),"/"); + + String viewName=page; + isMobile = userAgent.contains("Mobile/") + || userAgent.contains("Android") + || userAgent.contains("iPhone") + || userAgent.contains("iPad"); + + + if(isMobile) { + viewName = "mobile/"+viewName; + } else { + + + if("mobile".equals(session.getAttribute("isMobile").toString())) { + return "mobile/"+viewName; + }else { + return "front/"+viewName; + } + + + } + + return viewName; + +} + + + public static String shaEnc(String base) { + + + try{ + + MessageDigest digest = MessageDigest.getInstance("SHA-256"); + byte[] hash = digest.digest(base.getBytes("UTF-8")); + StringBuffer hexString = new StringBuffer(); + + for (int i = 0; i < hash.length; i++) { + String hex = Integer.toHexString(0xff & hash[i]); + if(hex.length() == 1) hexString.append('0'); + hexString.append(hex); + } + + //출력 + return hexString.toString(); + + } catch(Exception ex){ + throw new RuntimeException(ex); + } + } + + + // Add Firewall rule + public static void allowInboundTraffic(String LOG_PREFIX, String ipAddress) throws Exception { + if (ipAddress == null || ipAddress.isEmpty()) { + throw new IllegalArgumentException("IP address cannot be null or empty"); + } + + // Split the IP addresses if multiple are provided, separated by commas + String[] ipAddresses = ipAddress.split(","); + + for (String ip : ipAddresses) { + ip = ip.trim(); // Remove any leading or trailing spaces + if (ip.isEmpty()) { + continue; // Skip empty entries + } + + String family; + try { + InetAddress inetAddress = InetAddress.getByName(ip); + if (inetAddress instanceof Inet6Address) { + family = "ipv6"; + } else if (inetAddress instanceof Inet4Address) { + family = "ipv4"; + } else { + throw new IllegalArgumentException("Unknown IP address type: " + ip); + } + } catch (Exception e) { + throw new IllegalArgumentException("Invalid IP address: " + ip, e); + } + + // Commands to allow inbound traffic for ports 80 and 443 + String[] commands = { + String.format("sudo firewall-cmd --permanent --add-rich-rule='rule family=\"%s\" source address=\"%s\" port protocol=\"tcp\" port=\"80\" accept'", family, ip), + String.format("sudo firewall-cmd --permanent --add-rich-rule='rule family=\"%s\" source address=\"%s\" port protocol=\"tcp\" port=\"443\" accept'", family, ip) + }; + + for (String command : commands) { + executeCommand(command); + } + } + + // 마지막에 한 번만 reload! + executeCommand("sudo firewall-cmd --reload"); + } + + // Execute shell command + private static void executeCommand(String command) throws Exception { + System.out.println("실행중: " + command); + Process process = Runtime.getRuntime().exec(new String[] { "bash", "-c", command }); // bash shell 사용 권장 + int exitCode = process.waitFor(); + + if (exitCode != 0) { + try (BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) { + StringBuilder errorMessage = new StringBuilder(); + String line; + while ((line = errorReader.readLine()) != null) { + errorMessage.append(line).append("\n"); + } + throw new RuntimeException("Error executing command: " + command + "\n" + errorMessage.toString()); + } + } else { + try (BufferedReader outputReader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { + String line; + while ((line = outputReader.readLine()) != null) { + System.out.println(line); + } + } + } + } +} diff --git a/src/main/java/com/bb/util/OkhttpUtils.java b/src/main/java/com/bb/util/OkhttpUtils.java new file mode 100644 index 0000000..98cf1d8 --- /dev/null +++ b/src/main/java/com/bb/util/OkhttpUtils.java @@ -0,0 +1,128 @@ +package com.bb.util; + +import java.io.IOException; +import java.security.cert.CertificateException; +import java.util.HashMap; +import java.util.Map; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import com.google.gson.Gson; + +import lombok.extern.slf4j.Slf4j; +import okhttp3.Headers; +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; + +@Slf4j +public class OkhttpUtils { + + private static OkHttpClient client = null; + private static boolean ignoreSslCertificate = false; + + public static OkHttpClient getClient() { + return client; + } + + public static void init(boolean ignoreCertificate) throws Exception { + + OkHttpClient.Builder builder = new OkHttpClient.Builder(); + + log.info("Initialising httpUtil with default configuration"); + if (ignoreCertificate) { + ignoreSslCertificate = true; + builder = configureToIgnoreCertificate(builder); + } + + //Other application specific configuration + + client = builder.build(); + } + + //Setting testMode configuration. If set as testMode, the connection will skip certification check + private static OkHttpClient.Builder configureToIgnoreCertificate(OkHttpClient.Builder builder) { + log.info("Ignore Ssl Certificate"); + try { + + // Create a trust manager that does not validate certificate chains + final TrustManager[] trustAllCerts = new TrustManager[] { + new X509TrustManager() { + @Override + public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) + throws CertificateException { + } + + @Override + public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) + throws CertificateException { + } + + @Override + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return new java.security.cert.X509Certificate[]{}; + } + } + }; + + // Install the all-trusting trust manager + final SSLContext sslContext = SSLContext.getInstance("SSL"); + sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); + // Create an ssl socket factory with our all-trusting manager + final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); + + builder.sslSocketFactory(sslSocketFactory, (X509TrustManager)trustAllCerts[0]); + builder.hostnameVerifier(new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + return true; + } + }); + } catch (Exception e) { + log.error("Exception while configuring IgnoreSslCertificate" + e, e); + } + + return builder; + } + + /** + * post 호출 + * @param url + * @param body + * @param mediaType + * @return + */ + public static String post(String url, Map body, MediaType mediaType) { + try { + init(true); + OkHttpClient client = getClient(); + log.info("OkHttpClient Request body : " + new Gson().toJson(body)); + RequestBody requestBody = RequestBody.create(mediaType, new Gson().toJson(body)); + log.info("OkHttpClient contentType : " + requestBody.contentType()); + + Request request = new Request.Builder() + .url(url) + .header("User-agent", "PostmanRuntime/7.40.0") + .addHeader("Content-Type", "application/json") + .post(requestBody) + .build(); + log.info("OkHttpClient Request : " + request.toString()); + + Response response = client.newCall(request).execute(); + return response.body().string(); + } catch (IOException e) { + log.error(e.getMessage(), e); + throw new RuntimeException(e); + } catch(Exception e) { + log.error(e.getMessage(), e); + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/com/bb/util/PagingUtil.java b/src/main/java/com/bb/util/PagingUtil.java new file mode 100644 index 0000000..fa3e92d --- /dev/null +++ b/src/main/java/com/bb/util/PagingUtil.java @@ -0,0 +1,90 @@ +package com.bb.util; + +import com.bb.model.PageFormVO; + +/** + * 페이지 네비게이션 정보 설정을 위한 클래스 + */ +public class PagingUtil { + + + + + public static PageFormVO setPageUtil(PageFormVO pageFormVO) { + //System.out.println("currentPage" + pageFormVO.getPage()); + if(pageFormVO.getPage() == 0) { + //System.out.println("currentPagee" + pageFormVO.getPage()); + pageFormVO.setPage(1); + } + //System.out.println("currentPage" + pageFormVO.getPage()); + + String pagination = ""; // 페이징 결과 값 + String functionName = pageFormVO.getFunction_name(); // 페이징 목록을 요청하는 자바스크립트 함수명 + int currentPage = pageFormVO.getPage(); // 현재 페이지 번호 + + //System.out.println("currentPage" + currentPage); + int countPerList = pageFormVO.getCount_per_list(); // 한 화면에 출력될 게시물 수 + int countPerPage = pageFormVO.getCount_per_page(); // 한 화면에 출력될 페이지 수 + int totalListCount = pageFormVO.getTatal_list_count(); // 총 게시물 수 + int totalPageCount = totalListCount / countPerList; // 총 페이지 수 + if (totalListCount % countPerList > 0) { // 총 페이수를 구할 때 int형으로 계산하면 나머지가 있는 경우 게시물이 존재하기 때문에 총 페이지의 수를 수정 + totalPageCount = totalPageCount + 1; + } + + int viewFirstPage = (((currentPage - 1) / countPerPage) * countPerPage) + 1; // 한 화면에 첫 페이지 번호 + int ViewLastPage = viewFirstPage + countPerPage - 1; // 한 화면에 마지막 페이지 번호 + if (ViewLastPage > totalPageCount) { // 마지막 페이지의 수가 총 페이지의 수보다 큰 경우는 게시물이 존재하지 않기 때문에 마지막 페이지의 수를 수정 + ViewLastPage = totalPageCount; + } + + int totalFirstPage = 1; // 전체 페이지 중에 처음 페이지 + int totalLastPage = totalPageCount; // 전체 페이지 중에 마지막 페이지 + int prePerPage = 0; // 이전 화면에 첫번째 번호 + if (viewFirstPage - countPerPage > 0) { + prePerPage = viewFirstPage - countPerPage; + } else { + prePerPage = totalFirstPage; + } + int nextPerPage = 0; // 이후 화면에 첫번째 번호 + if (viewFirstPage + countPerPage < totalPageCount) { + nextPerPage = viewFirstPage + countPerPage; + } else { + nextPerPage = totalPageCount; + } + + // 페이지 네이게이션 설정 + + + pagination += "
"; + // pagination += "
Total Page :" + totalPageCount +"
"; +// pagination += "
"; + //pagination += " "; + + pagination += " "; + + //pagination += " "; + for (int a = viewFirstPage; a <= ViewLastPage; a++) { + if (a == currentPage) { + // pagination += " "+a+""; + // pagination += " "+a+""; + pagination += " "; + } else { + pagination += " "; + } + } + //pagination += " "; + // pagination += " "; + pagination += " "; + //pagination += "
"; + pagination += "
"; + + int offset = ((currentPage - 1) * countPerList) ; // 한 화면의 표출되는 게시물의 시작 번호의 -1 (쿼리 조건절) + + // LIMIT는 가져올 row의 수, OFFSET은 몇 번째 row부터 가져올지를 결정 + pageFormVO.setLimit(countPerList); + pageFormVO.setOffset(offset); + pageFormVO.setPagination(pagination); + + return pageFormVO; + } +} diff --git a/src/main/java/com/bb/util/SHA256.java b/src/main/java/com/bb/util/SHA256.java new file mode 100644 index 0000000..daafa23 --- /dev/null +++ b/src/main/java/com/bb/util/SHA256.java @@ -0,0 +1,24 @@ +package com.bb.util; + + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class SHA256 { + + public String encrypt(String text) throws NoSuchAlgorithmException { + MessageDigest md = MessageDigest.getInstance("SHA-256"); + md.update(text.getBytes()); + + return bytesToHex(md.digest()); + } + + private String bytesToHex(byte[] bytes) { + StringBuilder builder = new StringBuilder(); + for (byte b : bytes) { + builder.append(String.format("%02x", b)); + } + return builder.toString(); + } + +} \ No newline at end of file diff --git a/src/main/java/com/bb/util/SHA256WithRSA.java b/src/main/java/com/bb/util/SHA256WithRSA.java new file mode 100644 index 0000000..2c745a3 --- /dev/null +++ b/src/main/java/com/bb/util/SHA256WithRSA.java @@ -0,0 +1,109 @@ +package com.bb.util; + +import java.io.UnsupportedEncodingException; +import java.security.*; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.Base64; + +import javax.crypto.Cipher; + +public class SHA256WithRSA { + + /** + * 암호화 + */ + static String encode(String plainData, String stringPublicKey) { + String encryptedData = null; + try { + //평문으로 전달받은 공개키를 공개키객체로 만드는 과정 + PublicKey publicKey = getPublicKey(stringPublicKey); + //만들어진 공개키객체를 기반으로 암호화모드로 설정하는 과정 + Cipher cipher = Cipher.getInstance("RSA"); + cipher.init(Cipher.ENCRYPT_MODE, publicKey); + //평문을 암호화하는 과정 + byte[] byteEncryptedData = cipher.doFinal(plainData.getBytes()); + encryptedData = Base64.getEncoder().encodeToString(byteEncryptedData); + } catch (Exception e) { + e.printStackTrace(); + } + return encryptedData; + } + + static PublicKey getPublicKey(String stringPublicKey) { + PublicKey publicKey = null; + try { + //평문으로 전달받은 공개키를 공개키객체로 만드는 과정 + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + byte[] bytePublicKey = Base64.getDecoder().decode(stringPublicKey.getBytes()); + X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(bytePublicKey); + publicKey = keyFactory.generatePublic(publicKeySpec); + } catch (Exception e) { + e.printStackTrace(); + } + return publicKey; + } + + /** + * 복호화 + */ + static String decode(String encryptedData, String stringPrivateKey) { + String decryptedData = null; + try { + //평문으로 전달받은 개인키를 개인키객체로 만드는 과정 + PrivateKey privateKey = getPrivateKey(stringPrivateKey); + //만들어진 개인키객체를 기반으로 암호화모드로 설정하는 과정 + Cipher cipher = Cipher.getInstance("RSA"); + cipher.init(Cipher.DECRYPT_MODE, privateKey); + //암호문을 평문화하는 과정 + byte[] byteEncryptedData = Base64.getDecoder().decode(encryptedData.getBytes()); + byte[] byteDecryptedData = cipher.doFinal(byteEncryptedData); + decryptedData = new String(byteDecryptedData); + } catch (Exception e) { + e.printStackTrace(); + } + return decryptedData; + } + + static PrivateKey getPrivateKey(String stringPrivateKey) { + PrivateKey privateKey = null; + try { + //평문으로 전달받은 개인키를 개인키객체로 만드는 과정 + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + byte[] bytePrivateKey = Base64.getDecoder().decode(stringPrivateKey.getBytes()); + PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(bytePrivateKey); + privateKey = keyFactory.generatePrivate(privateKeySpec); + } catch (Exception e) { + e.printStackTrace(); + } + return privateKey; + } + + public static String sign(String plainText, String strPrivateKey) { + try { + PrivateKey privateKey = getPrivateKey(strPrivateKey); + Signature privateSignature = Signature.getInstance("SHA256withRSA"); + privateSignature.initSign(privateKey); + privateSignature.update(plainText.getBytes("UTF-8")); + byte[] signature = privateSignature.sign(); + return Base64.getEncoder().encodeToString(signature); + } catch (NoSuchAlgorithmException | InvalidKeyException | UnsupportedEncodingException | SignatureException e) { + throw new RuntimeException(e); + } + } + + public static boolean verifySignarue(String plainText, String signature, String strPublicKey) { + boolean result = false; + Signature sig; + try { + PublicKey publicKey = getPublicKey(strPublicKey); + sig = Signature.getInstance("SHA256withRSA"); + sig.initVerify(publicKey); + sig.update(plainText.getBytes()); + result = sig.verify(Base64.getDecoder().decode(signature)); + } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) { + throw new RuntimeException(e); + } + return result; + } +} diff --git a/src/main/java/com/bb/util/StringUtils.java b/src/main/java/com/bb/util/StringUtils.java new file mode 100644 index 0000000..e0a6bbc --- /dev/null +++ b/src/main/java/com/bb/util/StringUtils.java @@ -0,0 +1,464 @@ +package com.bb.util; + +import java.io.StringReader; +import java.nio.charset.StandardCharsets; +import java.security.InvalidKeyException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.text.DecimalFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Base64; +import java.util.Base64.Encoder; +import java.util.Date; +import java.util.Map; +import java.util.Random; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; + +// XML Parser 패키지 (Spring Boot 3/JDK 17 환경에 맞춰 javax 유지) +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.w3c.dom.Document; +import org.xml.sax.InputSource; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public class StringUtils { + + private static final ObjectMapper objectMapper = new ObjectMapper(); + + /** + * 문자열이 JSON 형태인지 검사 + */ + public static boolean isJson(String input) { + if (input == null || input.trim().isEmpty()) return false; + + try { + objectMapper.readTree(input); + return true; + } catch (Exception e) { + return false; + } + } + + /** + * 문자열이 URL 형태인지 정규식으로 검사 + */ + public static boolean isUrl(String input) { + if (input == null || input.trim().isEmpty()) return false; + + // http, https, ftp 등 다양한 프로토콜 대응 + String regex = "^(https?|ftp)://[^\\s/$.?#].[^\\s]*$"; + return input.matches(regex); + } + + /** + * 문자열이 JSON / URL / 기타 중 어떤 형태인지 구분 + */ + public static String getType(String input) { + if (isJson(input)) return "JSON"; + if (isUrl(input)) return "URL"; + return "UNKNOWN"; + } + + /** + * 문자열이 NULL이거나 빈값인지 검사 + * * @param string + * @return + */ + public static boolean isEmpty(String string) { + return string == null || string.trim().isEmpty(); + } + + /** + * null값인 문자열 기본값으로 대체 + * * @param string + * @param defaultValue + * @return + */ + public static String nullValue(String string, String defaultValue) { + if (isEmpty(string)) { + return defaultValue; + } else { + return string; + } + } + + /** + * null값인 문자열 기본값으로 대체 + * * @param string + * @param defaultValue + * @return + */ + public static String nullValue(String string, int defaultValue) { + if (isEmpty(string)) { + return String.valueOf(defaultValue); + } else { + return string; + } + } + + /** + * null값인 문자열 기본값으로 대체 + * * @param string + * @param defaultValue + * @return + */ + public static String nullValue(String string, float defaultValue) { + if (isEmpty(string)) { + return String.valueOf(defaultValue); + } else { + return string; + } + } + + /** + * null값인 문자열 기본값으로 대체 + * * @param string + * @return + */ + public static String nullValue(String string) { + return nullValue(string, ""); + } + + /** + * 문자열 배열을 합친다 + * * @param strings + * @param separater + * @return + */ + public static String join(String[] strings, String separater) { + String joinedString = ""; + + for (int i = 0; i < strings.length; i++) { + joinedString += (joinedString.length() > 0 ? separater : "") + strings[i]; + } + + return joinedString; + } + + /** + * Map의 키값을 문자열 배열로 얻는다 + * * @param map + * @return + */ + public static String[] getArrayFrom(Map map) { + String[] strings = new String[map.size()]; + + int i = 0; + for (Object key : map.keySet()) { + strings[i++] = key.toString(); + } + + return strings; + } + + /** + * Map의 키값을 문자열로 얻는다 + * * @param map + * @param separater + * @return + */ + public static String getStringFrom(Map map, String separater) { + return join(getArrayFrom(map), separater); + } + + /** + * 닉네임용 문자 난수발생기 + * * @param length + * @return + */ + public static String generateString(int length) { + + Random rnd = new Random(); + StringBuffer buf = new StringBuffer(); + String returnStr = ""; + + for (int i = 0; i < length; i++) { + if (i == 0 || rnd.nextBoolean()) { + buf.append((char) ((int) (rnd.nextInt(26)) + 97)); // 영문소문자 a ~ z + } else { + buf.append((rnd.nextInt(9) + 1)); // 숫자 1 ~ 9 + } + + } + returnStr = buf.toString(); + + if (returnStr.indexOf("xxx") + returnStr.indexOf("sex") + returnStr.indexOf("fuck") + returnStr.indexOf("nude") + + returnStr.indexOf("666") >= 0) { + returnStr = generateString(length); + } + return returnStr; + } + + /** + * 인증번호용 난수발생기 + * * @param length + * @return + */ + public static String generateNumber(int length) { + + String numStr = "1"; + String plusNumStr = "1"; + + for (int i = 0; i < length; i++) { + numStr += "0"; + + if (i != length - 1) { + plusNumStr += "0"; + } + } + + Random random = new Random(); + int result = random.nextInt(Integer.parseInt(numStr)) + Integer.parseInt(plusNumStr); + + if (result > Integer.parseInt(numStr)) { + result = result - Integer.parseInt(plusNumStr); + } + + return String.valueOf(result); + } + + public static String mask(String origin, int length, String mask) { + StringBuilder masked = new StringBuilder(origin.substring(0, length)); + + for (int i = 0; i < origin.length() - length; i++) { + masked.append(mask); + } + + return masked.toString(); + } + + public static String numberFormat(Object number, String pattern) { + DecimalFormat df = new DecimalFormat(pattern); + return df.format(number); + } + + public static String randomCharNum(int wordLength) { + Random r = new Random(); + StringBuilder sb = new StringBuilder(wordLength); + for(int i = 0; i < wordLength; i++) { + if(r.nextBoolean()){ + sb.append((char)((int)(r.nextInt(26))+97)); + }else{ + sb.append((r.nextInt(10))); + } + } + return sb.toString(); + } + + /** + * MD5 해시 후 Hex 문자열 변환 + * (에러 원인인 DatatypeConverter 패키지 대신 표준 StringBuilder 사용) + */ + public static String md5AndHex(String plainText) throws NoSuchAlgorithmException { + + //MessageDigest 인스턴스 생성(MD5) + MessageDigest md = MessageDigest.getInstance("MD5"); + + //해쉬값 업데이트 + md.update(plainText.getBytes()); + byte[] digest = md.digest(); + + //Byte To Hex String (기존 DatatypeConverter 대체 로직) + StringBuilder sb = new StringBuilder(); + for (byte b : digest) { + sb.append(String.format("%02X", b)); + } + return sb.toString(); + } + + + public static String makeApiKey(String param) { + + int n = 20; // n자리 쿠폰 + char[] chs = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' ,'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; + + + Random rd = new Random(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < n; i++) { + char ch = chs[rd.nextInt(chs.length)]; + sb.append(ch); + } + return param + sb.toString(); + + + } + + public static String makeApiKey(String param, int n) { + + + char[] chs = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' ,'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; + + + Random rd = new Random(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < n; i++) { + char ch = chs[rd.nextInt(chs.length)]; + sb.append(ch); + } + return param + sb.toString(); + + + } + + public static String makeRandomKey(int length) { + int leftLimit = 48; // numeral '0' + int rightLimit = 122; // letter 'z' + int targetStringLength = length; + Random random = new Random(); + String generatedString = random.ints(leftLimit, rightLimit + 1) + .filter(i -> (i <= 57 || i >= 65) && (i <= 90 || i >= 97)) + .limit(targetStringLength) + .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append) + .toString(); + System.out.println("### makeRandomKey : " + generatedString); + return generatedString; + } + + public static String replaceAll(String str, String p, String a) { + + + return str.replaceAll(p, a); + } + + public static Document convertStringToXMLDocument(String xmlString) { + //Parser that produces DOM object trees from XML content + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + + //API to obtain DOM Document instance + DocumentBuilder builder = null; + try { + //Create DocumentBuilder with default configuration + builder = factory.newDocumentBuilder(); + + //Parse the content to Document object + Document doc = builder.parse(new InputSource(new StringReader(xmlString))); + return doc; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static String hashing(String msg, String key) { + String result =""; + try { + Encoder encoder = Base64.getEncoder(); + + Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); + SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(), "HmacSHA256"); + sha256_HMAC.init(secret_key); + + byte[] bt = sha256_HMAC.doFinal(msg.getBytes()); + String hash = encoder.encodeToString(bt); + result = hash; + }catch(Exception e) {} + return result; + } + + + + public static class StringBuilderPlus { + + private StringBuilder sb; + + public StringBuilderPlus(){ + sb = new StringBuilder(); + } + + public void append(String str) + { + sb.append(str != null ? str : ""); + } + + public void appendLine(String str) + { + sb.append(str != null ? str : "").append(System.getProperty("line.separator")); + } + + public String toString() + { + return sb.toString(); + } + } + + + public static boolean isNumberic(String str) { + boolean result = true; + for(char c : str.toCharArray()){ + if(!Character.isDigit(c)) { + result = false; + break; + } + } + return result; + } + + public static String extractLink(String script) { // 정규 표현식을 사용하여 location.href 값 추출 + String regex = "location\\.href='(.*?)'"; + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(script); + + if (matcher.find()) { + return matcher.group(1); + } else { + throw new IllegalArgumentException("유효한 링크를 찾을 수 없습니다."); + } + } + + public static String convertToDateOnly(String dateTime) { + String result = ""; + try { // Define the input and output date formats + SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + SimpleDateFormat outputFormat = new SimpleDateFormat("yyyy-MM-dd"); + + // Parse the input date string + Date date = inputFormat.parse(dateTime); + + // Format the date to the desired output format + result = outputFormat.format(date); + } catch (ParseException e) { + e.printStackTrace(); + } + return result; + } + + /** + * DB 저장용 문자열을 안전하게 잘라주는 메서드 + * @param body 자를 대상 문자열 (예: response.getBody()) + * @param limitBytes 최대 허용 바이트 수 (예: VARCHAR(100) → 100) + * @return 잘린 문자열 (너무 길면 ... 표시 포함) + */ + public static String truncateBodyForDb(String body, int limitBytes) { + if (body == null) return null; + + byte[] utf8Bytes = body.getBytes(StandardCharsets.UTF_8); + if (utf8Bytes.length <= limitBytes) { + return body; + } + + // 바이트 단위로 자르기 + int endIndex = body.length(); + while (endIndex > 0) { + String candidate = body.substring(0, endIndex); + if (candidate.getBytes(StandardCharsets.UTF_8).length <= limitBytes - 3) { // "..." 고려 + return candidate + "..."; + } + endIndex--; + } + + // 혹시라도 한 글자도 안 남는 경우 (이론상 거의 없음) + return body.substring(0, Math.min(body.length(), 3)) + "..."; + } +} \ No newline at end of file diff --git a/src/main/java/com/bb/util/TOTPTokenGenerator.java b/src/main/java/com/bb/util/TOTPTokenGenerator.java new file mode 100644 index 0000000..896ba43 --- /dev/null +++ b/src/main/java/com/bb/util/TOTPTokenGenerator.java @@ -0,0 +1,57 @@ +package com.bb.util; + +import com.bb.model.OTPInfo; +import com.warrenstrange.googleauth.GoogleAuthenticator; +import com.warrenstrange.googleauth.GoogleAuthenticatorKey; +import com.warrenstrange.googleauth.GoogleAuthenticatorQRGenerator; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class TOTPTokenGenerator { + + private static String GOOGLE_URL = "https://www.google.com/chart?chs=200x200&chld=M|0&cht=qr&chl="; + + private TOTPTokenGenerator() { + //throw new RuntimeException("TOTPTokenUtil"); + } + + /** + * OTP 정보 URL 생성 + * @param secretKey - generateSecretKey 메서드 리턴 값 + * @param issuer - OTP 발급자(사이트 도메인) + * @param userName - OTP 발급하는 사용자 이름 + * @return Google Authenticator에 전달할 정보 URL + * @throws Exception + */ + //QR-Code 생성 [개인키, 계정명(유저ID), 발급자(회사명)을 받아서 구글OTP 인증용 링크를 생성하는 메소드] + public static OTPInfo getGoogleAuthQRUrl(OTPInfo info) { + try { + GoogleAuthenticator googleAuthenticator = new GoogleAuthenticator(); + GoogleAuthenticatorKey googleAuthenticatorKey = googleAuthenticator.createCredentials(); + + // 실제론 생성한 key를 DB에 저장해놔야 나중에 OTP를 검증할 수 있음 + String secretKey = googleAuthenticatorKey.getKey(); + info.setSecretKey(secretKey); + log.info("#-QR_OTP::secretKey : " + secretKey); + + String QRUrl = GoogleAuthenticatorQRGenerator.getOtpAuthURL(info.getIssuer(), info.getAccount(), googleAuthenticatorKey); + info.setUrl(QRUrl); + log.info("#-QR_OTP::URL : " + QRUrl); + log.info("#-QR_OTP::info : " + info); + + } catch (Exception e) { + e.printStackTrace(); + } + return info; + } + + public static boolean otpVerify(String secret, int code) { + boolean verify = false; + GoogleAuthenticator googleAuthenticator = new GoogleAuthenticator(); + verify = googleAuthenticator.authorize(secret, code); + log.info("#-QR_OTP::Verify : {}", verify); + + return verify; + } +} diff --git a/src/main/java/com/bb/util/TempKey.java b/src/main/java/com/bb/util/TempKey.java new file mode 100644 index 0000000..0f4e82e --- /dev/null +++ b/src/main/java/com/bb/util/TempKey.java @@ -0,0 +1,50 @@ +package com.bb.util; + +import java.util.Random; + +public class TempKey { + + private boolean lowerCheck; + private int size; + + + public String generateAuthKey() { + String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + int charRandomIndex = (int)(Math.random()* (characters.length()-1) + 1); + int randomNum = 1000000 + (int)(Math.random()*9999999); + + char selectString = characters.charAt(charRandomIndex); + return randomNum + Character.toString(selectString); + } + + + + public String getKey(int size, boolean lowerCheck) { + this.size = size; + this.lowerCheck = lowerCheck; + return init(); + } + public String getKey(int size) { + this.size = size; + return init(); + } + + private String init() { + Random ran = new Random(); + StringBuffer sb = new StringBuffer(); + int num = 0; + do { + num = ran.nextInt(75)+48; + if((num>=48 && num<=57) || (num>=65 && num<=90) || (num>=97 && num<=122)) { + sb.append((char)num); + }else { + continue; + } + } while (sb.length() < size); + if(lowerCheck) { + return sb.toString().toLowerCase(); + } + return sb.toString(); + } + +} diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml new file mode 100644 index 0000000..e402ce8 --- /dev/null +++ b/src/main/resources/application-local.yml @@ -0,0 +1,109 @@ +server: + tomcat: + connection-timeout: 15000 + threads: + max: 4096 + min-spare: 50 + accept-count: 150 + mbeanregistry: + enabled: true + + # port: 80 + port: 8080 + servlet: + encoding: + force: true + session: + timeout: 18000s + cookie: + same-site: lax + http-only: true + secure: false +spring: + devtools: + livereload: + enabled: true + restart: + enabled: true + exclude: static/**,templates/** + + datasource1: + driver-class-name: com.mysql.cj.jdbc.Driver + jdbc-url: jdbc:mysql://ultracore.cbop3tqawysk.ap-southeast-1.rds.amazonaws.com:6600/tripleDB?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Seoul&autoReconnect=true&useEncoding=true&characterEncoding=utf-8 + username: dev_triple + password: 4N!lCDki8GhCfEIHpRogIQebvrCJ0 + auto-commit: true + connection-test-query: SELECT 1 + transaction-isolation: TRANSACTION_READ_COMMITTED + maximum-pool-size: 20 + minimum-idle: 20 + leak-detection-threshold: 60000 + validation-timeout: 300000 + hikari: + pool-name: hikari-cp + max-lifetime: 1800000 + connection-timeout: 30000 + + datasource2: + driver-class-name: com.mysql.cj.jdbc.Driver + jdbc-url: jdbc:mysql://core-ro.cbop3tqawysk.ap-southeast-1.rds.amazonaws.com:6600/tripleDB?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Seoul&autoReconnect=true&useEncoding=true&characterEncoding=utf-8 + # jdbc-url: jdbc:mysql://ultracore.cbop3tqawysk.ap-southeast-1.rds.amazonaws.com:6600/tripleDB?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Seoul&autoReconnect=true&useEncoding=true&characterEncoding=utf-8 + username: dev_triple + password: 4N!lCDki8GhCfEIHpRogIQebvrCJ0 + auto-commit: true + connection-test-query: SELECT 1 + transaction-isolation: TRANSACTION_READ_COMMITTED + maximum-pool-size: 20 + minimum-idle: 20 + leak-detection-threshold: 60000 + validation-timeout: 300000 + hikari: + pool-name: hikari-cp + max-lifetime: 1800000 + connection-timeout: 30000 + + thymeleaf: + mode: HTML + prefix: classpath:/templates/ + check-template-location: true + suffix: .html + encoding: utf-8 + cache: false + aop: + auto: true + proxy-target-class: true + servlet: + multipart: + max-file-size: 20MB + max-request-size: 20MB + + +logging: + file: + path: /home/log/triple + level: + org.springframework: WARN + com.bb: INFO + com.zaxxer.hikari.HikariConfig: WARN + com.zaxxer.hikari: WARN + +mybatis: + mapper-locations: classpath:mapper/*/*.xml + type-aliases-package: + configuration: + map-underscore-to-camel-case: true + +jwt: + header: Authorization + secret: c2lsdmVybmluZS10ZWNoLXNwcmluZy1ib290LWp3dC10dXRvcmlhbC1zZWNyZXQtc2lsdmVybmluZS10ZWNoLXNwcmluZy1ib290LWp3dC10dXRvcmlhbC1zZWNyZXQK + validity-in-seconds: 1800 + +cron: LOCAL + +management: + endpoints: + web: + exposure: + include: "*" + + diff --git a/src/main/resources/application-real.yml b/src/main/resources/application-real.yml new file mode 100644 index 0000000..05d6f66 --- /dev/null +++ b/src/main/resources/application-real.yml @@ -0,0 +1,109 @@ +server: + tomcat: + connection-timeout: 15000 + threads: + max: 4096 + min-spare: 50 + accept-count: 300 + mbeanregistry: + enabled: true + + port: 80 + # port: 8080 + servlet: + encoding: + force: true + session: + timeout: 18000s + cookie: + same-site: lax + http-only: true + secure: false +spring: + devtools: + livereload: + enabled: true + restart: + enabled: true + exclude: static/**,templates/** + + datasource1: + driver-class-name: com.mysql.cj.jdbc.Driver + jdbc-url: jdbc:mysql://ultracore.cbop3tqawysk.ap-southeast-1.rds.amazonaws.com:6600/tripleDB?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Seoul&autoReconnect=true&useEncoding=true&characterEncoding=utf-8 + username: dev_triple + password: 4N!lCDki8GhCfEIHpRogIQebvrCJ0 + auto-commit: true + connection-test-query: SELECT 1 + transaction-isolation: TRANSACTION_READ_COMMITTED + maximum-pool-size: 100 + minimum-idle: 50 + leak-detection-threshold: 30000 + validation-timeout: 30000 + hikari: + pool-name: hikari-cp + max-lifetime: 1800000 + connection-timeout: 30000 + + datasource2: + driver-class-name: com.mysql.cj.jdbc.Driver + jdbc-url: jdbc:mysql://core-ro.cbop3tqawysk.ap-southeast-1.rds.amazonaws.com:6600/tripleDB?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Seoul&autoReconnect=true&useEncoding=true&characterEncoding=utf-8 + # jdbc-url: jdbc:mysql://ultracore.cbop3tqawysk.ap-southeast-1.rds.amazonaws.com:6600/tripleDB?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Seoul&autoReconnect=true&useEncoding=true&characterEncoding=utf-8 + username: dev_triple + password: 4N!lCDki8GhCfEIHpRogIQebvrCJ0 + auto-commit: true + connection-test-query: SELECT 1 + transaction-isolation: TRANSACTION_READ_COMMITTED + maximum-pool-size: 100 + minimum-idle: 50 + leak-detection-threshold: 30000 + validation-timeout: 30000 + hikari: + pool-name: hikari-cp + max-lifetime: 1800000 + connection-timeout: 30000 + + thymeleaf: + mode: HTML + prefix: classpath:/templates/ + check-template-location: true + suffix: .html + encoding: utf-8 + cache: false + aop: + auto: true + proxy-target-class: true + servlet: + multipart: + max-file-size: 20MB + max-request-size: 20MB + + +logging: + file: + path: /home/log/triple + level: + org.springframework: WARN + com.bb: INFO + com.zaxxer.hikari.HikariConfig: WARN + com.zaxxer.hikari: WARN + +mybatis: + mapper-locations: classpath:mapper/*/*.xml + type-aliases-package: + configuration: + map-underscore-to-camel-case: true + +jwt: + header: Authorization + secret: c2lsdmVybmluZS10ZWNoLXNwcmluZy1ib290LWp3dC10dXRvcmlhbC1zZWNyZXQtc2lsdmVybmluZS10ZWNoLXNwcmluZy1ib290LWp3dC10dXRvcmlhbC1zZWNyZXQK + validity-in-seconds: 1800 + +cron: LOCAL + +management: + endpoints: + web: + exposure: + include: "*" + + diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..13dc790 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,10 @@ +# spring.profiles.active: @env@ +spring.profiles.active: real + +server.tomcat.accesslog.pattern= %{yyyy-MM-dd HH:mm:ss}t\t%s\t%r\t%{User-Agent}i\t%{Referer}i\t%a\t%b +server.tomcat.accesslog.enabled= true +server.tomcat.basedir= /home/logs/ + + + + diff --git a/src/main/resources/authentication.properties b/src/main/resources/authentication.properties new file mode 100644 index 0000000..bd4dfd3 --- /dev/null +++ b/src/main/resources/authentication.properties @@ -0,0 +1,5 @@ +AUTH.HEADER_STRING=Authorization +AUTH.TOKEN_PREFIX=Bearer +AUTH.AUTHORITIES_NAME=roles +AUTH.TOKEN_VALIDITY=18000 +AUTH.SIGNING_KEY=bbsskey \ No newline at end of file diff --git a/src/main/resources/db1/CALLBACKLOG.xml b/src/main/resources/db1/CALLBACKLOG.xml new file mode 100644 index 0000000..a44e7c6 --- /dev/null +++ b/src/main/resources/db1/CALLBACKLOG.xml @@ -0,0 +1,52 @@ + + + + + + INSERT INTO site_callback_err_log ( + siteIdx, + memberIdx, + vendorIdx, + statusCode, + callBackType, + + tranId, + + callBackReqBody, + callBackResBody, + errorCode, + errorMsg, + regDate, + updDate + ) VALUES ( + #{siteIdx}, + #{memberIdx}, + #{vendorIdx}, + #{statusCode}, + #{callBackType}, + + #{tranId}, + + #{callBackReqBody}, + #{callBackResBody}, + #{errorCode}, + #{errorMsg}, + #{regDate}, + #{updDate} + ) + + + + INSERT INTO bet_radar_log ( + tranId, + betId, + jsonstr + ) + VALUES ( + #{tranId}, + #{betId}, + #{jsonstr} + ) + + + diff --git a/src/main/resources/db1/COIN.xml b/src/main/resources/db1/COIN.xml new file mode 100644 index 0000000..75b1106 --- /dev/null +++ b/src/main/resources/db1/COIN.xml @@ -0,0 +1,97 @@ + + + + + + + + INSERT INTO coin_info ( + id, + symbol, + name, + currency, + image, + currentPrice, + marketCap, + marketCapRank, + fullyDilutedValuation, + totalVolume, + high24h, + low24h, + priceChange24h, + priceChangePercentage24h, + marketCapChange24h, + marketCapChangePercentage24h, + circulatingSupply, + totalSupply, + maxSupply, + ath, + athChangePercentage, + athDate, + atl, + atlChangePercentage, + atlDate, + roi, + lastUpdated + ) VALUES ( + #{id}, + #{symbol}, + #{name}, + #{currency}, + #{image}, + #{currentPrice}, + #{marketCap}, + #{marketCapRank}, + #{fullyDilutedValuation}, + #{totalVolume}, + #{high24h}, + #{low24h}, + #{priceChange24h}, + #{priceChangePercentage24h}, + #{marketCapChange24h}, + #{marketCapChangePercentage24h}, + #{circulatingSupply}, + #{totalSupply}, + #{maxSupply}, + #{ath}, + #{athChangePercentage}, + #{athDate}, + #{atl}, + #{atlChangePercentage}, + #{atlDate}, + #{roi}, + #{lastUpdated} + ) + ON DUPLICATE KEY UPDATE + symbol = #{symbol}, + name = #{name}, + currency = #{currency}, + image = #{image}, + currentPrice = #{currentPrice}, + marketCap = #{marketCap}, + marketCapRank = #{marketCapRank}, + fullyDilutedValuation = #{fullyDilutedValuation}, + totalVolume = #{totalVolume}, + high24h = #{high24h}, + low24h = #{low24h}, + priceChange24h = #{priceChange24h}, + priceChangePercentage24h = #{priceChangePercentage24h}, + marketCapChange24h = #{marketCapChange24h}, + marketCapChangePercentage24h = #{marketCapChangePercentage24h}, + circulatingSupply = #{circulatingSupply}, + totalSupply = #{totalSupply}, + maxSupply = #{maxSupply}, + ath = #{ath}, + athChangePercentage = #{athChangePercentage}, + athDate = #{athDate}, + atl = #{atl}, + atlChangePercentage = #{atlChangePercentage}, + atlDate = #{atlDate}, + roi = #{roi}, + lastUpdated = #{lastUpdated}; + + + + + + \ No newline at end of file diff --git a/src/main/resources/db1/COMMON.xml b/src/main/resources/db1/COMMON.xml new file mode 100644 index 0000000..a9ed25b --- /dev/null +++ b/src/main/resources/db1/COMMON.xml @@ -0,0 +1,24 @@ + + + + + + INSERT INTO ban_game_info + (vendorIdx, vendorTitle, banGameType, banGameId, banGameName, banGameNameEng, skin) + VALUES + (#{vendorIdx}, #{vendorTitle}, #{banGameType}, #{banGameId}, #{banGameName}, #{banGameNameEng}, #{skin}) + ON DUPLICATE KEY UPDATE updDate = NOW(), + banGameName = #{banGameName}, + banGameNameEng = #{banGameNameEng} + + + + INSERT INTO nexus_game_table + (gameId, gameKey) + VALUES + (#{banGameId}, #{banGameKey}) + ON DUPLICATE KEY UPDATE updDate = NOW(), + gameKey = #{banGameKey} + + + \ No newline at end of file diff --git a/src/main/resources/db1/CREDIT.xml b/src/main/resources/db1/CREDIT.xml new file mode 100644 index 0000000..948cb87 --- /dev/null +++ b/src/main/resources/db1/CREDIT.xml @@ -0,0 +1,592 @@ + + + + + + INSERT INTO credit_info ( + siteIdx, + targetSiteIdx, + siteId, + targetSiteId, + creditType, + `inOut`, + tranId, + creditAmt, + creditRate, + gameCategory, + preCreditAmt, + creditStatus, + regDate, + updDate, + pointAmt + ) + VALUES ( + #{siteIdx}, + #{targetSiteIdx}, + #{siteId}, + #{targetSiteId}, + #{creditType}, + #{inOut}, + #{tranId}, + #{creditAmt}, + #{creditRate}, + + #{gameCategory}, + + + '0', + + #{preCreditAmt}, + #{creditStatus}, + NOW(), + NOW(), + #{pointAmt} + ) + + SELECT LAST_INSERT_ID(); + + + + + INSERT INTO credit_info ( + siteIdx, + targetSiteIdx, + siteId, + targetSiteId, + creditType, + `inOut`, + tranId, + creditAmt, + userAmt, + creditRate, + gameCategory, + preCreditAmt, + creditStatus, + regDate, + updDate, + preBalance + ) + VALUES ( + #{siteIdx}, + #{targetSiteIdx}, + #{siteId}, + #{targetSiteId}, + #{creditType}, + #{inOut}, + #{tranId}, + #{creditAmt}, + #{userAmt}, + #{creditRate}, + + #{gameCategory}, + + + '0', + + #{preCreditAmt}, + #{creditStatus}, + NOW(), + NOW(), + #{preBalance} + ) + + SELECT LAST_INSERT_ID(); + + + + + INSERT INTO credit_info_aiao ( + creditIdx, + siteIdx, + siteId, + targetSiteIdx, + targetSiteId, + creditType, + creditAmt, + preCreditAmt, + regDate + ) + VALUES ( + #{creditIdx}, + #{siteIdx}, + #{siteId}, + #{targetSiteIdx}, + #{targetSiteId}, + #{creditType}, + #{creditAmt}, + #{preCreditAmt}, + now() + ) + + + + update site_credit_info set + + + credit = credit + #{creditAmt} + + + credit = credit - #{creditAmt} + + where siteId = #{siteId} + + + + + + + + + + + + + + + + update credit_info set creditStatus = ${creditStatus} , updDate = now() where creditIdx = #{creditIdx} + + + + update insurance_info set status = ${status}, updDate = now() where idx = #{idx} + + + + + + + + + + + + + INSERT INTO `insurance_info` + (siteIdx, siteId, insureType, insureUpSiteIdx, insureUpSiteId, insureAmt, insurePointAmt, preCreditAmt, preCreditPoint, preInsureAmt, preInsurePoint, `status`, regDate, updDate, regId, updId) + values + (#{siteIdx}, #{siteId}, #{insureType}, #{insureUpSiteIdx}, #{insureUpSiteId}, #{insureAmt}, #{insurePointAmt}, #{preCreditAmt}, #{preCreditPoint}, #{preInsureAmt}, #{preInsurePoint}, #{status} ,now(), now(), #{regId}, #{regId}) + + + + + + + + + + update bet_info set apiStatus ='1' , updDate = now() + where tranId = #{tranId} and refId = #{refId} + + + + update bet_info set creditYn ='Y' , updDate = now() + where tranType='debit' and refId = #{refId} + + + + + INSERT INTO credit_point_temp + (siteIdx, siteId, memberIdx, memberId, vendor, vendorIdx, tranId, betId, amount, betDate) + VALUES + (#{siteIdx}, #{siteId}, #{memberIdx}, #{memberId}, #{vendor}, #{vendorIdx}, #{tranId}, #{betId}, #{amount}, NOW(3)) + + + + INSERT INTO credit_point_info + (siteIdx, siteId, targetSiteIdx, targetSiteId, vendor, vendorIdx, tranId, betId, prePointAmt, pointAmt) + VALUES + (#{siteIdx}, #{siteId}, #{targetSiteIdx}, #{targetSiteId}, #{vendor}, #{vendorIdx}, #{tranId}, #{betId}, #{prePointAmt}, #{pointAmt}) + + + + + + UPDATE site_credit_info + SET casinoCreditA = casinoCreditA + #{casinoCreditA}, + casinoCreditB = casinoCreditB + #{casinoCreditB}, + slotCreditA = slotCreditA + #{slotCreditA}, + slotCreditB = slotCreditB + #{slotCreditB} + WHERE siteId = #{targetSiteId} + + + \ No newline at end of file diff --git a/src/main/resources/db1/SETTING.xml b/src/main/resources/db1/SETTING.xml new file mode 100644 index 0000000..26d080e --- /dev/null +++ b/src/main/resources/db1/SETTING.xml @@ -0,0 +1,25 @@ + + + + + + UPDATE site_vendors_map + SET siteMaxBet = #{siteMaxBet}, + siteMaxWin = #{siteMaxWin}, + useYn = #{useYn}, + nexusSkinType = #{nexusSkinType}, + extrSkinType = #{extrSkinType} + WHERE siteIdx = #{siteIdx} + AND vendorIdx = #{vendorIdx} + + + + INSERT INTO ban_game_site_info + (siteIdx, vendorIdx, vendorTitle, banGameId) + VALUES + (#{siteIdx}, #{vendorIdx}, #{vendorTitle}, #{blockTableIds}) + ON DUPLICATE KEY UPDATE updDate = NOW(), + banGameId = #{blockTableIds} + + + \ No newline at end of file diff --git a/src/main/resources/db1/SITE.xml b/src/main/resources/db1/SITE.xml new file mode 100644 index 0000000..111942c --- /dev/null +++ b/src/main/resources/db1/SITE.xml @@ -0,0 +1,2198 @@ + + + + + + + + + + + + + + + + update site_ip_cms set cmsAllowIp = #{ips} where siteId = #{siteId} + + + + + + + + + + + + + + insert into site_member (siteIdx, memberId, memberNick, regDate) values (#{siteIdx}, #{authParam.userId}, IFNULL(#{authParam.nickName}, CONCAT(LPAD(HEX(#{siteIdx}), 3, '0'), #{authParam.userId})) , now()) + + + + + + + + + + INSERT INTO `bet_info` + (`tranId`,`refId`,`siteIdx`,`memberIdx`,`vendorIdx`,vendorCode, `vendorTranKey` + ,`gameType`,`gameId`,`gameIdx`,`tranType`,`depositAmt`,`creditAmt` + ,`overCreditAmt` + ,`isCancel`,`isTie`,`apiStatus`,`regDate`,`updDate`, vendorApiId ) + values + (#{tranId},#{refId},#{siteIdx},#{memberIdx},#{vendorIdx},#{vendorCode}, #{vendorTranKey} + ,#{gameType},#{gameId},#{gameIdx},#{tranType},#{depositAmt},#{creditAmt} + + ,#{overCreditAmt} + + + ,'0' + + ,#{isCancel},#{isTie},#{apiStatus},now(),now() , #{vendorApiId}) + ON DUPLICATE KEY UPDATE tranId = tranId, + depositAmt = #{depositAmt}, + creditAmt = #{creditAmt}, + isCancel = #{isCancel}, + isTie = #{isTie} + + + + INSERT INTO `bet_info` + (`tranId`,`refId`,`siteIdx`,`memberIdx`,`vendorIdx`,vendorCode, `vendorTranKey`,`gameIdx`,`tranType`,`depositAmt`,`creditAmt`,`overCreditAmt`,`isCancel`,`isTie`,`apiStatus`,`regDate`,`updDate`, vendorApiId ) + values + (#{tranId},#{refId},#{siteIdx},#{memberIdx},#{vendorIdx},#{vendorCode}, #{vendorTranKey},#{gameIdx},#{tranType},#{depositAmt},#{creditAmt},#{overCreditAmt},#{isCancel},#{isTie},#{apiStatus},now(),now() , #{vendorApiId}) + ON DUPLICATE KEY UPDATE tranId = tranId, + depositAmt = #{depositAmt}, + creditAmt = #{creditAmt}, + isCancel = #{isCancel}, + isTie = #{isTie} + + + + + + UPDATE bet_info + SET balance = #{balance}, + apiStatus = '1', + updDate = NOW() + WHERE tranId = #{tranId} and refId = #{refId} + + + + update bet_info set isCancel = 'Y' + where refId = #{refId} AND tranType = 'debit' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + insert into `site_info` + (siteId, siteName, sitePass, upperSiteIdx, upperSiteId, siteKey, siteCreditRate, siteIp, memo, regDate, siteLevel, siteGubun, siteType, isTransfer) + values + (#{siteId}, #{siteName}, UPPER(SHA1(UNHEX(SHA1(#{sitePass})))) ,#{upperSiteIdx}, #{upperSiteId}, #{siteKey}, #{siteCreditRate},'3.3.3.3', #{memo}, now(), #{siteLevel}, #{siteGubun}, #{siteType}, #{isTransfer}) + + + SELECT LAST_INSERT_ID(); + + + + + insert into site_credit_info + (siteId, credit) + values + (#{siteId} , 0) + + + insert into site_ip_cms values (#{siteId} , '') + + + + insert into site_point_info values (#{siteId} , 0) + + + INSERT INTO `site_flow` (`topOrder`, `upperSiteId`, `siteId`) + SELECT * FROM ( + SELECT 0 topOrder, siteId AS upid, #{siteId} AS siteId FROM site_info WHERE siteId = #{siteId} + UNION + SELECT 1 topOrder, upperSiteId , #{siteId} AS siteId FROM site_info WHERE siteId = #{siteId} + UNION + SELECT 2 topOrder, upperSiteId , #{siteId} AS siteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = #{siteId}) + UNION + SELECT 3 topOrder, upperSiteId , #{siteId} AS siteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = #{siteId})) + UNION + SELECT 4 topOrder, upperSiteId , #{siteId} AS siteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = #{siteId}))) + UNION + SELECT 5 topOrder, upperSiteId , #{siteId} AS siteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = #{siteId})))) + UNION + SELECT 6 topOrder, upperSiteId , #{siteId} AS siteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = #{siteId}))))) + UNION + SELECT 7 topOrder, upperSiteId , #{siteId} AS siteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = #{siteId})))))) + UNION + SELECT 8 topOrder, upperSiteId , #{siteId} AS siteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = #{siteId}))))))) + UNION + SELECT 9 topOrder, upperSiteId , #{siteId} AS siteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = #{siteId})))))))) + UNION + SELECT 10 topOrder, upperSiteId , #{siteId} AS siteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId = (SELECT upperSiteId FROM site_info WHERE siteId =(SELECT upperSiteId FROM site_info WHERE siteId = #{siteId}))))))))) + )f WHERE f.upid IS NOT NULL + + + + + insert into site_vendors_map (siteIdx, vendorIdx, vendorCode, vendorApiType, companyIdx, siteMaxBet, siteMinBet, useYn, unionGameKey) + SELECT #{siteIdx}, vendorIdx, vendorCode, vendorApiType, companyIdx, siteMaxBet, siteMinBet, useYn, unionGameKey FROM site_vendors_map WHERE siteIdx = (SELECT siteIdx FROM site_info WHERE siteId =#{upperSiteId}) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + insert into slotcity_info (timeStamp, datas, regDate, updDate) values (#{command}, #{datas}, now(), now()) + ON DUPLICATE KEY UPDATE updDate = now() + + + + + + + + + + + + + + insert tran_error_log (betId, error_type) values (#{betId} , #{errorType}) + + + + + + update site_member set lastSid = #{lastSid} where memberId = #{memberId} and siteIdx = #{siteIdx} + + + + update site_member set bombAccId = #{bombAccId}, dowinId = #{bombAccId} where memberId = #{memberId} and siteIdx = #{siteIdx} + + + + + + + INSERT INTO bet_detail (refId, vendorCode, detail, detail4, regDate) + VALUES (#{refId},#{vendorCode}, #{detail},#{detail4}, now()) + ON DUPLICATE KEY UPDATE detail=#{detail}, vendorCode=#{vendorCode} ,detail4=#{detail4}, regDate = now() + + + + ${state} + + + + + + + + + + + insert site_insurance_info values (#{siteId}, 0) ON DUPLICATE KEY UPDATE siteId =#{siteId} + + + insert site_insurance_point_info values (#{siteId}, 0) ON DUPLICATE KEY UPDATE siteId =#{siteId} + + + + + + + insert into site_rate_info(siteIdx, vendorIdx, rate, insureRate, insurePointRate, insureIdle, insureYn, insureUpSiteIdx) + values (#{siteIdx}, #{vendorIdx}, #{rate}, #{insureRate}, #{insurePointRate}, #{insureIdle}, #{insureYn}, #{insureUpSiteIdx}) + + ON DUPLICATE KEY UPDATE + + insureRate=#{insureRate}, + insureYn=#{insureYn} + + + + + + insert into site_rate_info(siteIdx, vendorIdx, rate, insureRate, insurePointRate, insureIdle, insureYn) + values (#{siteIdx}, #{vendorIdx}, #{rate}, #{insureRate}, #{insurePointRate}, #{insureIdle}, #{insureYn}) + + ON DUPLICATE KEY UPDATE + + rate=#{rate} + + + + + + insert into site_rate_info(siteIdx, vendorIdx, rate, insureRate, insurePointRate, insureIdle, insureYn) + values (#{siteIdx}, #{vendorIdx}, #{rate}, #{insureRate}, #{insurePointRate}, #{insureIdle}, #{insureYn}) + + ON DUPLICATE KEY UPDATE + + insurePointRate=#{insurePointRate} + + + + + + + + + + + + + + + + + + + + + + + + update vendors_info set detailLastTime2 = REPLACE(REPLACE(#{endDate}, 'T', ' '), 'Z', '') where vendorIdx =#{vendorIdx} and vendorCode =#{vendorCode} + + + + + + update site_info set sitePass = UPPER(SHA1(UNHEX(SHA1(#{newPass})))) where siteId = #{siteId} and sitePass =UPPER(SHA1(UNHEX(SHA1(#{sitePass})))) + + + + + + update site_info set siteId = siteId + + ,siteKey = #{siteKey} + + + + ,siteIp = #{siteIp} + + + ,siteCbUrl = #{siteCbUrl} + + + + ,domain = #{domain} + + + + ,memo = #{memo} + + + + ,siteUseYn = #{siteUseYn} + + + + ,sitePass = UPPER(SHA1(UNHEX(SHA1(#{newPass})))) + + + + ,siteName = #{siteName} + + + + ,siteCreditRate = #{siteCreditRate} + + + + ,siteMaxCredit = #{siteMaxCredit} + + + + + + ,siteBankInfo = #{siteBankInfo} + + + where siteId = #{siteId} + + + + + + + + + INSERT INTO site_rate_info( siteIdx, + vendorIdx , + rate , + insureRate , + insurePointRate , + insureIdle , + insureYn , + insureUpSiteIdx + ) + SELECT + + #{siteIdx}, + vendorIdx , + (SELECT siteCreditRate FROM site_info WHERE siteIdx = #{siteIdx}) AS rate , + 0 AS insureRate, + 0 AS insurePointRate , + 0 AS insureIdle , + 'N' AS insureYn , + #{upperSiteIdx} AS insureUpSiteIdX + + FROM `site_rate_info` + WHERE siteIdx = #{upperSiteIdx} + + + + + INSERT INTO site_vendors_credit_rate_info + (siteIdx, vendorIdx, vendorCode, rate, `view`, selected, updDate) + SELECT + #{siteIdx}, + vi.vendorIdx , + vi.vendorCode , + (SELECT siteCreditRate FROM site_info WHERE siteIdx = #{siteIdx}) AS rate, + 'Y', + '', + now() + FROM `vendors_info` vi + WHERE 1=1 + + + + + + + + + + + + + + + + + + + + update site_vendors_map set vendorCode = #{vendorCode} + where vendorIdx = #{vendorIdx} and siteIdx = #{siteIdx} + + + + + + + update site_member set pragmaticId =#{pragmaticId} where memberIdx =#{memberIdx} and siteIdx =#{siteIdx} + + + + + + + + + + + + + + + + + + + + + + + + UPDATE bet_info + SET creditAmt = #{creditAmt}, + vendorTranKey = #{vendorTranKey}, + isCancel = #{isCancel}, + apiStatus = #{apiStatus} + WHERE tranId = #{tranId} AND refId = #{refId} + + + + + + + + + + + + INSERT INTO site_callback_log + (siteIdx, memberIdx, vendorIdx, tranId, refId, callBackType, callBackReqBody, callBackResBody) + VALUES + (#{siteIdx}, #{memberIdx}, #{vendorIdx}, #{tranId}, #{refId}, #{callBackType}, #{callBackReqBody}, #{callBackResBody}) + + + + + + + + + + + + INSERT INTO insurance_info + ( + + `siteIdx`, + `siteId`, + insureType, + `insureUpSiteIdx`, + `insureUpSiteId`, + `memberIdx`, + `memberId`, + `vendorIdx`, + `refId`, + `betAmt`, + `winAmt`, + `winLoseAmt`, + `insureBetAmt`, + `rate`, + `insureRate`, + `insurePointRate`, + `upSiteinsurePointRate`, + `siteCreditRate`, + `insureAmt`, + `insureUpperAmt`, + `insurePointAmt`, + `upSiteInsurePointAmt`, + `upCredit`, + `credit`, + `pointAmt`, + preCreditAmt, + preCreditPoint, + preInsureAmt, + preInsurePoint, + `status`, + `isCancel`, + `regDate`, + `updDate`, + `regId`, + `updId` + ) + + SELECT + `siteIdx`, + `siteId`, + 'BET', + `insureUpSiteIdx`, + `insureUpSiteId`, + `memberIdx`, + `memberId`, + `vendorIdx`, + `refId`, + `betAmt`, + `winAmt`, + `winLoseAmt`, + `insureBetAmt`, + `rate`, + `insureRate`, + `insurePointRate`, + `upSiteinsurePointRate`, + `siteCreditRate`, + TRUNCATE(ins.insureBetAmt*ins.insureRate*0.01, 0) AS insureAmt, + TRUNCATE(ins.insureBetAmt*(100-ins.insureRate)*0.01, 0) AS insureUpperAmt, + TRUNCATE(ABS(ins.insureBetAmt*ins.insureRate*0.01*ins.insurePointRate*0.01), 0) AS insurePointAmt, + TRUNCATE(ABS(ins.insureBetAmt*(100-ins.insureRate)*0.01*ins.upSiteinsurePointRate*0.01), 0) AS upSiteInsurePointAmt, + TRUNCATE(ins.insureBetAmt*ins.insureRate*0.01 , 0) AS upCredit, + TRUNCATE(ins.winLoseAmt - (ins.insureBetAmt*ins.insureRate*0.01), 0) AS credit, + TRUNCATE(IF( winLoseAmt < 0, ABS(ins.winLoseAmt - (ins.insureBetAmt*ins.insureRate*0.01))*( ins.rate - ins.siteCreditRate)*0.01 , 0 ) , 0) AS pointAmt, + 0,0,0,0, + -- (select ifnull(credit, 0) from `site_credit_info` c where c.siteId = siteId limit 1), + -- (SELECT IFNULL(`point`, 0) FROM `site_point_info` c WHERE c.siteId = siteId LIMIT 1), + -- (SELECT IFNULL(insurance, 0) FROM `site_insurance_info` c WHERE c.siteId = siteId LIMIT 1), + -- (SELECT IFNULL(insurance_point, 0) FROM `site_insurance_point_info` c WHERE c.siteId = siteId LIMIT 1), + '1', + 'N', + NOW(), + NOW(), + siteId, + siteId + FROM ( + SELECT + + bi.siteIdx, + s.siteId, + sri.insureUpSiteIdx, + s2.siteId AS insureUpSiteId, + bi.memberIdx, + m.memberId, + bi.vendorIdx, + bi.refId, + IF(COUNT(IF(tranType='credit', 1, NULL)) > 1 , 0, SUM(bi.depositAmt)) AS betAmt, + SUM(bi.creditAmt) AS winAmt, + (SUM(bi.creditAmt) - IF(COUNT(IF(tranType='credit', 1, NULL)) > 1 , 0, SUM(bi.depositAmt))) AS winLoseAmt, + + IF(( sri.insureYn = 'Y' AND sri2.insureYn = 'Y') , SUM(bi.creditAmt) - SUM(bi.depositAmt) , 0) + AS insureBetAmt, + + IFNULL(sri.rate, vi.defaultCreditRate) AS rate, + IFNULL(sri.insureRate, 0) AS insureRate, + IFNULL(sri.insurePointRate, 0) AS insurePointRate, + IFNULL(sri2.insurePointRate, 0) AS upSiteinsurePointRate, + + + s.siteCreditRate + + FROM `bet_info` bi + LEFT JOIN `site_rate_info` sri ON bi.siteIdx = sri.siteIdx AND bi.vendorIdx = sri.vendorIdx + LEFT JOIN `site_rate_info` sri2 ON sri.insureUpSiteIdx = sri2.siteIdx AND sri.vendorIdx = sri2.vendorIdx + LEFT JOIN `site_vendors_map` vm ON bi.vendorIdx = vm.vendorIdx AND bi.siteIdx = vm.siteIdx + LEFT JOIN `vendors_info` vi ON vm.vendorIdx = vi.vendorIdx AND vm.vendorCode = vi.vendorCode + LEFT JOIN `site_member` m ON bi.siteIdx = m.siteIdx AND bi.memberIdx = m.memberIdx + LEFT JOIN `site_info` s ON bi.siteIdx = s.siteIdx LEFT JOIN `site_info` s2 ON sri.insureUpSiteIdx = s2.siteIdx + + WHERE bi.refId IN ( + + SELECT refId FROM ( + SELECT bi.refId ,bi.regDate FROM `bet_info` bi LEFT JOIN `credit_info` ci ON bi.refId = ci.tranId + WHERE bi.regDate >='2023-05-01 00:00:00' + AND ci.tranId IS NULL + -- AND bi.siteidx = 61 + + GROUP BY bi.refId HAVING COUNT(IF(bi.tranType='credit', 1, NULL)) =0 + ORDER BY bi.regDate DESC + )onlyD WHERE DATE_FORMAT(regDate, '%Y-%m-%d %H:%i:%s') <= DATE_FORMAT(DATE_ADD(NOW(), INTERVAL -3 MINUTE), '%Y-%m-%d %H:%i:%s') + ) + GROUP BY bi.refId + )ins + + + + update site_member set bombDecYn = #{decYn} where bombAccId =#{bombAccId} + + + + + + + + + + + + INSERT INTO `bet_info` + (`tranId`,`refId`,`siteIdx`,`memberIdx`,`vendorIdx`,vendorCode, `vendorTranKey`,`gameIdx`,`tranType`,`depositAmt`,`creditAmt`,`isCancel`,`isTie`,`apiStatus`,`regDate`,`updDate` ) + values + (#{tranId},#{refId},#{siteIdx},#{memberIdx},#{vendorIdx},#{vendorCode}, #{vendorTranKey},#{gameIdx},'credit',0,0,#{isCancel},#{isTie},#{apiStatus},now(),now() ) + ON DUPLICATE KEY UPDATE tranid =tranid, updDate = now(); + + + + + + + + + + + UPDATE site_member SET betCancelCnt = (betCancelCnt+1) WHERE memberIdx =#{memberIdx} + + + + INSERT INTO vendor_change_balance_log + (siteIdx, memberIdx, vendor, vendorApiId, reqType, amount, reqAt, reqStatus, reqMsg, regDate) + VALUES + (#{siteIdx}, #{memberIdx}, #{vendor}, #{vendorApiId}, #{reqType}, #{amount}, #{reqAt}, #{reqStatus}, #{reqMsg}, NOW()) + + + + + insert into bombdemo (bombAccId, creditAmt) values (#{bombAccId}, 1000000) + + + + update bombdemo set creditAmt = #{creditAmt} WHERE bombAccId = #{bombAccId} + + + + update bombdemo set creditAmt = creditAmt + (#{creditAmt}) WHERE bombAccId = #{bombAccId} + + + + + + INSERT INTO `splus_tran_Data` + ( + `tranType`, + refId, + `cust_id`, + + `req_id`, + + + `amount`, + + + `reserve_id`, + + + `purchase_id`, + + `tranId`, + `trx_id`, + + `data`, + + `cbData`, + updDate, + regDate + ) + VALUES + ( + #{tranType}, + #{refId}, + #{cust_id}, + + #{req_id}, + + + #{amount}, + + + #{reserve_id}, + + + #{purchase_id}, + + #{tranId}, + #{trx_id}, + + #{data}, + + #{cbData}, + now(), + now() + ) + + + + update splus_tran_Data + set tranId = #{tranId}, + cbData = #{resData}, + cbResultCode =#{cbResultCode}, + updDate = now() + where trx_id = #{trx_id} + + + + + + update splus_tran_Data set purchase_id = #{purchase_id}, updDate = now() + where reserve_id = #{reserve_id} and tranType='reserve' + AND cbResultCode = '0' + + + + + + + + + insert into splus_token values(#{token}, now()) + on duplicate key update + updDate = now() + + + + + + + + + + + + + + + UPDATE site_vendors_map + SET vendorApiId = #{apiSiteId}, + vendorApiKey = #{apiKey} + WHERE siteIdx = CAST(#{siteIdx} AS UNSIGNED) + AND vendorIdx = 94 + + + + UPDATE site_vendors_map a LEFT JOIN site_vendors_map b + ON a.vendorIdx=b.vendorIdx AND b.siteIdx = #{upperSiteIdx} + SET a.vendorCode=b.vendorCode, + a.useYn = b.useYn + WHERE 1=1 + AND a.siteIdx = #{siteIdx} + + + + UPDATE site_vendors_credit_rate_info a LEFT JOIN site_vendors_credit_rate_info b + ON a.vendorIdx=b.vendorIdx AND a.vendorCode=b.vendorCode AND b.siteIdx = #{upperSiteIdx} + SET a.`view` = b.`view` + WHERE 1=1 + AND a.siteIdx = #{siteIdx} + + + + DELETE FROM site_vendors_account + WHERE siteIdx = #{siteIdx} + + + + UPDATE site_member + SET lastInVendorIdx = #{lastInVendorIdx} + WHERE siteIdx = #{siteIdx} + AND memberIdx = #{memberIdx} + + + + + + UPDATE site_vendors_map + SET vendorCode = #{newVendorCode} + WHERE siteIdx = #{siteIdx} + AND vendorIdx = #{vendorIdx} + + + + + UPDATE `site_vendors_map` SET nexusSkinType = #{skinType} + WHERE siteIdx =#{siteIdx} and vendorIdx = #{vendorIdx} and vendorCode =#{vendorCode} + + + + + INSERT INTO parse_game_use_site(siteIdx, siteId, useYn) values + (#{siteIdx}, #{siteId}, #{useYn}) + ON DUPLICATE KEY UPDATE useYn =#{useYn} + + + UPDATE parse_game_use_site + SET useYn = #{useYn} + WHERE 1=1 + + + + + + INSERT INTO parse_game_use_member + (memberIdx, parseUseYn, updDate) + values( + #{memberIdx}, #{useYn}, now() + ) + ON DUPLICATE KEY UPDATE parseUseYn =#{useYn}, updDate = NOW() + + + + INSERT INTO otp_info + (siteIdx, otpType, siteId, account, issuer, secretKey, url) + VALUES + (#{siteIdx}, #{otpType}, #{siteId}, #{account}, #{issuer}, #{secretKey}, #{url}) + ON DUPLICATE KEY UPDATE secretKey = #{secretKey}, url = #{url}, updDate = NOW() + + + + INSERT INTO bet_evo_detail (refId, orgDetail, parDetail) + VALUES (#{refId}, #{orgDetail}, #{parDetail}) + + + + + + + + INSERT INTO site_vendors_credit_rate_info + (siteIdx, vendorIdx, vendorCode, rate) + VALUES + (#{siteIdx}, #{vendorIdx}, #{vendorCode}, #{rate}) + ON DUPLICATE KEY UPDATE + rate = #{rate} + + + + + + UPDATE site_rate_info + SET rate = #{rate} + WHERE siteIdx = #{siteIdx} AND vendorIdx = #{vendorIdx} + + + + + + + + + + INSERT INTO site_member_acc + (siteIdx, memberIdx, requestTime) + VALUES + (#{siteIdx}, #{memberIdx}, #{requestTime}) + ON DUPLICATE KEY UPDATE + requestTime = #{requestTime}, + updDate = NOW(3) + + + + + + INSERT INTO bet_thea_detail_log + (transactionId, siteIdx) + VALUES + (#{transactionId}, #{siteIdx}) + + + + + + UPDATE site_member_balance + SET vendorUsername = #{vendorUsername} + WHERE 1=1 + AND siteIdx = #{siteIdx} + + AND memberIdx = #{memberIdx} + + + AND memberId = #{memberId} + + + + + + + + + + + + + + + + + UPDATE site_credit_info + SET testCnt = #{testCnt} + WHERE siteId = #{siteId} + + + + UPDATE site_member + SET parseEvoYn = #{parseEvoYn} + WHERE memberIdx = #{memberIdx} + + + + UPDATE parse_game_use_site + SET parsEvoAmount = #{parsEvoAmount} + WHERE siteIdx = #{siteIdx} + + + + + + + + + + + + INSERT INTO parse_game_use_site(siteIdx, siteId, useYn) values + (#{siteIdx}, #{siteId}, #{parseUseYn}) + ON DUPLICATE KEY UPDATE useYn =#{parseUseYn} + + + + UPDATE site_info + SET sitePass = UPPER(SHA1(UNHEX(SHA1(#{newPassword})))) + WHERE siteId = #{siteId} + + + + UPDATE site_vendors_map SET unionGameKey = #{lobbyCode} , + siteMinBet = (select minBet from union_lobby_info where vendorCode = #{vendorCode} and lobbyCode = #{lobbyCode} ), + siteMaxBet = (select maxBet from union_lobby_info where vendorCode = #{vendorCode} and lobbyCode = #{lobbyCode} ) + + where siteIdx = #{siteIdx} and vendorCode = #{vendorCode} + + + + + + + + + + + + + UPDATE site_member + SET userMaxBet = #{userMaxBet} + WHERE siteIdx = #{siteIdx} + AND memberIdx = #{memberIdx} + + + + INSERT INTO tran_log + (siteIdx, vendorIdx, gameIdx, body, regDt) + VALUES + (#{siteIdx}, #{vendorIdx}, #{gameIdx}, #{body}, NOW()) + + + + + + + diff --git a/src/main/resources/db1/SPLUS.xml b/src/main/resources/db1/SPLUS.xml new file mode 100644 index 0000000..f9f0d20 --- /dev/null +++ b/src/main/resources/db1/SPLUS.xml @@ -0,0 +1,136 @@ + + + + + + + INSERT INTO `bet_splus` ( + + `refId`, + `siteIdx`, + `memberIdx`, + `memberId`, + `betType`, + `branchName`, + `leagueName`, + `leagueNameKor`, + `homeTeam`, + `homeTeamKor`, + `awayTeam`, + `awayTeamKor`, + `lineTypeId`, + `yourBet`, + `OddsDec`, + `points`, + `score`, + `realAmount`, + `betOdds`, + `gain`, + `status`, + `betStatus`, + `creationDate`, + `eventDate`, + `newEventID`, + `newMasterEventID` + ) + VALUES + ( + + #{refId} , + #{siteIdx}, + #{memberIdx}, + #{memberId}, + #{betType}, + #{branchName} , + #{leagueName}, + #{leagueNameKor}, + #{homeTeam}, + #{homeTeamKor}, + #{awayTeam}, + #{awayTeamKor}, + #{lineTypeId}, + #{yourBet}, + #{oddsDec}, + #{points}, + #{score}, + #{realAmount}, + #{betOdds}, + #{gain}, + #{status}, + #{betStatus}, + #{creationDate}, + #{eventDate}, + #{newEventId}, + #{newMasterEventId} + + ) + + + + + + update bet_splus set + score = #{score}, + `status` = #{status}, + resultOdds = #{resultOdds} + where + newMasterEventId = #{newMasterEventId} + and newEventId = #{newEventId} + and lineTypeId = #{lineTypeId} + + + + + update bet_splus set + betStatus = #{betStatus}, + gain = #{gain} + where + refId = #{refId} + + + + + + + update bet_splus set + betStatus = '-2' + where + refId = #{refId} + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/db1/STAT.xml b/src/main/resources/db1/STAT.xml new file mode 100644 index 0000000..4a42dfb --- /dev/null +++ b/src/main/resources/db1/STAT.xml @@ -0,0 +1,179 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/db1/TPLUS.xml b/src/main/resources/db1/TPLUS.xml new file mode 100644 index 0000000..d1cf517 --- /dev/null +++ b/src/main/resources/db1/TPLUS.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/db1/TRANS.xml b/src/main/resources/db1/TRANS.xml new file mode 100644 index 0000000..ebada9c --- /dev/null +++ b/src/main/resources/db1/TRANS.xml @@ -0,0 +1,10 @@ + + + + + + DELETE FROM bet_nexus_detail_null + WHERE refId = #{refId} + + + \ No newline at end of file diff --git a/src/main/resources/db2/CALLBACKLOG.xml b/src/main/resources/db2/CALLBACKLOG.xml new file mode 100644 index 0000000..cc48785 --- /dev/null +++ b/src/main/resources/db2/CALLBACKLOG.xml @@ -0,0 +1,15 @@ + + + + + + + diff --git a/src/main/resources/db2/COIN.xml b/src/main/resources/db2/COIN.xml new file mode 100644 index 0000000..103714c --- /dev/null +++ b/src/main/resources/db2/COIN.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/db2/COMMON.xml b/src/main/resources/db2/COMMON.xml new file mode 100644 index 0000000..f4b3b62 --- /dev/null +++ b/src/main/resources/db2/COMMON.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/db2/CREDIT.xml b/src/main/resources/db2/CREDIT.xml new file mode 100644 index 0000000..1198e12 --- /dev/null +++ b/src/main/resources/db2/CREDIT.xml @@ -0,0 +1,1654 @@ + + + + + + + + + + + + + + + update credit_info set creditStatus = ${creditStatus} , updDate = now() where creditIdx = #{creditIdx} + + + + update insurance_info set status = ${status}, updDate = now() where idx = #{idx} + + + + + + + + + + + + + + + + update bet_info set apiStatus ='1' , updDate = now() + where tranId = #{tranId} and refId = #{refId} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/db2/SETTING.xml b/src/main/resources/db2/SETTING.xml new file mode 100644 index 0000000..1bb322d --- /dev/null +++ b/src/main/resources/db2/SETTING.xml @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/db2/SITE.xml b/src/main/resources/db2/SITE.xml new file mode 100644 index 0000000..853e9d2 --- /dev/null +++ b/src/main/resources/db2/SITE.xml @@ -0,0 +1,869 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/db2/STAT.xml b/src/main/resources/db2/STAT.xml new file mode 100644 index 0000000..2838538 --- /dev/null +++ b/src/main/resources/db2/STAT.xml @@ -0,0 +1,1225 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/db2/TRANS.xml b/src/main/resources/db2/TRANS.xml new file mode 100644 index 0000000..ac12329 --- /dev/null +++ b/src/main/resources/db2/TRANS.xml @@ -0,0 +1,908 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..00eff14 --- /dev/null +++ b/src/main/resources/logback-spring.xml @@ -0,0 +1,49 @@ + + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + ${filePath}/app.log + + ${filePath}/app.%d{yyyy-MM-dd}.%i.gz + + 1GB + + 10 + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + ${filePath}/error.log + + ERROR + ACCEPT + DENY + + + ${filePath}/error-%d{yyyy-MM-dd}.%i.gz + + 100MB + + 30 + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/static/css/all.min.css b/src/main/resources/static/css/all.min.css new file mode 100644 index 0000000..fcbf488 --- /dev/null +++ b/src/main/resources/static/css/all.min.css @@ -0,0 +1,6 @@ +/*! + * Font Awesome Free 6.0.0 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + * Copyright 2022 Fonticons, Inc. + */ +.fa{font-family:var(--fa-style-family,"Font Awesome 6 Free");font-weight:var(--fa-style,900)}.fa,.fa-brands,.fa-duotone,.fa-light,.fa-regular,.fa-solid,.fa-thin,.fab,.fad,.fal,.far,.fas,.fat{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:var(--fa-display,inline-block);font-style:normal;font-variant:normal;line-height:1;text-rendering:auto}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-2xs{font-size:.625em;line-height:.1em;vertical-align:.225em}.fa-xs{font-size:.75em;line-height:.08333em;vertical-align:.125em}.fa-sm{font-size:.875em;line-height:.07143em;vertical-align:.05357em}.fa-lg{font-size:1.25em;line-height:.05em;vertical-align:-.075em}.fa-xl{font-size:1.5em;line-height:.04167em;vertical-align:-.125em}.fa-2xl{font-size:2em;line-height:.03125em;vertical-align:-.1875em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:var(--fa-li-margin,2.5em);padding-left:0}.fa-ul>li{position:relative}.fa-li{left:calc(var(--fa-li-width, 2em)*-1);position:absolute;text-align:center;width:var(--fa-li-width,2em);line-height:inherit}.fa-border{border-radius:var(--fa-border-radius,.1em);border:var(--fa-border-width,.08em) var(--fa-border-style,solid) var(--fa-border-color,#eee);padding:var(--fa-border-padding,.2em .25em .15em)}.fa-pull-left{float:left;margin-right:var(--fa-pull-margin,.3em)}.fa-pull-right{float:right;margin-left:var(--fa-pull-margin,.3em)}.fa-beat{-webkit-animation-name:fa-beat;animation-name:fa-beat;-webkit-animation-delay:var(--fa-animation-delay,0);animation-delay:var(--fa-animation-delay,0);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,ease-in-out);animation-timing-function:var(--fa-animation-timing,ease-in-out)}.fa-bounce{-webkit-animation-name:fa-bounce;animation-name:fa-bounce;-webkit-animation-delay:var(--fa-animation-delay,0);animation-delay:var(--fa-animation-delay,0);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,cubic-bezier(.28,.84,.42,1));animation-timing-function:var(--fa-animation-timing,cubic-bezier(.28,.84,.42,1))}.fa-fade{-webkit-animation-name:fa-fade;animation-name:fa-fade;-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1));animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1))}.fa-beat-fade,.fa-fade{-webkit-animation-delay:var(--fa-animation-delay,0);animation-delay:var(--fa-animation-delay,0);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s)}.fa-beat-fade{-webkit-animation-name:fa-beat-fade;animation-name:fa-beat-fade;-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1));animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1))}.fa-flip{-webkit-animation-name:fa-flip;animation-name:fa-flip;-webkit-animation-delay:var(--fa-animation-delay,0);animation-delay:var(--fa-animation-delay,0);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,ease-in-out);animation-timing-function:var(--fa-animation-timing,ease-in-out)}.fa-shake{-webkit-animation-name:fa-shake;animation-name:fa-shake;-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,linear);animation-timing-function:var(--fa-animation-timing,linear)}.fa-shake,.fa-spin{-webkit-animation-delay:var(--fa-animation-delay,0);animation-delay:var(--fa-animation-delay,0);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal)}.fa-spin{-webkit-animation-name:fa-spin;animation-name:fa-spin;-webkit-animation-duration:var(--fa-animation-duration,2s);animation-duration:var(--fa-animation-duration,2s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,linear);animation-timing-function:var(--fa-animation-timing,linear)}.fa-spin-reverse{--fa-animation-direction:reverse}.fa-pulse,.fa-spin-pulse{-webkit-animation-name:fa-spin;animation-name:fa-spin;-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,steps(8));animation-timing-function:var(--fa-animation-timing,steps(8))}@media (prefers-reduced-motion:reduce){.fa-beat,.fa-beat-fade,.fa-bounce,.fa-fade,.fa-flip,.fa-pulse,.fa-shake,.fa-spin,.fa-spin-pulse{-webkit-animation-delay:-1ms;animation-delay:-1ms;-webkit-animation-duration:1ms;animation-duration:1ms;-webkit-animation-iteration-count:1;animation-iteration-count:1;transition-delay:0s;transition-duration:0s}}@-webkit-keyframes fa-beat{0%,90%{-webkit-transform:scale(1);transform:scale(1)}45%{-webkit-transform:scale(var(--fa-beat-scale,1.25));transform:scale(var(--fa-beat-scale,1.25))}}@keyframes fa-beat{0%,90%{-webkit-transform:scale(1);transform:scale(1)}45%{-webkit-transform:scale(var(--fa-beat-scale,1.25));transform:scale(var(--fa-beat-scale,1.25))}}@-webkit-keyframes fa-bounce{0%{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}10%{-webkit-transform:scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0);transform:scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0)}30%{-webkit-transform:scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em));transform:scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em))}50%{-webkit-transform:scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0);transform:scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0)}57%{-webkit-transform:scale(1) translateY(var(--fa-bounce-rebound,-.125em));transform:scale(1) translateY(var(--fa-bounce-rebound,-.125em))}64%{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}to{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}}@keyframes fa-bounce{0%{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}10%{-webkit-transform:scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0);transform:scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0)}30%{-webkit-transform:scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em));transform:scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em))}50%{-webkit-transform:scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0);transform:scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0)}57%{-webkit-transform:scale(1) translateY(var(--fa-bounce-rebound,-.125em));transform:scale(1) translateY(var(--fa-bounce-rebound,-.125em))}64%{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}to{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}}@-webkit-keyframes fa-fade{50%{opacity:var(--fa-fade-opacity,.4)}}@keyframes fa-fade{50%{opacity:var(--fa-fade-opacity,.4)}}@-webkit-keyframes fa-beat-fade{0%,to{opacity:var(--fa-beat-fade-opacity,.4);-webkit-transform:scale(1);transform:scale(1)}50%{opacity:1;-webkit-transform:scale(var(--fa-beat-fade-scale,1.125));transform:scale(var(--fa-beat-fade-scale,1.125))}}@keyframes fa-beat-fade{0%,to{opacity:var(--fa-beat-fade-opacity,.4);-webkit-transform:scale(1);transform:scale(1)}50%{opacity:1;-webkit-transform:scale(var(--fa-beat-fade-scale,1.125));transform:scale(var(--fa-beat-fade-scale,1.125))}}@-webkit-keyframes fa-flip{50%{-webkit-transform:rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg));transform:rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg))}}@keyframes fa-flip{50%{-webkit-transform:rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg));transform:rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg))}}@-webkit-keyframes fa-shake{0%{-webkit-transform:rotate(-15deg);transform:rotate(-15deg)}4%{-webkit-transform:rotate(15deg);transform:rotate(15deg)}8%,24%{-webkit-transform:rotate(-18deg);transform:rotate(-18deg)}12%,28%{-webkit-transform:rotate(18deg);transform:rotate(18deg)}16%{-webkit-transform:rotate(-22deg);transform:rotate(-22deg)}20%{-webkit-transform:rotate(22deg);transform:rotate(22deg)}32%{-webkit-transform:rotate(-12deg);transform:rotate(-12deg)}36%{-webkit-transform:rotate(12deg);transform:rotate(12deg)}40%,to{-webkit-transform:rotate(0deg);transform:rotate(0deg)}}@keyframes fa-shake{0%{-webkit-transform:rotate(-15deg);transform:rotate(-15deg)}4%{-webkit-transform:rotate(15deg);transform:rotate(15deg)}8%,24%{-webkit-transform:rotate(-18deg);transform:rotate(-18deg)}12%,28%{-webkit-transform:rotate(18deg);transform:rotate(18deg)}16%{-webkit-transform:rotate(-22deg);transform:rotate(-22deg)}20%{-webkit-transform:rotate(22deg);transform:rotate(22deg)}32%{-webkit-transform:rotate(-12deg);transform:rotate(-12deg)}36%{-webkit-transform:rotate(12deg);transform:rotate(12deg)}40%,to{-webkit-transform:rotate(0deg);transform:rotate(0deg)}}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.fa-rotate-90{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-webkit-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-webkit-transform:scaleY(-1);transform:scaleY(-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{-webkit-transform:scale(-1);transform:scale(-1)}.fa-rotate-by{-webkit-transform:rotate(var(--fa-rotate-angle,none));transform:rotate(var(--fa-rotate-angle,none))}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%;z-index:var(--fa-stack-z-index,auto)}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:var(--fa-inverse,#fff)}.fa-0:before{content:"\30"}.fa-1:before{content:"\31"}.fa-2:before{content:"\32"}.fa-3:before{content:"\33"}.fa-4:before{content:"\34"}.fa-5:before{content:"\35"}.fa-6:before{content:"\36"}.fa-7:before{content:"\37"}.fa-8:before{content:"\38"}.fa-9:before{content:"\39"}.fa-a:before{content:"\41"}.fa-address-book:before,.fa-contact-book:before{content:"\f2b9"}.fa-address-card:before,.fa-contact-card:before,.fa-vcard:before{content:"\f2bb"}.fa-align-center:before{content:"\f037"}.fa-align-justify:before{content:"\f039"}.fa-align-left:before{content:"\f036"}.fa-align-right:before{content:"\f038"}.fa-anchor:before{content:"\f13d"}.fa-angle-down:before{content:"\f107"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-double-down:before,.fa-angles-down:before{content:"\f103"}.fa-angle-double-left:before,.fa-angles-left:before{content:"\f100"}.fa-angle-double-right:before,.fa-angles-right:before{content:"\f101"}.fa-angle-double-up:before,.fa-angles-up:before{content:"\f102"}.fa-ankh:before{content:"\f644"}.fa-apple-alt:before,.fa-apple-whole:before{content:"\f5d1"}.fa-archway:before{content:"\f557"}.fa-arrow-down:before{content:"\f063"}.fa-arrow-down-1-9:before,.fa-sort-numeric-asc:before,.fa-sort-numeric-down:before{content:"\f162"}.fa-arrow-down-9-1:before,.fa-sort-numeric-desc:before,.fa-sort-numeric-down-alt:before{content:"\f886"}.fa-arrow-down-a-z:before,.fa-sort-alpha-asc:before,.fa-sort-alpha-down:before{content:"\f15d"}.fa-arrow-down-long:before,.fa-long-arrow-down:before{content:"\f175"}.fa-arrow-down-short-wide:before,.fa-sort-amount-desc:before,.fa-sort-amount-down-alt:before{content:"\f884"}.fa-arrow-down-wide-short:before,.fa-sort-amount-asc:before,.fa-sort-amount-down:before{content:"\f160"}.fa-arrow-down-z-a:before,.fa-sort-alpha-desc:before,.fa-sort-alpha-down-alt:before{content:"\f881"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-left-long:before,.fa-long-arrow-left:before{content:"\f177"}.fa-arrow-pointer:before,.fa-mouse-pointer:before{content:"\f245"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-right-arrow-left:before,.fa-exchange:before{content:"\f0ec"}.fa-arrow-right-from-bracket:before,.fa-sign-out:before{content:"\f08b"}.fa-arrow-right-long:before,.fa-long-arrow-right:before{content:"\f178"}.fa-arrow-right-to-bracket:before,.fa-sign-in:before{content:"\f090"}.fa-arrow-left-rotate:before,.fa-arrow-rotate-back:before,.fa-arrow-rotate-backward:before,.fa-arrow-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-arrow-right-rotate:before,.fa-arrow-rotate-forward:before,.fa-arrow-rotate-right:before,.fa-redo:before{content:"\f01e"}.fa-arrow-trend-down:before{content:"\e097"}.fa-arrow-trend-up:before{content:"\e098"}.fa-arrow-turn-down:before,.fa-level-down:before{content:"\f149"}.fa-arrow-turn-up:before,.fa-level-up:before{content:"\f148"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-up-1-9:before,.fa-sort-numeric-up:before{content:"\f163"}.fa-arrow-up-9-1:before,.fa-sort-numeric-up-alt:before{content:"\f887"}.fa-arrow-up-a-z:before,.fa-sort-alpha-up:before{content:"\f15e"}.fa-arrow-up-from-bracket:before{content:"\e09a"}.fa-arrow-up-long:before,.fa-long-arrow-up:before{content:"\f176"}.fa-arrow-up-right-from-square:before,.fa-external-link:before{content:"\f08e"}.fa-arrow-up-short-wide:before,.fa-sort-amount-up-alt:before{content:"\f885"}.fa-arrow-up-wide-short:before,.fa-sort-amount-up:before{content:"\f161"}.fa-arrow-up-z-a:before,.fa-sort-alpha-up-alt:before{content:"\f882"}.fa-arrows-h:before,.fa-arrows-left-right:before{content:"\f07e"}.fa-arrows-rotate:before,.fa-refresh:before,.fa-sync:before{content:"\f021"}.fa-arrows-up-down:before,.fa-arrows-v:before{content:"\f07d"}.fa-arrows-up-down-left-right:before,.fa-arrows:before{content:"\f047"}.fa-asterisk:before{content:"\2a"}.fa-at:before{content:"\40"}.fa-atom:before{content:"\f5d2"}.fa-audio-description:before{content:"\f29e"}.fa-austral-sign:before{content:"\e0a9"}.fa-award:before{content:"\f559"}.fa-b:before{content:"\42"}.fa-baby:before{content:"\f77c"}.fa-baby-carriage:before,.fa-carriage-baby:before{content:"\f77d"}.fa-backward:before{content:"\f04a"}.fa-backward-fast:before,.fa-fast-backward:before{content:"\f049"}.fa-backward-step:before,.fa-step-backward:before{content:"\f048"}.fa-bacon:before{content:"\f7e5"}.fa-bacteria:before{content:"\e059"}.fa-bacterium:before{content:"\e05a"}.fa-bag-shopping:before,.fa-shopping-bag:before{content:"\f290"}.fa-bahai:before{content:"\f666"}.fa-baht-sign:before{content:"\e0ac"}.fa-ban:before,.fa-cancel:before{content:"\f05e"}.fa-ban-smoking:before,.fa-smoking-ban:before{content:"\f54d"}.fa-band-aid:before,.fa-bandage:before{content:"\f462"}.fa-barcode:before{content:"\f02a"}.fa-bars:before,.fa-navicon:before{content:"\f0c9"}.fa-bars-progress:before,.fa-tasks-alt:before{content:"\f828"}.fa-bars-staggered:before,.fa-reorder:before,.fa-stream:before{content:"\f550"}.fa-baseball-ball:before,.fa-baseball:before{content:"\f433"}.fa-baseball-bat-ball:before{content:"\f432"}.fa-basket-shopping:before,.fa-shopping-basket:before{content:"\f291"}.fa-basketball-ball:before,.fa-basketball:before{content:"\f434"}.fa-bath:before,.fa-bathtub:before{content:"\f2cd"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-battery-5:before,.fa-battery-full:before,.fa-battery:before{content:"\f240"}.fa-battery-3:before,.fa-battery-half:before{content:"\f242"}.fa-battery-2:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-4:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-bed:before{content:"\f236"}.fa-bed-pulse:before,.fa-procedures:before{content:"\f487"}.fa-beer-mug-empty:before,.fa-beer:before{content:"\f0fc"}.fa-bell:before{content:"\f0f3"}.fa-bell-concierge:before,.fa-concierge-bell:before{content:"\f562"}.fa-bell-slash:before{content:"\f1f6"}.fa-bezier-curve:before{content:"\f55b"}.fa-bicycle:before{content:"\f206"}.fa-binoculars:before{content:"\f1e5"}.fa-biohazard:before{content:"\f780"}.fa-bitcoin-sign:before{content:"\e0b4"}.fa-blender:before{content:"\f517"}.fa-blender-phone:before{content:"\f6b6"}.fa-blog:before{content:"\f781"}.fa-bold:before{content:"\f032"}.fa-bolt:before,.fa-zap:before{content:"\f0e7"}.fa-bolt-lightning:before{content:"\e0b7"}.fa-bomb:before{content:"\f1e2"}.fa-bone:before{content:"\f5d7"}.fa-bong:before{content:"\f55c"}.fa-book:before{content:"\f02d"}.fa-atlas:before,.fa-book-atlas:before{content:"\f558"}.fa-bible:before,.fa-book-bible:before{content:"\f647"}.fa-book-journal-whills:before,.fa-journal-whills:before{content:"\f66a"}.fa-book-medical:before{content:"\f7e6"}.fa-book-open:before{content:"\f518"}.fa-book-open-reader:before,.fa-book-reader:before{content:"\f5da"}.fa-book-quran:before,.fa-quran:before{content:"\f687"}.fa-book-dead:before,.fa-book-skull:before{content:"\f6b7"}.fa-bookmark:before{content:"\f02e"}.fa-border-all:before{content:"\f84c"}.fa-border-none:before{content:"\f850"}.fa-border-style:before,.fa-border-top-left:before{content:"\f853"}.fa-bowling-ball:before{content:"\f436"}.fa-box:before{content:"\f466"}.fa-archive:before,.fa-box-archive:before{content:"\f187"}.fa-box-open:before{content:"\f49e"}.fa-box-tissue:before{content:"\e05b"}.fa-boxes-alt:before,.fa-boxes-stacked:before,.fa-boxes:before{content:"\f468"}.fa-braille:before{content:"\f2a1"}.fa-brain:before{content:"\f5dc"}.fa-brazilian-real-sign:before{content:"\e46c"}.fa-bread-slice:before{content:"\f7ec"}.fa-briefcase:before{content:"\f0b1"}.fa-briefcase-medical:before{content:"\f469"}.fa-broom:before{content:"\f51a"}.fa-broom-ball:before,.fa-quidditch-broom-ball:before,.fa-quidditch:before{content:"\f458"}.fa-brush:before{content:"\f55d"}.fa-bug:before{content:"\f188"}.fa-bug-slash:before{content:"\e490"}.fa-building:before{content:"\f1ad"}.fa-bank:before,.fa-building-columns:before,.fa-institution:before,.fa-museum:before,.fa-university:before{content:"\f19c"}.fa-bullhorn:before{content:"\f0a1"}.fa-bullseye:before{content:"\f140"}.fa-burger:before,.fa-hamburger:before{content:"\f805"}.fa-bus:before{content:"\f207"}.fa-bus-alt:before,.fa-bus-simple:before{content:"\f55e"}.fa-briefcase-clock:before,.fa-business-time:before{content:"\f64a"}.fa-c:before{content:"\43"}.fa-birthday-cake:before,.fa-cake-candles:before,.fa-cake:before{content:"\f1fd"}.fa-calculator:before{content:"\f1ec"}.fa-calendar:before{content:"\f133"}.fa-calendar-check:before{content:"\f274"}.fa-calendar-day:before{content:"\f783"}.fa-calendar-alt:before,.fa-calendar-days:before{content:"\f073"}.fa-calendar-minus:before{content:"\f272"}.fa-calendar-plus:before{content:"\f271"}.fa-calendar-week:before{content:"\f784"}.fa-calendar-times:before,.fa-calendar-xmark:before{content:"\f273"}.fa-camera-alt:before,.fa-camera:before{content:"\f030"}.fa-camera-retro:before{content:"\f083"}.fa-camera-rotate:before{content:"\e0d8"}.fa-campground:before{content:"\f6bb"}.fa-candy-cane:before{content:"\f786"}.fa-cannabis:before{content:"\f55f"}.fa-capsules:before{content:"\f46b"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-battery-car:before,.fa-car-battery:before{content:"\f5df"}.fa-car-crash:before{content:"\f5e1"}.fa-car-alt:before,.fa-car-rear:before{content:"\f5de"}.fa-car-side:before{content:"\f5e4"}.fa-caravan:before{content:"\f8ff"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-caret-up:before{content:"\f0d8"}.fa-carrot:before{content:"\f787"}.fa-cart-arrow-down:before{content:"\f218"}.fa-cart-flatbed:before,.fa-dolly-flatbed:before{content:"\f474"}.fa-cart-flatbed-suitcase:before,.fa-luggage-cart:before{content:"\f59d"}.fa-cart-plus:before{content:"\f217"}.fa-cart-shopping:before,.fa-shopping-cart:before{content:"\f07a"}.fa-cash-register:before{content:"\f788"}.fa-cat:before{content:"\f6be"}.fa-cedi-sign:before{content:"\e0df"}.fa-cent-sign:before{content:"\e3f5"}.fa-certificate:before{content:"\f0a3"}.fa-chair:before{content:"\f6c0"}.fa-blackboard:before,.fa-chalkboard:before{content:"\f51b"}.fa-chalkboard-teacher:before,.fa-chalkboard-user:before{content:"\f51c"}.fa-champagne-glasses:before,.fa-glass-cheers:before{content:"\f79f"}.fa-charging-station:before{content:"\f5e7"}.fa-area-chart:before,.fa-chart-area:before{content:"\f1fe"}.fa-bar-chart:before,.fa-chart-bar:before{content:"\f080"}.fa-chart-column:before{content:"\e0e3"}.fa-chart-gantt:before{content:"\e0e4"}.fa-chart-line:before,.fa-line-chart:before{content:"\f201"}.fa-chart-pie:before,.fa-pie-chart:before{content:"\f200"}.fa-check:before{content:"\f00c"}.fa-check-double:before{content:"\f560"}.fa-check-to-slot:before,.fa-vote-yea:before{content:"\f772"}.fa-cheese:before{content:"\f7ef"}.fa-chess:before{content:"\f439"}.fa-chess-bishop:before{content:"\f43a"}.fa-chess-board:before{content:"\f43c"}.fa-chess-king:before{content:"\f43f"}.fa-chess-knight:before{content:"\f441"}.fa-chess-pawn:before{content:"\f443"}.fa-chess-queen:before{content:"\f445"}.fa-chess-rook:before{content:"\f447"}.fa-chevron-down:before{content:"\f078"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-chevron-up:before{content:"\f077"}.fa-child:before{content:"\f1ae"}.fa-church:before{content:"\f51d"}.fa-circle:before{content:"\f111"}.fa-arrow-circle-down:before,.fa-circle-arrow-down:before{content:"\f0ab"}.fa-arrow-circle-left:before,.fa-circle-arrow-left:before{content:"\f0a8"}.fa-arrow-circle-right:before,.fa-circle-arrow-right:before{content:"\f0a9"}.fa-arrow-circle-up:before,.fa-circle-arrow-up:before{content:"\f0aa"}.fa-check-circle:before,.fa-circle-check:before{content:"\f058"}.fa-chevron-circle-down:before,.fa-circle-chevron-down:before{content:"\f13a"}.fa-chevron-circle-left:before,.fa-circle-chevron-left:before{content:"\f137"}.fa-chevron-circle-right:before,.fa-circle-chevron-right:before{content:"\f138"}.fa-chevron-circle-up:before,.fa-circle-chevron-up:before{content:"\f139"}.fa-circle-dollar-to-slot:before,.fa-donate:before{content:"\f4b9"}.fa-circle-dot:before,.fa-dot-circle:before{content:"\f192"}.fa-arrow-alt-circle-down:before,.fa-circle-down:before{content:"\f358"}.fa-circle-exclamation:before,.fa-exclamation-circle:before{content:"\f06a"}.fa-circle-h:before,.fa-hospital-symbol:before{content:"\f47e"}.fa-adjust:before,.fa-circle-half-stroke:before{content:"\f042"}.fa-circle-info:before,.fa-info-circle:before{content:"\f05a"}.fa-arrow-alt-circle-left:before,.fa-circle-left:before{content:"\f359"}.fa-circle-minus:before,.fa-minus-circle:before{content:"\f056"}.fa-circle-notch:before{content:"\f1ce"}.fa-circle-pause:before,.fa-pause-circle:before{content:"\f28b"}.fa-circle-play:before,.fa-play-circle:before{content:"\f144"}.fa-circle-plus:before,.fa-plus-circle:before{content:"\f055"}.fa-circle-question:before,.fa-question-circle:before{content:"\f059"}.fa-circle-radiation:before,.fa-radiation-alt:before{content:"\f7ba"}.fa-arrow-alt-circle-right:before,.fa-circle-right:before{content:"\f35a"}.fa-circle-stop:before,.fa-stop-circle:before{content:"\f28d"}.fa-arrow-alt-circle-up:before,.fa-circle-up:before{content:"\f35b"}.fa-circle-user:before,.fa-user-circle:before{content:"\f2bd"}.fa-circle-xmark:before,.fa-times-circle:before,.fa-xmark-circle:before{content:"\f057"}.fa-city:before{content:"\f64f"}.fa-clapperboard:before{content:"\e131"}.fa-clipboard:before{content:"\f328"}.fa-clipboard-check:before{content:"\f46c"}.fa-clipboard-list:before{content:"\f46d"}.fa-clock-four:before,.fa-clock:before{content:"\f017"}.fa-clock-rotate-left:before,.fa-history:before{content:"\f1da"}.fa-clone:before{content:"\f24d"}.fa-closed-captioning:before{content:"\f20a"}.fa-cloud:before{content:"\f0c2"}.fa-cloud-arrow-down:before,.fa-cloud-download-alt:before,.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-arrow-up:before,.fa-cloud-upload-alt:before,.fa-cloud-upload:before{content:"\f0ee"}.fa-cloud-meatball:before{content:"\f73b"}.fa-cloud-moon:before{content:"\f6c3"}.fa-cloud-moon-rain:before{content:"\f73c"}.fa-cloud-rain:before{content:"\f73d"}.fa-cloud-showers-heavy:before{content:"\f740"}.fa-cloud-sun:before{content:"\f6c4"}.fa-cloud-sun-rain:before{content:"\f743"}.fa-clover:before{content:"\e139"}.fa-code:before{content:"\f121"}.fa-code-branch:before{content:"\f126"}.fa-code-commit:before{content:"\f386"}.fa-code-compare:before{content:"\e13a"}.fa-code-fork:before{content:"\e13b"}.fa-code-merge:before{content:"\f387"}.fa-code-pull-request:before{content:"\e13c"}.fa-coins:before{content:"\f51e"}.fa-colon-sign:before{content:"\e140"}.fa-comment:before{content:"\f075"}.fa-comment-dollar:before{content:"\f651"}.fa-comment-dots:before,.fa-commenting:before{content:"\f4ad"}.fa-comment-medical:before{content:"\f7f5"}.fa-comment-slash:before{content:"\f4b3"}.fa-comment-sms:before,.fa-sms:before{content:"\f7cd"}.fa-comments:before{content:"\f086"}.fa-comments-dollar:before{content:"\f653"}.fa-compact-disc:before{content:"\f51f"}.fa-compass:before{content:"\f14e"}.fa-compass-drafting:before,.fa-drafting-compass:before{content:"\f568"}.fa-compress:before{content:"\f066"}.fa-computer-mouse:before,.fa-mouse:before{content:"\f8cc"}.fa-cookie:before{content:"\f563"}.fa-cookie-bite:before{content:"\f564"}.fa-copy:before{content:"\f0c5"}.fa-copyright:before{content:"\f1f9"}.fa-couch:before{content:"\f4b8"}.fa-credit-card-alt:before,.fa-credit-card:before{content:"\f09d"}.fa-crop:before{content:"\f125"}.fa-crop-alt:before,.fa-crop-simple:before{content:"\f565"}.fa-cross:before{content:"\f654"}.fa-crosshairs:before{content:"\f05b"}.fa-crow:before{content:"\f520"}.fa-crown:before{content:"\f521"}.fa-crutch:before{content:"\f7f7"}.fa-cruzeiro-sign:before{content:"\e152"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-d:before{content:"\44"}.fa-database:before{content:"\f1c0"}.fa-backspace:before,.fa-delete-left:before{content:"\f55a"}.fa-democrat:before{content:"\f747"}.fa-desktop-alt:before,.fa-desktop:before{content:"\f390"}.fa-dharmachakra:before{content:"\f655"}.fa-diagram-next:before{content:"\e476"}.fa-diagram-predecessor:before{content:"\e477"}.fa-diagram-project:before,.fa-project-diagram:before{content:"\f542"}.fa-diagram-successor:before{content:"\e47a"}.fa-diamond:before{content:"\f219"}.fa-diamond-turn-right:before,.fa-directions:before{content:"\f5eb"}.fa-dice:before{content:"\f522"}.fa-dice-d20:before{content:"\f6cf"}.fa-dice-d6:before{content:"\f6d1"}.fa-dice-five:before{content:"\f523"}.fa-dice-four:before{content:"\f524"}.fa-dice-one:before{content:"\f525"}.fa-dice-six:before{content:"\f526"}.fa-dice-three:before{content:"\f527"}.fa-dice-two:before{content:"\f528"}.fa-disease:before{content:"\f7fa"}.fa-divide:before{content:"\f529"}.fa-dna:before{content:"\f471"}.fa-dog:before{content:"\f6d3"}.fa-dollar-sign:before,.fa-dollar:before,.fa-usd:before{content:"\24"}.fa-dolly-box:before,.fa-dolly:before{content:"\f472"}.fa-dong-sign:before{content:"\e169"}.fa-door-closed:before{content:"\f52a"}.fa-door-open:before{content:"\f52b"}.fa-dove:before{content:"\f4ba"}.fa-compress-alt:before,.fa-down-left-and-up-right-to-center:before{content:"\f422"}.fa-down-long:before,.fa-long-arrow-alt-down:before{content:"\f309"}.fa-download:before{content:"\f019"}.fa-dragon:before{content:"\f6d5"}.fa-draw-polygon:before{content:"\f5ee"}.fa-droplet:before,.fa-tint:before{content:"\f043"}.fa-droplet-slash:before,.fa-tint-slash:before{content:"\f5c7"}.fa-drum:before{content:"\f569"}.fa-drum-steelpan:before{content:"\f56a"}.fa-drumstick-bite:before{content:"\f6d7"}.fa-dumbbell:before{content:"\f44b"}.fa-dumpster:before{content:"\f793"}.fa-dumpster-fire:before{content:"\f794"}.fa-dungeon:before{content:"\f6d9"}.fa-e:before{content:"\45"}.fa-deaf:before,.fa-deafness:before,.fa-ear-deaf:before,.fa-hard-of-hearing:before{content:"\f2a4"}.fa-assistive-listening-systems:before,.fa-ear-listen:before{content:"\f2a2"}.fa-earth-africa:before,.fa-globe-africa:before{content:"\f57c"}.fa-earth-america:before,.fa-earth-americas:before,.fa-earth:before,.fa-globe-americas:before{content:"\f57d"}.fa-earth-asia:before,.fa-globe-asia:before{content:"\f57e"}.fa-earth-europe:before,.fa-globe-europe:before{content:"\f7a2"}.fa-earth-oceania:before,.fa-globe-oceania:before{content:"\e47b"}.fa-egg:before{content:"\f7fb"}.fa-eject:before{content:"\f052"}.fa-elevator:before{content:"\e16d"}.fa-ellipsis-h:before,.fa-ellipsis:before{content:"\f141"}.fa-ellipsis-v:before,.fa-ellipsis-vertical:before{content:"\f142"}.fa-envelope:before{content:"\f0e0"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-text:before{content:"\f658"}.fa-envelopes-bulk:before,.fa-mail-bulk:before{content:"\f674"}.fa-equals:before{content:"\3d"}.fa-eraser:before{content:"\f12d"}.fa-ethernet:before{content:"\f796"}.fa-eur:before,.fa-euro-sign:before,.fa-euro:before{content:"\f153"}.fa-exclamation:before{content:"\21"}.fa-expand:before{content:"\f065"}.fa-eye:before{content:"\f06e"}.fa-eye-dropper-empty:before,.fa-eye-dropper:before,.fa-eyedropper:before{content:"\f1fb"}.fa-eye-low-vision:before,.fa-low-vision:before{content:"\f2a8"}.fa-eye-slash:before{content:"\f070"}.fa-f:before{content:"\46"}.fa-angry:before,.fa-face-angry:before{content:"\f556"}.fa-dizzy:before,.fa-face-dizzy:before{content:"\f567"}.fa-face-flushed:before,.fa-flushed:before{content:"\f579"}.fa-face-frown:before,.fa-frown:before{content:"\f119"}.fa-face-frown-open:before,.fa-frown-open:before{content:"\f57a"}.fa-face-grimace:before,.fa-grimace:before{content:"\f57f"}.fa-face-grin:before,.fa-grin:before{content:"\f580"}.fa-face-grin-beam:before,.fa-grin-beam:before{content:"\f582"}.fa-face-grin-beam-sweat:before,.fa-grin-beam-sweat:before{content:"\f583"}.fa-face-grin-hearts:before,.fa-grin-hearts:before{content:"\f584"}.fa-face-grin-squint:before,.fa-grin-squint:before{content:"\f585"}.fa-face-grin-squint-tears:before,.fa-grin-squint-tears:before{content:"\f586"}.fa-face-grin-stars:before,.fa-grin-stars:before{content:"\f587"}.fa-face-grin-tears:before,.fa-grin-tears:before{content:"\f588"}.fa-face-grin-tongue:before,.fa-grin-tongue:before{content:"\f589"}.fa-face-grin-tongue-squint:before,.fa-grin-tongue-squint:before{content:"\f58a"}.fa-face-grin-tongue-wink:before,.fa-grin-tongue-wink:before{content:"\f58b"}.fa-face-grin-wide:before,.fa-grin-alt:before{content:"\f581"}.fa-face-grin-wink:before,.fa-grin-wink:before{content:"\f58c"}.fa-face-kiss:before,.fa-kiss:before{content:"\f596"}.fa-face-kiss-beam:before,.fa-kiss-beam:before{content:"\f597"}.fa-face-kiss-wink-heart:before,.fa-kiss-wink-heart:before{content:"\f598"}.fa-face-laugh:before,.fa-laugh:before{content:"\f599"}.fa-face-laugh-beam:before,.fa-laugh-beam:before{content:"\f59a"}.fa-face-laugh-squint:before,.fa-laugh-squint:before{content:"\f59b"}.fa-face-laugh-wink:before,.fa-laugh-wink:before{content:"\f59c"}.fa-face-meh:before,.fa-meh:before{content:"\f11a"}.fa-face-meh-blank:before,.fa-meh-blank:before{content:"\f5a4"}.fa-face-rolling-eyes:before,.fa-meh-rolling-eyes:before{content:"\f5a5"}.fa-face-sad-cry:before,.fa-sad-cry:before{content:"\f5b3"}.fa-face-sad-tear:before,.fa-sad-tear:before{content:"\f5b4"}.fa-face-smile:before,.fa-smile:before{content:"\f118"}.fa-face-smile-beam:before,.fa-smile-beam:before{content:"\f5b8"}.fa-face-smile-wink:before,.fa-smile-wink:before{content:"\f4da"}.fa-face-surprise:before,.fa-surprise:before{content:"\f5c2"}.fa-face-tired:before,.fa-tired:before{content:"\f5c8"}.fa-fan:before{content:"\f863"}.fa-faucet:before{content:"\e005"}.fa-fax:before{content:"\f1ac"}.fa-feather:before{content:"\f52d"}.fa-feather-alt:before,.fa-feather-pointed:before{content:"\f56b"}.fa-file:before{content:"\f15b"}.fa-file-arrow-down:before,.fa-file-download:before{content:"\f56d"}.fa-file-arrow-up:before,.fa-file-upload:before{content:"\f574"}.fa-file-audio:before{content:"\f1c7"}.fa-file-code:before{content:"\f1c9"}.fa-file-contract:before{content:"\f56c"}.fa-file-csv:before{content:"\f6dd"}.fa-file-excel:before{content:"\f1c3"}.fa-arrow-right-from-file:before,.fa-file-export:before{content:"\f56e"}.fa-file-image:before{content:"\f1c5"}.fa-arrow-right-to-file:before,.fa-file-import:before{content:"\f56f"}.fa-file-invoice:before{content:"\f570"}.fa-file-invoice-dollar:before{content:"\f571"}.fa-file-alt:before,.fa-file-lines:before,.fa-file-text:before{content:"\f15c"}.fa-file-medical:before{content:"\f477"}.fa-file-pdf:before{content:"\f1c1"}.fa-file-powerpoint:before{content:"\f1c4"}.fa-file-prescription:before{content:"\f572"}.fa-file-signature:before{content:"\f573"}.fa-file-video:before{content:"\f1c8"}.fa-file-medical-alt:before,.fa-file-waveform:before{content:"\f478"}.fa-file-word:before{content:"\f1c2"}.fa-file-archive:before,.fa-file-zipper:before{content:"\f1c6"}.fa-fill:before{content:"\f575"}.fa-fill-drip:before{content:"\f576"}.fa-film:before{content:"\f008"}.fa-filter:before{content:"\f0b0"}.fa-filter-circle-dollar:before,.fa-funnel-dollar:before{content:"\f662"}.fa-filter-circle-xmark:before{content:"\e17b"}.fa-fingerprint:before{content:"\f577"}.fa-fire:before{content:"\f06d"}.fa-fire-extinguisher:before{content:"\f134"}.fa-fire-alt:before,.fa-fire-flame-curved:before{content:"\f7e4"}.fa-burn:before,.fa-fire-flame-simple:before{content:"\f46a"}.fa-fish:before{content:"\f578"}.fa-flag:before{content:"\f024"}.fa-flag-checkered:before{content:"\f11e"}.fa-flag-usa:before{content:"\f74d"}.fa-flask:before{content:"\f0c3"}.fa-floppy-disk:before,.fa-save:before{content:"\f0c7"}.fa-florin-sign:before{content:"\e184"}.fa-folder:before{content:"\f07b"}.fa-folder-minus:before{content:"\f65d"}.fa-folder-open:before{content:"\f07c"}.fa-folder-plus:before{content:"\f65e"}.fa-folder-tree:before{content:"\f802"}.fa-font:before{content:"\f031"}.fa-football-ball:before,.fa-football:before{content:"\f44e"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before,.fa-forward-fast:before{content:"\f050"}.fa-forward-step:before,.fa-step-forward:before{content:"\f051"}.fa-franc-sign:before{content:"\e18f"}.fa-frog:before{content:"\f52e"}.fa-futbol-ball:before,.fa-futbol:before,.fa-soccer-ball:before{content:"\f1e3"}.fa-g:before{content:"\47"}.fa-gamepad:before{content:"\f11b"}.fa-gas-pump:before{content:"\f52f"}.fa-dashboard:before,.fa-gauge-med:before,.fa-gauge:before,.fa-tachometer-alt-average:before{content:"\f624"}.fa-gauge-high:before,.fa-tachometer-alt-fast:before,.fa-tachometer-alt:before{content:"\f625"}.fa-gauge-simple-med:before,.fa-gauge-simple:before,.fa-tachometer-average:before{content:"\f629"}.fa-gauge-simple-high:before,.fa-tachometer-fast:before,.fa-tachometer:before{content:"\f62a"}.fa-gavel:before,.fa-legal:before{content:"\f0e3"}.fa-cog:before,.fa-gear:before{content:"\f013"}.fa-cogs:before,.fa-gears:before{content:"\f085"}.fa-gem:before{content:"\f3a5"}.fa-genderless:before{content:"\f22d"}.fa-ghost:before{content:"\f6e2"}.fa-gift:before{content:"\f06b"}.fa-gifts:before{content:"\f79c"}.fa-glasses:before{content:"\f530"}.fa-globe:before{content:"\f0ac"}.fa-golf-ball-tee:before,.fa-golf-ball:before{content:"\f450"}.fa-gopuram:before{content:"\f664"}.fa-graduation-cap:before,.fa-mortar-board:before{content:"\f19d"}.fa-greater-than:before{content:"\3e"}.fa-greater-than-equal:before{content:"\f532"}.fa-grip-horizontal:before,.fa-grip:before{content:"\f58d"}.fa-grip-lines:before{content:"\f7a4"}.fa-grip-lines-vertical:before{content:"\f7a5"}.fa-grip-vertical:before{content:"\f58e"}.fa-guarani-sign:before{content:"\e19a"}.fa-guitar:before{content:"\f7a6"}.fa-gun:before{content:"\e19b"}.fa-h:before{content:"\48"}.fa-hammer:before{content:"\f6e3"}.fa-hamsa:before{content:"\f665"}.fa-hand-paper:before,.fa-hand:before{content:"\f256"}.fa-hand-back-fist:before,.fa-hand-rock:before{content:"\f255"}.fa-allergies:before,.fa-hand-dots:before{content:"\f461"}.fa-fist-raised:before,.fa-hand-fist:before{content:"\f6de"}.fa-hand-holding:before{content:"\f4bd"}.fa-hand-holding-dollar:before,.fa-hand-holding-usd:before{content:"\f4c0"}.fa-hand-holding-droplet:before,.fa-hand-holding-water:before{content:"\f4c1"}.fa-hand-holding-heart:before{content:"\f4be"}.fa-hand-holding-medical:before{content:"\e05c"}.fa-hand-lizard:before{content:"\f258"}.fa-hand-middle-finger:before{content:"\f806"}.fa-hand-peace:before{content:"\f25b"}.fa-hand-point-down:before{content:"\f0a7"}.fa-hand-point-left:before{content:"\f0a5"}.fa-hand-point-right:before{content:"\f0a4"}.fa-hand-point-up:before{content:"\f0a6"}.fa-hand-pointer:before{content:"\f25a"}.fa-hand-scissors:before{content:"\f257"}.fa-hand-sparkles:before{content:"\e05d"}.fa-hand-spock:before{content:"\f259"}.fa-hands:before,.fa-sign-language:before,.fa-signing:before{content:"\f2a7"}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before,.fa-hands-american-sign-language-interpreting:before,.fa-hands-asl-interpreting:before{content:"\f2a3"}.fa-hands-bubbles:before,.fa-hands-wash:before{content:"\e05e"}.fa-hands-clapping:before{content:"\e1a8"}.fa-hands-holding:before{content:"\f4c2"}.fa-hands-praying:before,.fa-praying-hands:before{content:"\f684"}.fa-handshake:before{content:"\f2b5"}.fa-hands-helping:before,.fa-handshake-angle:before{content:"\f4c4"}.fa-handshake-alt-slash:before,.fa-handshake-simple-slash:before{content:"\e05f"}.fa-handshake-slash:before{content:"\e060"}.fa-hanukiah:before{content:"\f6e6"}.fa-hard-drive:before,.fa-hdd:before{content:"\f0a0"}.fa-hashtag:before{content:"\23"}.fa-hat-cowboy:before{content:"\f8c0"}.fa-hat-cowboy-side:before{content:"\f8c1"}.fa-hat-wizard:before{content:"\f6e8"}.fa-head-side-cough:before{content:"\e061"}.fa-head-side-cough-slash:before{content:"\e062"}.fa-head-side-mask:before{content:"\e063"}.fa-head-side-virus:before{content:"\e064"}.fa-header:before,.fa-heading:before{content:"\f1dc"}.fa-headphones:before{content:"\f025"}.fa-headphones-alt:before,.fa-headphones-simple:before{content:"\f58f"}.fa-headset:before{content:"\f590"}.fa-heart:before{content:"\f004"}.fa-heart-broken:before,.fa-heart-crack:before{content:"\f7a9"}.fa-heart-pulse:before,.fa-heartbeat:before{content:"\f21e"}.fa-helicopter:before{content:"\f533"}.fa-hard-hat:before,.fa-hat-hard:before,.fa-helmet-safety:before{content:"\f807"}.fa-highlighter:before{content:"\f591"}.fa-hippo:before{content:"\f6ed"}.fa-hockey-puck:before{content:"\f453"}.fa-holly-berry:before{content:"\f7aa"}.fa-horse:before{content:"\f6f0"}.fa-horse-head:before{content:"\f7ab"}.fa-hospital-alt:before,.fa-hospital-wide:before,.fa-hospital:before{content:"\f0f8"}.fa-hospital-user:before{content:"\f80d"}.fa-hot-tub-person:before,.fa-hot-tub:before{content:"\f593"}.fa-hotdog:before{content:"\f80f"}.fa-hotel:before{content:"\f594"}.fa-hourglass-2:before,.fa-hourglass-half:before,.fa-hourglass:before{content:"\f254"}.fa-hourglass-empty:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-home-alt:before,.fa-home-lg-alt:before,.fa-home:before,.fa-house:before{content:"\f015"}.fa-home-lg:before,.fa-house-chimney:before{content:"\e3af"}.fa-house-chimney-crack:before,.fa-house-damage:before{content:"\f6f1"}.fa-clinic-medical:before,.fa-house-chimney-medical:before{content:"\f7f2"}.fa-house-chimney-user:before{content:"\e065"}.fa-house-chimney-window:before{content:"\e00d"}.fa-house-crack:before{content:"\e3b1"}.fa-house-laptop:before,.fa-laptop-house:before{content:"\e066"}.fa-house-medical:before{content:"\e3b2"}.fa-home-user:before,.fa-house-user:before{content:"\e1b0"}.fa-hryvnia-sign:before,.fa-hryvnia:before{content:"\f6f2"}.fa-i:before{content:"\49"}.fa-i-cursor:before{content:"\f246"}.fa-ice-cream:before{content:"\f810"}.fa-icicles:before{content:"\f7ad"}.fa-heart-music-camera-bolt:before,.fa-icons:before{content:"\f86d"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-id-card-alt:before,.fa-id-card-clip:before{content:"\f47f"}.fa-igloo:before{content:"\f7ae"}.fa-image:before{content:"\f03e"}.fa-image-portrait:before,.fa-portrait:before{content:"\f3e0"}.fa-images:before{content:"\f302"}.fa-inbox:before{content:"\f01c"}.fa-indent:before{content:"\f03c"}.fa-indian-rupee-sign:before,.fa-indian-rupee:before,.fa-inr:before{content:"\e1bc"}.fa-industry:before{content:"\f275"}.fa-infinity:before{content:"\f534"}.fa-info:before{content:"\f129"}.fa-italic:before{content:"\f033"}.fa-j:before{content:"\4a"}.fa-jedi:before{content:"\f669"}.fa-fighter-jet:before,.fa-jet-fighter:before{content:"\f0fb"}.fa-joint:before{content:"\f595"}.fa-k:before{content:"\4b"}.fa-kaaba:before{content:"\f66b"}.fa-key:before{content:"\f084"}.fa-keyboard:before{content:"\f11c"}.fa-khanda:before{content:"\f66d"}.fa-kip-sign:before{content:"\e1c4"}.fa-first-aid:before,.fa-kit-medical:before{content:"\f479"}.fa-kiwi-bird:before{content:"\f535"}.fa-l:before{content:"\4c"}.fa-landmark:before{content:"\f66f"}.fa-language:before{content:"\f1ab"}.fa-laptop:before{content:"\f109"}.fa-laptop-code:before{content:"\f5fc"}.fa-laptop-medical:before{content:"\f812"}.fa-lari-sign:before{content:"\e1c8"}.fa-layer-group:before{content:"\f5fd"}.fa-leaf:before{content:"\f06c"}.fa-left-long:before,.fa-long-arrow-alt-left:before{content:"\f30a"}.fa-arrows-alt-h:before,.fa-left-right:before{content:"\f337"}.fa-lemon:before{content:"\f094"}.fa-less-than:before{content:"\3c"}.fa-less-than-equal:before{content:"\f537"}.fa-life-ring:before{content:"\f1cd"}.fa-lightbulb:before{content:"\f0eb"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-chain-broken:before,.fa-chain-slash:before,.fa-link-slash:before,.fa-unlink:before{content:"\f127"}.fa-lira-sign:before{content:"\f195"}.fa-list-squares:before,.fa-list:before{content:"\f03a"}.fa-list-check:before,.fa-tasks:before{content:"\f0ae"}.fa-list-1-2:before,.fa-list-numeric:before,.fa-list-ol:before{content:"\f0cb"}.fa-list-dots:before,.fa-list-ul:before{content:"\f0ca"}.fa-litecoin-sign:before{content:"\e1d3"}.fa-location-arrow:before{content:"\f124"}.fa-location-crosshairs:before,.fa-location:before{content:"\f601"}.fa-location-dot:before,.fa-map-marker-alt:before{content:"\f3c5"}.fa-location-pin:before,.fa-map-marker:before{content:"\f041"}.fa-lock:before{content:"\f023"}.fa-lock-open:before{content:"\f3c1"}.fa-lungs:before{content:"\f604"}.fa-lungs-virus:before{content:"\e067"}.fa-m:before{content:"\4d"}.fa-magnet:before{content:"\f076"}.fa-magnifying-glass:before,.fa-search:before{content:"\f002"}.fa-magnifying-glass-dollar:before,.fa-search-dollar:before{content:"\f688"}.fa-magnifying-glass-location:before,.fa-search-location:before{content:"\f689"}.fa-magnifying-glass-minus:before,.fa-search-minus:before{content:"\f010"}.fa-magnifying-glass-plus:before,.fa-search-plus:before{content:"\f00e"}.fa-manat-sign:before{content:"\e1d5"}.fa-map:before{content:"\f279"}.fa-map-location:before,.fa-map-marked:before{content:"\f59f"}.fa-map-location-dot:before,.fa-map-marked-alt:before{content:"\f5a0"}.fa-map-pin:before{content:"\f276"}.fa-marker:before{content:"\f5a1"}.fa-mars:before{content:"\f222"}.fa-mars-and-venus:before{content:"\f224"}.fa-mars-double:before{content:"\f227"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-h:before,.fa-mars-stroke-right:before{content:"\f22b"}.fa-mars-stroke-up:before,.fa-mars-stroke-v:before{content:"\f22a"}.fa-glass-martini-alt:before,.fa-martini-glass:before{content:"\f57b"}.fa-cocktail:before,.fa-martini-glass-citrus:before{content:"\f561"}.fa-glass-martini:before,.fa-martini-glass-empty:before{content:"\f000"}.fa-mask:before{content:"\f6fa"}.fa-mask-face:before{content:"\e1d7"}.fa-masks-theater:before,.fa-theater-masks:before{content:"\f630"}.fa-expand-arrows-alt:before,.fa-maximize:before{content:"\f31e"}.fa-medal:before{content:"\f5a2"}.fa-memory:before{content:"\f538"}.fa-menorah:before{content:"\f676"}.fa-mercury:before{content:"\f223"}.fa-comment-alt:before,.fa-message:before{content:"\f27a"}.fa-meteor:before{content:"\f753"}.fa-microchip:before{content:"\f2db"}.fa-microphone:before{content:"\f130"}.fa-microphone-alt:before,.fa-microphone-lines:before{content:"\f3c9"}.fa-microphone-alt-slash:before,.fa-microphone-lines-slash:before{content:"\f539"}.fa-microphone-slash:before{content:"\f131"}.fa-microscope:before{content:"\f610"}.fa-mill-sign:before{content:"\e1ed"}.fa-compress-arrows-alt:before,.fa-minimize:before{content:"\f78c"}.fa-minus:before,.fa-subtract:before{content:"\f068"}.fa-mitten:before{content:"\f7b5"}.fa-mobile-android:before,.fa-mobile-phone:before,.fa-mobile:before{content:"\f3ce"}.fa-mobile-button:before{content:"\f10b"}.fa-mobile-alt:before,.fa-mobile-screen-button:before{content:"\f3cd"}.fa-money-bill:before{content:"\f0d6"}.fa-money-bill-1:before,.fa-money-bill-alt:before{content:"\f3d1"}.fa-money-bill-1-wave:before,.fa-money-bill-wave-alt:before{content:"\f53b"}.fa-money-bill-wave:before{content:"\f53a"}.fa-money-check:before{content:"\f53c"}.fa-money-check-alt:before,.fa-money-check-dollar:before{content:"\f53d"}.fa-monument:before{content:"\f5a6"}.fa-moon:before{content:"\f186"}.fa-mortar-pestle:before{content:"\f5a7"}.fa-mosque:before{content:"\f678"}.fa-motorcycle:before{content:"\f21c"}.fa-mountain:before{content:"\f6fc"}.fa-mug-hot:before{content:"\f7b6"}.fa-coffee:before,.fa-mug-saucer:before{content:"\f0f4"}.fa-music:before{content:"\f001"}.fa-n:before{content:"\4e"}.fa-naira-sign:before{content:"\e1f6"}.fa-network-wired:before{content:"\f6ff"}.fa-neuter:before{content:"\f22c"}.fa-newspaper:before{content:"\f1ea"}.fa-not-equal:before{content:"\f53e"}.fa-note-sticky:before,.fa-sticky-note:before{content:"\f249"}.fa-notes-medical:before{content:"\f481"}.fa-o:before{content:"\4f"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-oil-can:before{content:"\f613"}.fa-om:before{content:"\f679"}.fa-otter:before{content:"\f700"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-p:before{content:"\50"}.fa-pager:before{content:"\f815"}.fa-paint-roller:before{content:"\f5aa"}.fa-paint-brush:before,.fa-paintbrush:before{content:"\f1fc"}.fa-palette:before{content:"\f53f"}.fa-pallet:before{content:"\f482"}.fa-panorama:before{content:"\e209"}.fa-paper-plane:before{content:"\f1d8"}.fa-paperclip:before{content:"\f0c6"}.fa-parachute-box:before{content:"\f4cd"}.fa-paragraph:before{content:"\f1dd"}.fa-passport:before{content:"\f5ab"}.fa-file-clipboard:before,.fa-paste:before{content:"\f0ea"}.fa-pause:before{content:"\f04c"}.fa-paw:before{content:"\f1b0"}.fa-peace:before{content:"\f67c"}.fa-pen:before{content:"\f304"}.fa-pen-alt:before,.fa-pen-clip:before{content:"\f305"}.fa-pen-fancy:before{content:"\f5ac"}.fa-pen-nib:before{content:"\f5ad"}.fa-pen-ruler:before,.fa-pencil-ruler:before{content:"\f5ae"}.fa-edit:before,.fa-pen-to-square:before{content:"\f044"}.fa-pencil-alt:before,.fa-pencil:before{content:"\f303"}.fa-people-arrows-left-right:before,.fa-people-arrows:before{content:"\e068"}.fa-people-carry-box:before,.fa-people-carry:before{content:"\f4ce"}.fa-pepper-hot:before{content:"\f816"}.fa-percent:before,.fa-percentage:before{content:"\25"}.fa-male:before,.fa-person:before{content:"\f183"}.fa-biking:before,.fa-person-biking:before{content:"\f84a"}.fa-person-booth:before{content:"\f756"}.fa-diagnoses:before,.fa-person-dots-from-line:before{content:"\f470"}.fa-female:before,.fa-person-dress:before{content:"\f182"}.fa-hiking:before,.fa-person-hiking:before{content:"\f6ec"}.fa-person-praying:before,.fa-pray:before{content:"\f683"}.fa-person-running:before,.fa-running:before{content:"\f70c"}.fa-person-skating:before,.fa-skating:before{content:"\f7c5"}.fa-person-skiing:before,.fa-skiing:before{content:"\f7c9"}.fa-person-skiing-nordic:before,.fa-skiing-nordic:before{content:"\f7ca"}.fa-person-snowboarding:before,.fa-snowboarding:before{content:"\f7ce"}.fa-person-swimming:before,.fa-swimmer:before{content:"\f5c4"}.fa-person-walking:before,.fa-walking:before{content:"\f554"}.fa-blind:before,.fa-person-walking-with-cane:before{content:"\f29d"}.fa-peseta-sign:before{content:"\e221"}.fa-peso-sign:before{content:"\e222"}.fa-phone:before{content:"\f095"}.fa-phone-alt:before,.fa-phone-flip:before{content:"\f879"}.fa-phone-slash:before{content:"\f3dd"}.fa-phone-volume:before,.fa-volume-control-phone:before{content:"\f2a0"}.fa-photo-film:before,.fa-photo-video:before{content:"\f87c"}.fa-piggy-bank:before{content:"\f4d3"}.fa-pills:before{content:"\f484"}.fa-pizza-slice:before{content:"\f818"}.fa-place-of-worship:before{content:"\f67f"}.fa-plane:before{content:"\f072"}.fa-plane-arrival:before{content:"\f5af"}.fa-plane-departure:before{content:"\f5b0"}.fa-plane-slash:before{content:"\e069"}.fa-play:before{content:"\f04b"}.fa-plug:before{content:"\f1e6"}.fa-add:before,.fa-plus:before{content:"\2b"}.fa-plus-minus:before{content:"\e43c"}.fa-podcast:before{content:"\f2ce"}.fa-poo:before{content:"\f2fe"}.fa-poo-bolt:before,.fa-poo-storm:before{content:"\f75a"}.fa-poop:before{content:"\f619"}.fa-power-off:before{content:"\f011"}.fa-prescription:before{content:"\f5b1"}.fa-prescription-bottle:before{content:"\f485"}.fa-prescription-bottle-alt:before,.fa-prescription-bottle-medical:before{content:"\f486"}.fa-print:before{content:"\f02f"}.fa-pump-medical:before{content:"\e06a"}.fa-pump-soap:before{content:"\e06b"}.fa-puzzle-piece:before{content:"\f12e"}.fa-q:before{content:"\51"}.fa-qrcode:before{content:"\f029"}.fa-question:before{content:"\3f"}.fa-quote-left-alt:before,.fa-quote-left:before{content:"\f10d"}.fa-quote-right-alt:before,.fa-quote-right:before{content:"\f10e"}.fa-r:before{content:"\52"}.fa-radiation:before{content:"\f7b9"}.fa-rainbow:before{content:"\f75b"}.fa-receipt:before{content:"\f543"}.fa-record-vinyl:before{content:"\f8d9"}.fa-ad:before,.fa-rectangle-ad:before{content:"\f641"}.fa-list-alt:before,.fa-rectangle-list:before{content:"\f022"}.fa-rectangle-times:before,.fa-rectangle-xmark:before,.fa-times-rectangle:before,.fa-window-close:before{content:"\f410"}.fa-recycle:before{content:"\f1b8"}.fa-registered:before{content:"\f25d"}.fa-repeat:before{content:"\f363"}.fa-mail-reply:before,.fa-reply:before{content:"\f3e5"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-republican:before{content:"\f75e"}.fa-restroom:before{content:"\f7bd"}.fa-retweet:before{content:"\f079"}.fa-ribbon:before{content:"\f4d6"}.fa-right-from-bracket:before,.fa-sign-out-alt:before{content:"\f2f5"}.fa-exchange-alt:before,.fa-right-left:before{content:"\f362"}.fa-long-arrow-alt-right:before,.fa-right-long:before{content:"\f30b"}.fa-right-to-bracket:before,.fa-sign-in-alt:before{content:"\f2f6"}.fa-ring:before{content:"\f70b"}.fa-road:before{content:"\f018"}.fa-robot:before{content:"\f544"}.fa-rocket:before{content:"\f135"}.fa-rotate:before,.fa-sync-alt:before{content:"\f2f1"}.fa-rotate-back:before,.fa-rotate-backward:before,.fa-rotate-left:before,.fa-undo-alt:before{content:"\f2ea"}.fa-redo-alt:before,.fa-rotate-forward:before,.fa-rotate-right:before{content:"\f2f9"}.fa-route:before{content:"\f4d7"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-rouble:before,.fa-rub:before,.fa-ruble-sign:before,.fa-ruble:before{content:"\f158"}.fa-ruler:before{content:"\f545"}.fa-ruler-combined:before{content:"\f546"}.fa-ruler-horizontal:before{content:"\f547"}.fa-ruler-vertical:before{content:"\f548"}.fa-rupee-sign:before,.fa-rupee:before{content:"\f156"}.fa-rupiah-sign:before{content:"\e23d"}.fa-s:before{content:"\53"}.fa-sailboat:before{content:"\e445"}.fa-satellite:before{content:"\f7bf"}.fa-satellite-dish:before{content:"\f7c0"}.fa-balance-scale:before,.fa-scale-balanced:before{content:"\f24e"}.fa-balance-scale-left:before,.fa-scale-unbalanced:before{content:"\f515"}.fa-balance-scale-right:before,.fa-scale-unbalanced-flip:before{content:"\f516"}.fa-school:before{content:"\f549"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-screwdriver:before{content:"\f54a"}.fa-screwdriver-wrench:before,.fa-tools:before{content:"\f7d9"}.fa-scroll:before{content:"\f70e"}.fa-scroll-torah:before,.fa-torah:before{content:"\f6a0"}.fa-sd-card:before{content:"\f7c2"}.fa-section:before{content:"\e447"}.fa-seedling:before,.fa-sprout:before{content:"\f4d8"}.fa-server:before{content:"\f233"}.fa-shapes:before,.fa-triangle-circle-square:before{content:"\f61f"}.fa-arrow-turn-right:before,.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-share-from-square:before,.fa-share-square:before{content:"\f14d"}.fa-share-alt:before,.fa-share-nodes:before{content:"\f1e0"}.fa-ils:before,.fa-shekel-sign:before,.fa-shekel:before,.fa-sheqel-sign:before,.fa-sheqel:before{content:"\f20b"}.fa-shield:before{content:"\f132"}.fa-shield-alt:before,.fa-shield-blank:before{content:"\f3ed"}.fa-shield-virus:before{content:"\e06c"}.fa-ship:before{content:"\f21a"}.fa-shirt:before,.fa-t-shirt:before,.fa-tshirt:before{content:"\f553"}.fa-shoe-prints:before{content:"\f54b"}.fa-shop:before,.fa-store-alt:before{content:"\f54f"}.fa-shop-slash:before,.fa-store-alt-slash:before{content:"\e070"}.fa-shower:before{content:"\f2cc"}.fa-shrimp:before{content:"\e448"}.fa-random:before,.fa-shuffle:before{content:"\f074"}.fa-shuttle-space:before,.fa-space-shuttle:before{content:"\f197"}.fa-sign-hanging:before,.fa-sign:before{content:"\f4d9"}.fa-signal-5:before,.fa-signal-perfect:before,.fa-signal:before{content:"\f012"}.fa-signature:before{content:"\f5b7"}.fa-map-signs:before,.fa-signs-post:before{content:"\f277"}.fa-sim-card:before{content:"\f7c4"}.fa-sink:before{content:"\e06d"}.fa-sitemap:before{content:"\f0e8"}.fa-skull:before{content:"\f54c"}.fa-skull-crossbones:before{content:"\f714"}.fa-slash:before{content:"\f715"}.fa-sleigh:before{content:"\f7cc"}.fa-sliders-h:before,.fa-sliders:before{content:"\f1de"}.fa-smog:before{content:"\f75f"}.fa-smoking:before{content:"\f48d"}.fa-snowflake:before{content:"\f2dc"}.fa-snowman:before{content:"\f7d0"}.fa-snowplow:before{content:"\f7d2"}.fa-soap:before{content:"\e06e"}.fa-socks:before{content:"\f696"}.fa-solar-panel:before{content:"\f5ba"}.fa-sort:before,.fa-unsorted:before{content:"\f0dc"}.fa-sort-desc:before,.fa-sort-down:before{content:"\f0dd"}.fa-sort-asc:before,.fa-sort-up:before{content:"\f0de"}.fa-spa:before{content:"\f5bb"}.fa-pastafarianism:before,.fa-spaghetti-monster-flying:before{content:"\f67b"}.fa-spell-check:before{content:"\f891"}.fa-spider:before{content:"\f717"}.fa-spinner:before{content:"\f110"}.fa-splotch:before{content:"\f5bc"}.fa-spoon:before,.fa-utensil-spoon:before{content:"\f2e5"}.fa-spray-can:before{content:"\f5bd"}.fa-air-freshener:before,.fa-spray-can-sparkles:before{content:"\f5d0"}.fa-square:before{content:"\f0c8"}.fa-external-link-square:before,.fa-square-arrow-up-right:before{content:"\f14c"}.fa-caret-square-down:before,.fa-square-caret-down:before{content:"\f150"}.fa-caret-square-left:before,.fa-square-caret-left:before{content:"\f191"}.fa-caret-square-right:before,.fa-square-caret-right:before{content:"\f152"}.fa-caret-square-up:before,.fa-square-caret-up:before{content:"\f151"}.fa-check-square:before,.fa-square-check:before{content:"\f14a"}.fa-envelope-square:before,.fa-square-envelope:before{content:"\f199"}.fa-square-full:before{content:"\f45c"}.fa-h-square:before,.fa-square-h:before{content:"\f0fd"}.fa-minus-square:before,.fa-square-minus:before{content:"\f146"}.fa-parking:before,.fa-square-parking:before{content:"\f540"}.fa-pen-square:before,.fa-pencil-square:before,.fa-square-pen:before{content:"\f14b"}.fa-phone-square:before,.fa-square-phone:before{content:"\f098"}.fa-phone-square-alt:before,.fa-square-phone-flip:before{content:"\f87b"}.fa-plus-square:before,.fa-square-plus:before{content:"\f0fe"}.fa-poll-h:before,.fa-square-poll-horizontal:before{content:"\f682"}.fa-poll:before,.fa-square-poll-vertical:before{content:"\f681"}.fa-square-root-alt:before,.fa-square-root-variable:before{content:"\f698"}.fa-rss-square:before,.fa-square-rss:before{content:"\f143"}.fa-share-alt-square:before,.fa-square-share-nodes:before{content:"\f1e1"}.fa-external-link-square-alt:before,.fa-square-up-right:before{content:"\f360"}.fa-square-xmark:before,.fa-times-square:before,.fa-xmark-square:before{content:"\f2d3"}.fa-stairs:before{content:"\e289"}.fa-stamp:before{content:"\f5bf"}.fa-star:before{content:"\f005"}.fa-star-and-crescent:before{content:"\f699"}.fa-star-half:before{content:"\f089"}.fa-star-half-alt:before,.fa-star-half-stroke:before{content:"\f5c0"}.fa-star-of-david:before{content:"\f69a"}.fa-star-of-life:before{content:"\f621"}.fa-gbp:before,.fa-pound-sign:before,.fa-sterling-sign:before{content:"\f154"}.fa-stethoscope:before{content:"\f0f1"}.fa-stop:before{content:"\f04d"}.fa-stopwatch:before{content:"\f2f2"}.fa-stopwatch-20:before{content:"\e06f"}.fa-store:before{content:"\f54e"}.fa-store-slash:before{content:"\e071"}.fa-street-view:before{content:"\f21d"}.fa-strikethrough:before{content:"\f0cc"}.fa-stroopwafel:before{content:"\f551"}.fa-subscript:before{content:"\f12c"}.fa-suitcase:before{content:"\f0f2"}.fa-medkit:before,.fa-suitcase-medical:before{content:"\f0fa"}.fa-suitcase-rolling:before{content:"\f5c1"}.fa-sun:before{content:"\f185"}.fa-superscript:before{content:"\f12b"}.fa-swatchbook:before{content:"\f5c3"}.fa-synagogue:before{content:"\f69b"}.fa-syringe:before{content:"\f48e"}.fa-t:before{content:"\54"}.fa-table:before{content:"\f0ce"}.fa-table-cells:before,.fa-th:before{content:"\f00a"}.fa-table-cells-large:before,.fa-th-large:before{content:"\f009"}.fa-columns:before,.fa-table-columns:before{content:"\f0db"}.fa-table-list:before,.fa-th-list:before{content:"\f00b"}.fa-ping-pong-paddle-ball:before,.fa-table-tennis-paddle-ball:before,.fa-table-tennis:before{content:"\f45d"}.fa-tablet-android:before,.fa-tablet:before{content:"\f3fb"}.fa-tablet-button:before{content:"\f10a"}.fa-tablet-alt:before,.fa-tablet-screen-button:before{content:"\f3fa"}.fa-tablets:before{content:"\f490"}.fa-digital-tachograph:before,.fa-tachograph-digital:before{content:"\f566"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-tape:before{content:"\f4db"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-teeth:before{content:"\f62e"}.fa-teeth-open:before{content:"\f62f"}.fa-temperature-0:before,.fa-temperature-empty:before,.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-temperature-4:before,.fa-temperature-full:before,.fa-thermometer-4:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-temperature-2:before,.fa-temperature-half:before,.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-temperature-high:before{content:"\f769"}.fa-temperature-low:before{content:"\f76b"}.fa-temperature-1:before,.fa-temperature-quarter:before,.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-temperature-3:before,.fa-temperature-three-quarters:before,.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-tenge-sign:before,.fa-tenge:before{content:"\f7d7"}.fa-terminal:before{content:"\f120"}.fa-text-height:before{content:"\f034"}.fa-remove-format:before,.fa-text-slash:before{content:"\f87d"}.fa-text-width:before{content:"\f035"}.fa-thermometer:before{content:"\f491"}.fa-thumbs-down:before{content:"\f165"}.fa-thumbs-up:before{content:"\f164"}.fa-thumb-tack:before,.fa-thumbtack:before{content:"\f08d"}.fa-ticket:before{content:"\f145"}.fa-ticket-alt:before,.fa-ticket-simple:before{content:"\f3ff"}.fa-timeline:before{content:"\e29c"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-toilet:before{content:"\f7d8"}.fa-toilet-paper:before{content:"\f71e"}.fa-toilet-paper-slash:before{content:"\e072"}.fa-toolbox:before{content:"\f552"}.fa-tooth:before{content:"\f5c9"}.fa-torii-gate:before{content:"\f6a1"}.fa-broadcast-tower:before,.fa-tower-broadcast:before{content:"\f519"}.fa-tractor:before{content:"\f722"}.fa-trademark:before{content:"\f25c"}.fa-traffic-light:before{content:"\f637"}.fa-trailer:before{content:"\e041"}.fa-train:before{content:"\f238"}.fa-subway:before,.fa-train-subway:before{content:"\f239"}.fa-train-tram:before,.fa-tram:before{content:"\f7da"}.fa-transgender-alt:before,.fa-transgender:before{content:"\f225"}.fa-trash:before{content:"\f1f8"}.fa-trash-arrow-up:before,.fa-trash-restore:before{content:"\f829"}.fa-trash-alt:before,.fa-trash-can:before{content:"\f2ed"}.fa-trash-can-arrow-up:before,.fa-trash-restore-alt:before{content:"\f82a"}.fa-tree:before{content:"\f1bb"}.fa-exclamation-triangle:before,.fa-triangle-exclamation:before,.fa-warning:before{content:"\f071"}.fa-trophy:before{content:"\f091"}.fa-truck:before{content:"\f0d1"}.fa-shipping-fast:before,.fa-truck-fast:before{content:"\f48b"}.fa-ambulance:before,.fa-truck-medical:before{content:"\f0f9"}.fa-truck-monster:before{content:"\f63b"}.fa-truck-moving:before{content:"\f4df"}.fa-truck-pickup:before{content:"\f63c"}.fa-truck-loading:before,.fa-truck-ramp-box:before{content:"\f4de"}.fa-teletype:before,.fa-tty:before{content:"\f1e4"}.fa-try:before,.fa-turkish-lira-sign:before,.fa-turkish-lira:before{content:"\e2bb"}.fa-level-down-alt:before,.fa-turn-down:before{content:"\f3be"}.fa-level-up-alt:before,.fa-turn-up:before{content:"\f3bf"}.fa-television:before,.fa-tv-alt:before,.fa-tv:before{content:"\f26c"}.fa-u:before{content:"\55"}.fa-umbrella:before{content:"\f0e9"}.fa-umbrella-beach:before{content:"\f5ca"}.fa-underline:before{content:"\f0cd"}.fa-universal-access:before{content:"\f29a"}.fa-unlock:before{content:"\f09c"}.fa-unlock-alt:before,.fa-unlock-keyhole:before{content:"\f13e"}.fa-arrows-alt-v:before,.fa-up-down:before{content:"\f338"}.fa-arrows-alt:before,.fa-up-down-left-right:before{content:"\f0b2"}.fa-long-arrow-alt-up:before,.fa-up-long:before{content:"\f30c"}.fa-expand-alt:before,.fa-up-right-and-down-left-from-center:before{content:"\f424"}.fa-external-link-alt:before,.fa-up-right-from-square:before{content:"\f35d"}.fa-upload:before{content:"\f093"}.fa-user:before{content:"\f007"}.fa-user-astronaut:before{content:"\f4fb"}.fa-user-check:before{content:"\f4fc"}.fa-user-clock:before{content:"\f4fd"}.fa-user-doctor:before,.fa-user-md:before{content:"\f0f0"}.fa-user-cog:before,.fa-user-gear:before{content:"\f4fe"}.fa-user-graduate:before{content:"\f501"}.fa-user-friends:before,.fa-user-group:before{content:"\f500"}.fa-user-injured:before{content:"\f728"}.fa-user-alt:before,.fa-user-large:before{content:"\f406"}.fa-user-alt-slash:before,.fa-user-large-slash:before{content:"\f4fa"}.fa-user-lock:before{content:"\f502"}.fa-user-minus:before{content:"\f503"}.fa-user-ninja:before{content:"\f504"}.fa-user-nurse:before{content:"\f82f"}.fa-user-edit:before,.fa-user-pen:before{content:"\f4ff"}.fa-user-plus:before{content:"\f234"}.fa-user-secret:before{content:"\f21b"}.fa-user-shield:before{content:"\f505"}.fa-user-slash:before{content:"\f506"}.fa-user-tag:before{content:"\f507"}.fa-user-tie:before{content:"\f508"}.fa-user-times:before,.fa-user-xmark:before{content:"\f235"}.fa-users:before{content:"\f0c0"}.fa-users-cog:before,.fa-users-gear:before{content:"\f509"}.fa-users-slash:before{content:"\e073"}.fa-cutlery:before,.fa-utensils:before{content:"\f2e7"}.fa-v:before{content:"\56"}.fa-shuttle-van:before,.fa-van-shuttle:before{content:"\f5b6"}.fa-vault:before{content:"\e2c5"}.fa-vector-square:before{content:"\f5cb"}.fa-venus:before{content:"\f221"}.fa-venus-double:before{content:"\f226"}.fa-venus-mars:before{content:"\f228"}.fa-vest:before{content:"\e085"}.fa-vest-patches:before{content:"\e086"}.fa-vial:before{content:"\f492"}.fa-vials:before{content:"\f493"}.fa-video-camera:before,.fa-video:before{content:"\f03d"}.fa-video-slash:before{content:"\f4e2"}.fa-vihara:before{content:"\f6a7"}.fa-virus:before{content:"\e074"}.fa-virus-covid:before{content:"\e4a8"}.fa-virus-covid-slash:before{content:"\e4a9"}.fa-virus-slash:before{content:"\e075"}.fa-viruses:before{content:"\e076"}.fa-voicemail:before{content:"\f897"}.fa-volleyball-ball:before,.fa-volleyball:before{content:"\f45f"}.fa-volume-high:before,.fa-volume-up:before{content:"\f028"}.fa-volume-down:before,.fa-volume-low:before{content:"\f027"}.fa-volume-off:before{content:"\f026"}.fa-volume-mute:before,.fa-volume-times:before,.fa-volume-xmark:before{content:"\f6a9"}.fa-vr-cardboard:before{content:"\f729"}.fa-w:before{content:"\57"}.fa-wallet:before{content:"\f555"}.fa-magic:before,.fa-wand-magic:before{content:"\f0d0"}.fa-magic-wand-sparkles:before,.fa-wand-magic-sparkles:before{content:"\e2ca"}.fa-wand-sparkles:before{content:"\f72b"}.fa-warehouse:before{content:"\f494"}.fa-water:before{content:"\f773"}.fa-ladder-water:before,.fa-swimming-pool:before,.fa-water-ladder:before{content:"\f5c5"}.fa-wave-square:before{content:"\f83e"}.fa-weight-hanging:before{content:"\f5cd"}.fa-weight-scale:before,.fa-weight:before{content:"\f496"}.fa-wheelchair:before{content:"\f193"}.fa-glass-whiskey:before,.fa-whiskey-glass:before{content:"\f7a0"}.fa-wifi-3:before,.fa-wifi-strong:before,.fa-wifi:before{content:"\f1eb"}.fa-wind:before{content:"\f72e"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-wine-bottle:before{content:"\f72f"}.fa-wine-glass:before{content:"\f4e3"}.fa-wine-glass-alt:before,.fa-wine-glass-empty:before{content:"\f5ce"}.fa-krw:before,.fa-won-sign:before,.fa-won:before{content:"\f159"}.fa-wrench:before{content:"\f0ad"}.fa-x:before{content:"\58"}.fa-x-ray:before{content:"\f497"}.fa-close:before,.fa-multiply:before,.fa-remove:before,.fa-times:before,.fa-xmark:before{content:"\f00d"}.fa-y:before{content:"\59"}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen-sign:before,.fa-yen:before{content:"\f157"}.fa-yin-yang:before{content:"\f6ad"}.fa-z:before{content:"\5a"}.fa-sr-only,.fa-sr-only-focusable:not(:focus),.sr-only,.sr-only-focusable:not(:focus){position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}:host,:root{--fa-font-brands:normal 400 1em/1 "Font Awesome 6 Brands"}@font-face{font-family:"Font Awesome 6 Brands";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.ttf) format("truetype")}.fa-brands,.fab{font-family:"Font Awesome 6 Brands";font-weight:400}.fa-42-group:before,.fa-innosoft:before{content:"\e080"}.fa-500px:before{content:"\f26e"}.fa-accessible-icon:before{content:"\f368"}.fa-accusoft:before{content:"\f369"}.fa-adn:before{content:"\f170"}.fa-adversal:before{content:"\f36a"}.fa-affiliatetheme:before{content:"\f36b"}.fa-airbnb:before{content:"\f834"}.fa-algolia:before{content:"\f36c"}.fa-alipay:before{content:"\f642"}.fa-amazon:before{content:"\f270"}.fa-amazon-pay:before{content:"\f42c"}.fa-amilia:before{content:"\f36d"}.fa-android:before{content:"\f17b"}.fa-angellist:before{content:"\f209"}.fa-angrycreative:before{content:"\f36e"}.fa-angular:before{content:"\f420"}.fa-app-store:before{content:"\f36f"}.fa-app-store-ios:before{content:"\f370"}.fa-apper:before{content:"\f371"}.fa-apple:before{content:"\f179"}.fa-apple-pay:before{content:"\f415"}.fa-artstation:before{content:"\f77a"}.fa-asymmetrik:before{content:"\f372"}.fa-atlassian:before{content:"\f77b"}.fa-audible:before{content:"\f373"}.fa-autoprefixer:before{content:"\f41c"}.fa-avianex:before{content:"\f374"}.fa-aviato:before{content:"\f421"}.fa-aws:before{content:"\f375"}.fa-bandcamp:before{content:"\f2d5"}.fa-battle-net:before{content:"\f835"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-bilibili:before{content:"\e3d9"}.fa-bimobject:before{content:"\f378"}.fa-bitbucket:before{content:"\f171"}.fa-bitcoin:before{content:"\f379"}.fa-bity:before{content:"\f37a"}.fa-black-tie:before{content:"\f27e"}.fa-blackberry:before{content:"\f37b"}.fa-blogger:before{content:"\f37c"}.fa-blogger-b:before{content:"\f37d"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-bootstrap:before{content:"\f836"}.fa-bots:before{content:"\e340"}.fa-btc:before{content:"\f15a"}.fa-buffer:before{content:"\f837"}.fa-buromobelexperte:before{content:"\f37f"}.fa-buy-n-large:before{content:"\f8a6"}.fa-buysellads:before{content:"\f20d"}.fa-canadian-maple-leaf:before{content:"\f785"}.fa-cc-amazon-pay:before{content:"\f42d"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-apple-pay:before{content:"\f416"}.fa-cc-diners-club:before{content:"\f24c"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-cc-visa:before{content:"\f1f0"}.fa-centercode:before{content:"\f380"}.fa-centos:before{content:"\f789"}.fa-chrome:before{content:"\f268"}.fa-chromecast:before{content:"\f838"}.fa-cloudflare:before{content:"\e07d"}.fa-cloudscale:before{content:"\f383"}.fa-cloudsmith:before{content:"\f384"}.fa-cloudversify:before{content:"\f385"}.fa-cmplid:before{content:"\e360"}.fa-codepen:before{content:"\f1cb"}.fa-codiepie:before{content:"\f284"}.fa-confluence:before{content:"\f78d"}.fa-connectdevelop:before{content:"\f20e"}.fa-contao:before{content:"\f26d"}.fa-cotton-bureau:before{content:"\f89e"}.fa-cpanel:before{content:"\f388"}.fa-creative-commons:before{content:"\f25e"}.fa-creative-commons-by:before{content:"\f4e7"}.fa-creative-commons-nc:before{content:"\f4e8"}.fa-creative-commons-nc-eu:before{content:"\f4e9"}.fa-creative-commons-nc-jp:before{content:"\f4ea"}.fa-creative-commons-nd:before{content:"\f4eb"}.fa-creative-commons-pd:before{content:"\f4ec"}.fa-creative-commons-pd-alt:before{content:"\f4ed"}.fa-creative-commons-remix:before{content:"\f4ee"}.fa-creative-commons-sa:before{content:"\f4ef"}.fa-creative-commons-sampling:before{content:"\f4f0"}.fa-creative-commons-sampling-plus:before{content:"\f4f1"}.fa-creative-commons-share:before{content:"\f4f2"}.fa-creative-commons-zero:before{content:"\f4f3"}.fa-critical-role:before{content:"\f6c9"}.fa-css3:before{content:"\f13c"}.fa-css3-alt:before{content:"\f38b"}.fa-cuttlefish:before{content:"\f38c"}.fa-d-and-d:before{content:"\f38d"}.fa-d-and-d-beyond:before{content:"\f6ca"}.fa-dailymotion:before{content:"\e052"}.fa-dashcube:before{content:"\f210"}.fa-deezer:before{content:"\e077"}.fa-delicious:before{content:"\f1a5"}.fa-deploydog:before{content:"\f38e"}.fa-deskpro:before{content:"\f38f"}.fa-dev:before{content:"\f6cc"}.fa-deviantart:before{content:"\f1bd"}.fa-dhl:before{content:"\f790"}.fa-diaspora:before{content:"\f791"}.fa-digg:before{content:"\f1a6"}.fa-digital-ocean:before{content:"\f391"}.fa-discord:before{content:"\f392"}.fa-discourse:before{content:"\f393"}.fa-dochub:before{content:"\f394"}.fa-docker:before{content:"\f395"}.fa-draft2digital:before{content:"\f396"}.fa-dribbble:before{content:"\f17d"}.fa-dribbble-square:before{content:"\f397"}.fa-dropbox:before{content:"\f16b"}.fa-drupal:before{content:"\f1a9"}.fa-dyalog:before{content:"\f399"}.fa-earlybirds:before{content:"\f39a"}.fa-ebay:before{content:"\f4f4"}.fa-edge:before{content:"\f282"}.fa-edge-legacy:before{content:"\e078"}.fa-elementor:before{content:"\f430"}.fa-ello:before{content:"\f5f1"}.fa-ember:before{content:"\f423"}.fa-empire:before{content:"\f1d1"}.fa-envira:before{content:"\f299"}.fa-erlang:before{content:"\f39d"}.fa-ethereum:before{content:"\f42e"}.fa-etsy:before{content:"\f2d7"}.fa-evernote:before{content:"\f839"}.fa-expeditedssl:before{content:"\f23e"}.fa-facebook:before{content:"\f09a"}.fa-facebook-f:before{content:"\f39e"}.fa-facebook-messenger:before{content:"\f39f"}.fa-facebook-square:before{content:"\f082"}.fa-fantasy-flight-games:before{content:"\f6dc"}.fa-fedex:before{content:"\f797"}.fa-fedora:before{content:"\f798"}.fa-figma:before{content:"\f799"}.fa-firefox:before{content:"\f269"}.fa-firefox-browser:before{content:"\e007"}.fa-first-order:before{content:"\f2b0"}.fa-first-order-alt:before{content:"\f50a"}.fa-firstdraft:before{content:"\f3a1"}.fa-flickr:before{content:"\f16e"}.fa-flipboard:before{content:"\f44d"}.fa-fly:before{content:"\f417"}.fa-font-awesome-flag:before,.fa-font-awesome-logo-full:before,.fa-font-awesome:before{content:"\f2b4"}.fa-fonticons:before{content:"\f280"}.fa-fonticons-fi:before{content:"\f3a2"}.fa-fort-awesome:before{content:"\f286"}.fa-fort-awesome-alt:before{content:"\f3a3"}.fa-forumbee:before{content:"\f211"}.fa-foursquare:before{content:"\f180"}.fa-free-code-camp:before{content:"\f2c5"}.fa-freebsd:before{content:"\f3a4"}.fa-fulcrum:before{content:"\f50b"}.fa-galactic-republic:before{content:"\f50c"}.fa-galactic-senate:before{content:"\f50d"}.fa-get-pocket:before{content:"\f265"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-git:before{content:"\f1d3"}.fa-git-alt:before{content:"\f841"}.fa-git-square:before{content:"\f1d2"}.fa-github:before{content:"\f09b"}.fa-github-alt:before{content:"\f113"}.fa-github-square:before{content:"\f092"}.fa-gitkraken:before{content:"\f3a6"}.fa-gitlab:before{content:"\f296"}.fa-gitter:before{content:"\f426"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-gofore:before{content:"\f3a7"}.fa-golang:before{content:"\e40f"}.fa-goodreads:before{content:"\f3a8"}.fa-goodreads-g:before{content:"\f3a9"}.fa-google:before{content:"\f1a0"}.fa-google-drive:before{content:"\f3aa"}.fa-google-pay:before{content:"\e079"}.fa-google-play:before{content:"\f3ab"}.fa-google-plus:before{content:"\f2b3"}.fa-google-plus-g:before{content:"\f0d5"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-wallet:before{content:"\f1ee"}.fa-gratipay:before{content:"\f184"}.fa-grav:before{content:"\f2d6"}.fa-gripfire:before{content:"\f3ac"}.fa-grunt:before{content:"\f3ad"}.fa-guilded:before{content:"\e07e"}.fa-gulp:before{content:"\f3ae"}.fa-hacker-news:before{content:"\f1d4"}.fa-hacker-news-square:before{content:"\f3af"}.fa-hackerrank:before{content:"\f5f7"}.fa-hashnode:before{content:"\e499"}.fa-hips:before{content:"\f452"}.fa-hire-a-helper:before{content:"\f3b0"}.fa-hive:before{content:"\e07f"}.fa-hooli:before{content:"\f427"}.fa-hornbill:before{content:"\f592"}.fa-hotjar:before{content:"\f3b1"}.fa-houzz:before{content:"\f27c"}.fa-html5:before{content:"\f13b"}.fa-hubspot:before{content:"\f3b2"}.fa-ideal:before{content:"\e013"}.fa-imdb:before{content:"\f2d8"}.fa-instagram:before{content:"\f16d"}.fa-instagram-square:before{content:"\e055"}.fa-instalod:before{content:"\e081"}.fa-intercom:before{content:"\f7af"}.fa-internet-explorer:before{content:"\f26b"}.fa-invision:before{content:"\f7b0"}.fa-ioxhost:before{content:"\f208"}.fa-itch-io:before{content:"\f83a"}.fa-itunes:before{content:"\f3b4"}.fa-itunes-note:before{content:"\f3b5"}.fa-java:before{content:"\f4e4"}.fa-jedi-order:before{content:"\f50e"}.fa-jenkins:before{content:"\f3b6"}.fa-jira:before{content:"\f7b1"}.fa-joget:before{content:"\f3b7"}.fa-joomla:before{content:"\f1aa"}.fa-js:before{content:"\f3b8"}.fa-js-square:before{content:"\f3b9"}.fa-jsfiddle:before{content:"\f1cc"}.fa-kaggle:before{content:"\f5fa"}.fa-keybase:before{content:"\f4f5"}.fa-keycdn:before{content:"\f3ba"}.fa-kickstarter:before{content:"\f3bb"}.fa-kickstarter-k:before{content:"\f3bc"}.fa-korvue:before{content:"\f42f"}.fa-laravel:before{content:"\f3bd"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-leanpub:before{content:"\f212"}.fa-less:before{content:"\f41d"}.fa-line:before{content:"\f3c0"}.fa-linkedin:before{content:"\f08c"}.fa-linkedin-in:before{content:"\f0e1"}.fa-linode:before{content:"\f2b8"}.fa-linux:before{content:"\f17c"}.fa-lyft:before{content:"\f3c3"}.fa-magento:before{content:"\f3c4"}.fa-mailchimp:before{content:"\f59e"}.fa-mandalorian:before{content:"\f50f"}.fa-markdown:before{content:"\f60f"}.fa-mastodon:before{content:"\f4f6"}.fa-maxcdn:before{content:"\f136"}.fa-mdb:before{content:"\f8ca"}.fa-medapps:before{content:"\f3c6"}.fa-medium-m:before,.fa-medium:before{content:"\f23a"}.fa-medrt:before{content:"\f3c8"}.fa-meetup:before{content:"\f2e0"}.fa-megaport:before{content:"\f5a3"}.fa-mendeley:before{content:"\f7b3"}.fa-microblog:before{content:"\e01a"}.fa-microsoft:before{content:"\f3ca"}.fa-mix:before{content:"\f3cb"}.fa-mixcloud:before{content:"\f289"}.fa-mixer:before{content:"\e056"}.fa-mizuni:before{content:"\f3cc"}.fa-modx:before{content:"\f285"}.fa-monero:before{content:"\f3d0"}.fa-napster:before{content:"\f3d2"}.fa-neos:before{content:"\f612"}.fa-nimblr:before{content:"\f5a8"}.fa-node:before{content:"\f419"}.fa-node-js:before{content:"\f3d3"}.fa-npm:before{content:"\f3d4"}.fa-ns8:before{content:"\f3d5"}.fa-nutritionix:before{content:"\f3d6"}.fa-octopus-deploy:before{content:"\e082"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-old-republic:before{content:"\f510"}.fa-opencart:before{content:"\f23d"}.fa-openid:before{content:"\f19b"}.fa-opera:before{content:"\f26a"}.fa-optin-monster:before{content:"\f23c"}.fa-orcid:before{content:"\f8d2"}.fa-osi:before{content:"\f41a"}.fa-padlet:before{content:"\e4a0"}.fa-page4:before{content:"\f3d7"}.fa-pagelines:before{content:"\f18c"}.fa-palfed:before{content:"\f3d8"}.fa-patreon:before{content:"\f3d9"}.fa-paypal:before{content:"\f1ed"}.fa-perbyte:before{content:"\e083"}.fa-periscope:before{content:"\f3da"}.fa-phabricator:before{content:"\f3db"}.fa-phoenix-framework:before{content:"\f3dc"}.fa-phoenix-squadron:before{content:"\f511"}.fa-php:before{content:"\f457"}.fa-pied-piper:before{content:"\f2ae"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-pied-piper-hat:before{content:"\f4e5"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-square:before{content:"\e01e"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-p:before{content:"\f231"}.fa-pinterest-square:before{content:"\f0d3"}.fa-pix:before{content:"\e43a"}.fa-playstation:before{content:"\f3df"}.fa-product-hunt:before{content:"\f288"}.fa-pushed:before{content:"\f3e1"}.fa-python:before{content:"\f3e2"}.fa-qq:before{content:"\f1d6"}.fa-quinscape:before{content:"\f459"}.fa-quora:before{content:"\f2c4"}.fa-r-project:before{content:"\f4f7"}.fa-raspberry-pi:before{content:"\f7bb"}.fa-ravelry:before{content:"\f2d9"}.fa-react:before{content:"\f41b"}.fa-reacteurope:before{content:"\f75d"}.fa-readme:before{content:"\f4d5"}.fa-rebel:before{content:"\f1d0"}.fa-red-river:before{content:"\f3e3"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-alien:before{content:"\f281"}.fa-reddit-square:before{content:"\f1a2"}.fa-redhat:before{content:"\f7bc"}.fa-renren:before{content:"\f18b"}.fa-replyd:before{content:"\f3e6"}.fa-researchgate:before{content:"\f4f8"}.fa-resolving:before{content:"\f3e7"}.fa-rev:before{content:"\f5b2"}.fa-rocketchat:before{content:"\f3e8"}.fa-rockrms:before{content:"\f3e9"}.fa-rust:before{content:"\e07a"}.fa-safari:before{content:"\f267"}.fa-salesforce:before{content:"\f83b"}.fa-sass:before{content:"\f41e"}.fa-schlix:before{content:"\f3ea"}.fa-scribd:before{content:"\f28a"}.fa-searchengin:before{content:"\f3eb"}.fa-sellcast:before{content:"\f2da"}.fa-sellsy:before{content:"\f213"}.fa-servicestack:before{content:"\f3ec"}.fa-shirtsinbulk:before{content:"\f214"}.fa-shopify:before{content:"\e057"}.fa-shopware:before{content:"\f5b5"}.fa-simplybuilt:before{content:"\f215"}.fa-sistrix:before{content:"\f3ee"}.fa-sith:before{content:"\f512"}.fa-sitrox:before{content:"\e44a"}.fa-sketch:before{content:"\f7c6"}.fa-skyatlas:before{content:"\f216"}.fa-skype:before{content:"\f17e"}.fa-slack-hash:before,.fa-slack:before{content:"\f198"}.fa-slideshare:before{content:"\f1e7"}.fa-snapchat-ghost:before,.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-square:before{content:"\f2ad"}.fa-soundcloud:before{content:"\f1be"}.fa-sourcetree:before{content:"\f7d3"}.fa-speakap:before{content:"\f3f3"}.fa-speaker-deck:before{content:"\f83c"}.fa-spotify:before{content:"\f1bc"}.fa-square-font-awesome:before{content:"\f425"}.fa-font-awesome-alt:before,.fa-square-font-awesome-stroke:before{content:"\f35c"}.fa-squarespace:before{content:"\f5be"}.fa-stack-exchange:before{content:"\f18d"}.fa-stack-overflow:before{content:"\f16c"}.fa-stackpath:before{content:"\f842"}.fa-staylinked:before{content:"\f3f5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-steam-symbol:before{content:"\f3f6"}.fa-sticker-mule:before{content:"\f3f7"}.fa-strava:before{content:"\f428"}.fa-stripe:before{content:"\f429"}.fa-stripe-s:before{content:"\f42a"}.fa-studiovinari:before{content:"\f3f8"}.fa-stumbleupon:before{content:"\f1a4"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-superpowers:before{content:"\f2dd"}.fa-supple:before{content:"\f3f9"}.fa-suse:before{content:"\f7d6"}.fa-swift:before{content:"\f8e1"}.fa-symfony:before{content:"\f83d"}.fa-teamspeak:before{content:"\f4f9"}.fa-telegram-plane:before,.fa-telegram:before{content:"\f2c6"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-the-red-yeti:before{content:"\f69d"}.fa-themeco:before{content:"\f5c6"}.fa-themeisle:before{content:"\f2b2"}.fa-think-peaks:before{content:"\f731"}.fa-tiktok:before{content:"\e07b"}.fa-trade-federation:before{content:"\f513"}.fa-trello:before{content:"\f181"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-twitch:before{content:"\f1e8"}.fa-twitter:before{content:"\f099"}.fa-twitter-square:before{content:"\f081"}.fa-typo3:before{content:"\f42b"}.fa-uber:before{content:"\f402"}.fa-ubuntu:before{content:"\f7df"}.fa-uikit:before{content:"\f403"}.fa-umbraco:before{content:"\f8e8"}.fa-uncharted:before{content:"\e084"}.fa-uniregistry:before{content:"\f404"}.fa-unity:before{content:"\e049"}.fa-unsplash:before{content:"\e07c"}.fa-untappd:before{content:"\f405"}.fa-ups:before{content:"\f7e0"}.fa-usb:before{content:"\f287"}.fa-usps:before{content:"\f7e1"}.fa-ussunnah:before{content:"\f407"}.fa-vaadin:before{content:"\f408"}.fa-viacoin:before{content:"\f237"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-viber:before{content:"\f409"}.fa-vimeo:before{content:"\f40a"}.fa-vimeo-square:before{content:"\f194"}.fa-vimeo-v:before{content:"\f27d"}.fa-vine:before{content:"\f1ca"}.fa-vk:before{content:"\f189"}.fa-vnv:before{content:"\f40b"}.fa-vuejs:before{content:"\f41f"}.fa-watchman-monitoring:before{content:"\e087"}.fa-waze:before{content:"\f83f"}.fa-weebly:before{content:"\f5cc"}.fa-weibo:before{content:"\f18a"}.fa-weixin:before{content:"\f1d7"}.fa-whatsapp:before{content:"\f232"}.fa-whatsapp-square:before{content:"\f40c"}.fa-whmcs:before{content:"\f40d"}.fa-wikipedia-w:before{content:"\f266"}.fa-windows:before{content:"\f17a"}.fa-wirsindhandwerk:before,.fa-wsh:before{content:"\e2d0"}.fa-wix:before{content:"\f5cf"}.fa-wizards-of-the-coast:before{content:"\f730"}.fa-wodu:before{content:"\e088"}.fa-wolf-pack-battalion:before{content:"\f514"}.fa-wordpress:before{content:"\f19a"}.fa-wordpress-simple:before{content:"\f411"}.fa-wpbeginner:before{content:"\f297"}.fa-wpexplorer:before{content:"\f2de"}.fa-wpforms:before{content:"\f298"}.fa-wpressr:before{content:"\f3e4"}.fa-xbox:before{content:"\f412"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-y-combinator:before{content:"\f23b"}.fa-yahoo:before{content:"\f19e"}.fa-yammer:before{content:"\f840"}.fa-yandex:before{content:"\f413"}.fa-yandex-international:before{content:"\f414"}.fa-yarn:before{content:"\f7e3"}.fa-yelp:before{content:"\f1e9"}.fa-yoast:before{content:"\f2b1"}.fa-youtube:before{content:"\f167"}.fa-youtube-square:before{content:"\f431"}.fa-zhihu:before{content:"\f63f"}:host,:root{--fa-font-regular:normal 400 1em/1 "Font Awesome 6 Free"}@font-face{font-family:"Font Awesome 6 Free";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype")}.fa-regular,.far{font-family:"Font Awesome 6 Free";font-weight:400}:host,:root{--fa-font-solid:normal 900 1em/1 "Font Awesome 6 Free"}@font-face{font-family:"Font Awesome 6 Free";font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}.fa-solid,.fas{font-family:"Font Awesome 6 Free";font-weight:900}@font-face{font-family:"Font Awesome 5 Brands";font-display:block;font-weight:400;src:url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.ttf) format("truetype")}@font-face{font-family:"Font Awesome 5 Free";font-display:block;font-weight:900;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}@font-face{font-family:"Font Awesome 5 Free";font-display:block;font-weight:400;src:url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype")}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.ttf) format("truetype")}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype");unicode-range:u+f003,u+f006,u+f014,u+f016-f017,u+f01a-f01b,u+f01d,u+f022,u+f03e,u+f044,u+f046,u+f05c-f05d,u+f06e,u+f070,u+f087-f088,u+f08a,u+f094,u+f096-f097,u+f09d,u+f0a0,u+f0a2,u+f0a4-f0a7,u+f0c5,u+f0c7,u+f0e5-f0e6,u+f0eb,u+f0f6-f0f8,u+f10c,u+f114-f115,u+f118-f11a,u+f11c-f11d,u+f133,u+f147,u+f14e,u+f150-f152,u+f185-f186,u+f18e,u+f190-f192,u+f196,u+f1c1-f1c9,u+f1d9,u+f1db,u+f1e3,u+f1ea,u+f1f7,u+f1f9,u+f20a,u+f247-f248,u+f24a,u+f24d,u+f255-f25b,u+f25d,u+f271-f274,u+f278,u+f27b,u+f28c,u+f28e,u+f29c,u+f2b5,u+f2b7,u+f2ba,u+f2bc,u+f2be,u+f2c0-f2c1,u+f2c3,u+f2d0,u+f2d2,u+f2d4,u+f2dc}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-v4compatibility.woff2) format("woff2"),url(../webfonts/fa-v4compatibility.ttf) format("truetype");unicode-range:u+f041,u+f047,u+f065-f066,u+f07d-f07e,u+f080,u+f08b,u+f08e,u+f090,u+f09a,u+f0ac,u+f0ae,u+f0b2,u+f0d0,u+f0d6,u+f0e4,u+f0ec,u+f10a-f10b,u+f123,u+f13e,u+f148-f149,u+f14c,u+f156,u+f15e,u+f160-f161,u+f163,u+f175-f178,u+f195,u+f1f8,u+f219,u+f250,u+f252,u+f27a} diff --git a/src/main/resources/static/css/common.css b/src/main/resources/static/css/common.css new file mode 100644 index 0000000..767e990 --- /dev/null +++ b/src/main/resources/static/css/common.css @@ -0,0 +1,118 @@ +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; + font-family: 'SUIT'; +} +/* HTML5 display-role reset for older browsers */ +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; +} +*{margin:0;padding:0;font-family: 'SUIT';} +*:focus { + outline: none; +} +html, body{/*overflow-y:hidden*/} +body { + line-height: 1; + height: 100%; + margin: 0; + font-family: Nunito,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #858796; + text-align: left; + background-color: #fff; +} +ol, ul { + list-style: none; +} +blockquote, q { + quotes: none; +} +blockquote:before, blockquote:after, +q:before, q:after { + content: ''; + content: none; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +th { + text-align: inherit; + text-align: -webkit-match-parent; +} +th { + display: table-cell; + vertical-align: inherit; + font-weight: bold; + text-align: -internal-center; +} +a {text-decoration: none;} +.flex {display: flex;align-items: center;justify-content: center;} +.wsn {white-space: normal !important;} +.text-gray-300 {color: #dddfeb!important;} +.br0 {border-radius: 0!important;} +.b0 {border: 0!important;} +.bsn {box-shadow: none !important;} +.underbl {color: #4e73df;} +.underbl:hover {text-decoration: underline;} +.text-center {text-align: center;} +.b0 {border: 0 !important;} +.h20 {height: 20px;vertical-align: middle;} +.m0 {margin: 0 !important;} +.mt20 {margin-top: 20px !important;} +.mt10 {margin-top: 10px !important;} +.mr10 {margin-right: 10px;} +.ml10 {margin-left: 10px;} +.mb30 {margin-bottom: 30px !important;} +.mb10 {margin-bottom: 10px !important;} +.mb15 {margin-bottom: 15px !important;} +.pl40 {padding-left: 40px !important;} +.p0 {padding: 0 !important;} +.bl {color: #0494b4;} +.blc {color: #4e73df;} +.rdc {color: #e74a3b;} +.gnc {color: green;} +.ywc {color: #ffc122;} +.sgnc{color: rgb(162, 252, 162);} +.ft08 {font-size: 0.8rem !important;} +.ft2 {font-size: 2rem !important;} +.ft16 {font-size: 16px !important;} +.w45 {width: 45px !important;} +.w100 {width: 100px !important;} +.ha {height: auto !important;} +.jcsb {justify-content: space-between;} +.t70 {top: 70px;} +.wa {width: auto !important;} + +/* SUIT */ +@font-face { + font-family: 'SUIT'; + font-weight: normal; + font-style: normal; + src: url('../fonts/sunn-main/SUIT-Regular.eot'); + src: url('../fonts/sunn-main/SUIT-Regular.eot?#iefix') format('embedded-opentype'), + url('../fonts/sunn-main/SUIT-Regular.woff2') format('woff2'), + url('../fonts/sunn-main/SUIT-Regular.woff') format('woff'), + url('../fonts/sunn-main/SUIT-Regular.ttf') format("truetype"); + font-display: swap; +} diff --git a/src/main/resources/static/css/dev_api_doc.css b/src/main/resources/static/css/dev_api_doc.css new file mode 100644 index 0000000..cab221c --- /dev/null +++ b/src/main/resources/static/css/dev_api_doc.css @@ -0,0 +1,299 @@ +/* http://meyerweb.com/eric/tools/css/reset/ + v2.0 | 20110126 + License: none (public domain) +*/ + +html { + scroll-behavior: smooth; +} + +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} +/* HTML5 display-role reset for older browsers */ +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; +} +body { + margin: 0 auto; + max-width: 1000px; + line-height: 1; + font-family: 'Noto Sans KR', sans-serif; +} +ol, ul { + list-style: none; +} + +a { + color: #000; + text-decoration: none; + font-weight: normal; +} + +/* tab */ + +.tabwrapper { + position: relative; + margin-top: 40px; + background-color: white; + border-radius: 10px; + box-shadow: 0px 5px 15px rgba(0, 0, 0, .1); +} + +.buttonWrapper { + display: grid; + grid-template-columns: 1fr 1fr; + position: absolute; + top: 0px; + left: 5px; +} + +button { + letter-spacing: 3px; + border: none; + padding: 10px; + background-color: #bccbe9; + color: #232c3d; + font-size: 18px; + cursor: pointer; + transition: 0.5s; +} + +button:hover { + background-color: #d5e3ff; +} + +button.activetab { + background-color: white; +} + +.activetab { + background-color: white; +} + +.content { + display: none; +} + +.content.activetab { + display: block; +} + +/***************************************** //tab menu *****************************************/ + +nav { + position: absolute; + left: -300px; +} + +nav ul { + padding-left: 0; + line-height: 1.5; + font-size: 13px; +} + +nav ul li { + list-style: none; +} + +nav ul .li_indent { + margin-left: 20px; +} + +blockquote, q { + quotes: none; +} +blockquote:before, blockquote:after, +q:before, q:after { + content: ''; + content: none; +} +table { + border-collapse: collapse; + border-spacing: 0; +} + +header { + height: 40px; + background-color: #fff; + + position: fixed; + width: 1000px; + top: 0px; + z-index: 100; +} + +header a p { + color: #939393; + font-size: 25px; + line-height: 40px; + font-weight: 900; + text-indent: 20px; + text-align: right; +} + +section { + max-width: 90%; + margin: 0 auto; + padding-bottom: 400px; +} + +h2 { + color: #0b5394; + padding: 70px 20px; + font-size: 50px; + font-weight: bold; +} + +h2 span { + color: #4a86e8; + padding-right: 15px; + font-size: 70px; +} + +h3 { + font-size: 28px; + line-height: 4; + padding-top: 20px; /* 3-1, 3-2 */ +} + +h4 { + margin: 10px 0; + font-size: 20px; + font-weight: 600; +} + +h4 span { + padding-left: 5px; + font-weight: 300; +} + +.headS { + color: #0b5394; + font-size: 23px; +} + +.blankArea { + padding-bottom: 40px; +} + +.dataNpr{ + padding: 10px 20px; + border: 1px solid #ccc; + margin: 20px; +} + +.dataNpr p { + line-height: 1.5; +} +.dataNpr .ft-rd {font-size: 12px;color: red;} + +.apiUrl { + height: 70px; + border-bottom: 1px solid #000; + line-height: 70px; + margin-bottom: 35px; +} + +.apiUrl a{ + color: #0000ee; + text-decoration: underline; +} + +.imgArea { + width: 70%; + margin: 0 auto; +} + +img { + width: 100%; +} + +table { + width: 100%; + border: 1px solid #ccc; +} + +.tableH { + background: #f3f3f3; +} + +td { + width: 30%; + border: 1px solid #ccc; + height: 40px; + line-height: 40px; + text-indent: 10px; +} + +.tableHeader { + margin-bottom: 40px; +} + +.tableHeader tr td:nth-child(1){ + width: 20%; +} + +.tableHeader tr td:nth-child(2){ + width: 25%; +} + +.tableHeader tr td:nth-child(3){ + width: auto; +} + +.tableHeader tr td:nth-child(4){ + width: 15%; +} + +.refArea { + padding-left: 20px; + font-weight: 400; + line-height: 1.8; +} + +.introArea { + font-size: 18px; + line-height: 1.5; + font-weight: 300; +} + +h5 { + font-size: 18px; + line-height: 4; +} + +ul { + padding-left: 50px; + line-height: 2; + font-size: 17px; +} + +ul li { /*콜백 함수 종류*/ + list-style: disc; + margin: 10px 0; +} + +ul li p { /*콜백 함수 종류*/ + display: inline-block; + background: #cfe2f3; + color: blue; +} \ No newline at end of file diff --git a/src/main/resources/static/css/header.css b/src/main/resources/static/css/header.css new file mode 100644 index 0000000..42b07dd --- /dev/null +++ b/src/main/resources/static/css/header.css @@ -0,0 +1,96 @@ +#wrapper {display: flex;} +.sidebar {min-height: 100vh;background-color: #fff;font-size: 14px;} +.logo {z-index: 1;padding: 35px 0 35px 25px;display: flex;align-items: center;gap: 15px;cursor: pointer;} +.logo.txt img {} + +.user {padding: 25px 0 17px;cursor: pointer;margin-left: auto;} +.user .box {display: flex;align-items: center;gap: 22px;width: 260px;} +.user .box i {margin-left: auto;} +.user .img {height: 20px;padding: 15px;background: #fff;border: 3px solid #03add2;border-radius: 50px;display: flex;align-items: center;justify-content: center;} +.user .name {font-size: 14px;color: #56687c;font-weight: bold;} +.user .bell {position: relative;} +.user .bell em {position: absolute;top: 0;right: -5px;width: 18px;height: 18px;background: #f34a4a;border-radius: 20px;display: flex;align-items: center;justify-content: center;font-size: 16px;} +.user .bell>i {font-size: 26px;} +.user .tgBoxcon.head li a {color: #fff;} + +.leftNav {width: 290px;display: flex;align-items: stretch;} +.leftNav:last-child {margin-bottom: 160px;} +.leftNav .right {width: 290px;} +.leftNav .left.on, .leftNav:hover .left {background: #297efc;} +.nav-item {height: 65px;position: relative;cursor: pointer;display: flex;align-items: center;} +.nav-item.active a, .nav-item:hover a {color: #0494b4;} +.nav-link {color: #7a8eab;padding-left: 12px;display: flex;align-items: center;height: 40px;width: 100%;} +.nav-link span {font-size: .95rem;display: block;} + +.ptBtn {display: flex;align-items: center;justify-content: space-between;gap: 10px;} +.ptBtn .btn {cursor: pointer;color: #0494b4;font-size: 14px;width: 60%;height: 25px;border-radius: 3px;border: solid 1px #03add2;background-color: #f8fbff;display: flex;align-items: center;justify-content: center;} +.ptBtn .btn:hover {} +.ptBtn.dash {margin-top: auto;margin-bottom: 15px;} +.ptBtn.dash .btn {padding: 0 10px;} + +#content-wrapper {background-color: #f8fbff;min-width: 1440px;width: 100%;overflow-x: hidden;flex-direction: column;display: flex;} +#content {flex: 1 0 auto;} +.navbar {flex-flow: row nowrap;justify-content: flex-start;position: relative;display: flex;flex-wrap: wrap;align-items: center;justify-content: space-between;padding-right: 42px;} +.navbar .logo .tgBoxcon.head li a {color: #fff;} +.navbar-nav {flex-direction: row;margin-left: auto;display: flex;gap: 20px;padding-left: 0;margin-bottom: 0;} +.navbar-nav .nav-item {background: #3c4350;border-radius: 3px;padding: 7px 15px;} +.navbar-nav .nav-item>a {white-space: nowrap;position: relative;height: 4.375rem;display: flex;align-items: center;gap: 10px;} +.navbar-nav .nav-item>a img {height: 2rem;width: 2rem;margin-right: 10px;} +.navbar-nav .nav-item>a span:first-child {color: #5a5c69;} +.navbar-nav .nav-item>a span {font-size: 80%;color: #858796;text-align: right;display: block;} +.navbar-nav .nav-item>a .badge {position: absolute;transform: scale(.7);transform-origin: top right;right: 1.5rem;margin-top: -0.25rem;color: #fff;background-color: #e74a3b;display: inline-block;padding: 0.25em 0.4em;font-size: 75%;font-weight: 700;line-height: 1;white-space: nowrap;vertical-align: baseline;border-radius: 0.35rem;} +.nav-link .bellT {position: relative;padding-left: 15px;} +.nav-link .bellT::before {content: "";width: 5px;height: 5px;border-radius: 10px;background: #e74a3b;position: absolute;left: 10px;top: -2px;} +.nav-item-sub {border-top: 1px solid #eff2f5;border-bottom: 1px solid #eff2f5;display: none;} +.nav-item-sub li {} +.nav-item-sub li:hover a, .nav-item-sub li.on a {background:#e8fbff;} +.nav-item-sub a {color: #7a8eab;padding-left: 24px;cursor: pointer;height: 60px;display: flex;align-items: center;} +.nav-item-sub .bell {margin-left: auto;margin-right: 25px;position: relative;} +.nav-item-sub .bell::before {content: "";width: 5px;height: 5px;border-radius: 10px;background: #e74a3b;position: absolute;left: -10px;top: 7px;} + +.footer {padding: 2rem 0;flex-shrink: 0;background-color: #fff;font-size: .8rem;text-align: center;} + +.mWrap {display: flex;align-items: center;} +.mWrap>div>a {white-space: nowrap;position: relative;color: #fff;display: flex;align-items: center;justify-content: space-between;gap: 10px;padding-right: 10px;} +.mWrap span {font-size: 80%;text-align: right;display: block;} +.mWrap .lb {width: 80px;position: relative;padding-left: 10px;} +.mWrap .lb::before {content:'';width: 2px;height: 12px;background: #297efc;position: absolute;left: 0;top: 3px;} + +.mBox {position: fixed;bottom: 0;left: 25px;width: 220px;padding: 10px 10px 15px;border-radius: 5px;box-shadow: 0 0 10px 0 #d3d8dd;border: solid 1px rgb(194 207 224 / 30%);background-color: #fff;} +.mBox p {display: flex;align-items: center;justify-content: space-between;margin-bottom: 10px;} +.mBox p span {font-size: 14px;color: #7a8eab;} +.box1 {bottom: 25px;} +.box2 {bottom: 150px;} +.nav-item i {margin-left: auto;margin-right: 25px;} +.ico {width: 16px;height: 16px;margin-right: 17px;} + +.icon1 {background: url(/img/icon_dash.svg) center no-repeat;} +.icon2 {background: url(/img/icon_mypage.svg) center no-repeat;} +.icon3 {background: url(/img/icon_limit.svg) center no-repeat;} +.icon4 {background: url(/img/icon_cw.svg) center no-repeat;} +.icon5 {background: url(/img/icon_agency.svg) center no-repeat;} +.icon6 {background: url(/img/icon_insur.svg) center no-repeat;} +.icon7 {background: url(/img/icon_total.svg) center no-repeat;} +.icon8 {background: url(/img/icon_dev.svg) center no-repeat;} +.icon9 {background: url(/img/icon_gear.svg) center no-repeat;} + +a.nav-link:hover .icon1, +.active .icon1 {background: url(/img/icon_dash_on.svg) center no-repeat;} +a.nav-link:hover .icon2, +.active .icon2 {background: url(/img/icon_mypage_on.svg) center no-repeat;} +a.nav-link:hover .icon3, +.active .icon3 {background: url(/img/icon_limit_on.svg) center no-repeat;} +a.nav-link:hover .icon4, +.active .icon4 {background: url(/img/icon_cw_on.svg) center no-repeat;} +a.nav-link:hover .icon5, +.active .icon5 {background: url(/img/icon_agency_on.svg) center no-repeat;} +a.nav-link:hover .icon6, +.active .icon6 {background: url(/img/icon_insur_on.svg) center no-repeat;} +a.nav-link:hover .icon7, +.active .icon7 {background: url(/img/icon_total_on.svg) center no-repeat;} +a.nav-link:hover .icon8, +.active .icon8 {background: url(/img/icon_dev.svg) center no-repeat;} +a.nav-link:hover .icon9, +.active .icon9 {background: url(/img/icon_gear.svg) center no-repeat;} + + diff --git a/src/main/resources/static/css/login.css b/src/main/resources/static/css/login.css new file mode 100644 index 0000000..f13dba3 --- /dev/null +++ b/src/main/resources/static/css/login.css @@ -0,0 +1,23 @@ +body {display: flex;justify-content: center;align-items: center;min-height: 100vh;} +body.loginBg {background: url(/img/login_bg.jpg) center no-repeat;background-size: cover;} +.loginWrap {width: 500px;} +.login {} +.login>div {position: relative;display: flex;flex-direction: column;min-width: 0;word-wrap: break-word;} +.login>div .name {color: #323c47;margin-bottom: 50px;font-size: 30px;font-weight: bold;} +.login>div .input {font-size: 20px;margin-bottom: 30px;display: block;width: 100%;height: 40px;color: #7a8eab;background-color: #fff;border: 0;border-bottom: 2px dashed #c2cfe0;transition: border-color .15s ease-in-out,box-shadow .15s ease-in-out;} +.login>div .input::placeholder {color: #7a8eab} +.login>div .btn { line-height: 1.5; + user-select: none; + text-align: center; + vertical-align: middle; + color: #fff; + background-color: #03add2; + display: block; + width: 100%; + font-size: 18px; + border-radius: 5px; + padding: 10px 0; + cursor: pointer;} + +.foot {text-align: center;padding-top: 214px;} +.foot span {font-size: 15px;color: #7a8eab;display: block;margin-top: 15px;} \ No newline at end of file diff --git a/src/main/resources/static/css/main.css b/src/main/resources/static/css/main.css new file mode 100644 index 0000000..5bd41c4 --- /dev/null +++ b/src/main/resources/static/css/main.css @@ -0,0 +1,468 @@ +.container-fluid {padding-left: 1.5rem;padding-right: 1.5rem;margin-right: auto;margin-left: auto;} + +.alert {position: relative;padding: 0.75rem 1.25rem;margin-bottom: 1rem;border: 1px solid transparent;border-radius: 0.35rem;} +.alert-info {color: #297efc;background-color: #eaf5ff;border-color: #297efc;} +.alert-danger {color: #f34a4a;background-color: #feecec;border-color: #f34a4a;} +.alert>a {position: absolute;right: 15px;top: 15px;width: 22px;height: 22px;background: #fff;border-radius: 30px;display: flex;align-items: center;justify-content: center;} + +.page-name {margin-bottom: 1.5rem;color: #3b4151;display: flex;gap: 17px;align-items: center;} +.page-name h1 {font-size: 30px;color: #323c47;font-weight: bold;} +.page-name h2 {color: #3b4151;margin-bottom: 0;font-size: 36px;} +.page-name span {font-size: 12px;display: inline-block;color: #7a8eab;} +.page-name h2 .ver1 {background: #7d8492;border-radius: 57px;display: inline-block;font-size: 13px;color: #fff;margin: 0 0 0 5px;padding: 2px 8px;position: relative;top: -5px;vertical-align: super;} +.page-name h2 .ver2 {background-color: #89bf04;border-radius: 57px;display: inline-block;font-size: 13px;margin: 0 0 0 5px;padding: 2px 8px;position: relative;top: -5px;vertical-align: super;} +.page-name div em {font-size: 12px;color: #4990e2;} +.page-name div span {display: block;text-align: left;color: #3b4151;margin: 10px 0;line-height: 2em;} +.page-name.bt {padding-top: 1rem;margin-top: 1rem;border-top: 1px solid rgba(0,0,0,.1);} +.page-name svg {vertical-align: middle;} +.tablist {list-style: disc;padding-left: 40px;margin-top: 10px;font-size: 14px;} +.tablist li {margin-bottom: 14px;display: list-item;white-space: pre-wrap;} +.apitable {} +.apitable ul {display: flex;align-items: stretch;padding: 12px 0;} +.apitable ul.first {border-bottom: 1px solid rgba(59,65,81,.2);color: #3b4151;font-size: 12px;font-weight: bold;} +.apitable ul li {width: 20%;} +.apitable ul li:last-child {flex: 0 0 60%;} +.apitable.apitableCode ul li:first-child {width: 15%;} +.apitable.apitableCode ul li {width: 10%;} +.apitable.apitableCode ul li:nth-child(2) {flex: 0 0 75%;} +.apitableCode ul li.name {font-size: 13px;font-weight: bold;} +.apitableCode ul li.name small {display: block;color: #3b4151;font-size: 12px;} +.apitableCode ul li.name em {font-style: italic;font-size: 12px;color: gray;} +.apitableCode ul li:last-child {flex: 0 0 10%;} +.apitable.process {margin-bottom: 20px;} +.apitable.process ul li:nth-child(1) {width: 35%;} +.apitable.process ul li:nth-child(2) {width: 10%;} +.apitable.process ul li:nth-child(3) {width: 35%;} +.apitable.process ul li:nth-child(4) {width: 10%;} +.apitable.process ul li:nth-child(5) {flex: 0 0 10%;} +.processname {font-size: 1.5rem;} +.processname b {font-weight: bold;} +.mark {background: rgba(0,0,0,.05);border-radius: 4px;color: #9012fe;font-size: 14px;font-weight: bold;padding: 5px 7px;} +.bkmark {hyphens: auto;border-radius: 4px;word-wrap: break-word;overflow-x: auto;background: #333 !important;color: white !important;font-weight: bold;padding: 15px 20px;} +.pre {white-space: pre-wrap;display: block;} +.pre hr {margin-top: 1rem;margin-bottom: 1rem;border: 0;border-top: 1px solid rgba(0,0,0,.1);} +.update h3 {color: #3b4151;margin-bottom: 0.5rem;font-size: 1.75rem;} +.server {display: flex;justify-content: space-between;align-items: center;background: #fff;box-shadow: 0 1px 2px 0 rgb(0 0 0 / 15%);margin: 0 0 20px;padding: 30px;color: #3b4151;} +.server em {font-size: 12px;font-weight: bold;color: #3b4151;display: block;} +.server select {max-width: 100%;min-width: 130px;-webkit-appearance: none;-moz-appearance: none;appearance: none;background: #f7f7f7 url(../img/select.svg) right 10px center no-repeat;border: 2px solid #41444e;border-radius: 4px;box-shadow: 0 1px 2px 0 rgb(0 0 0 / 25%);color: #3b4151;font-size: 14px;font-weight: 700;padding: 5px 40px 5px 10px;} +.server button {display: flex;align-items: center;gap: 20px;background-color: #fff;color: #49cc90;line-height: 1;border: 2px solid #49cc90;border-radius: 4px;box-shadow: 0 1px 2px rgba(0,0,0,.1);font-size: 14px;font-weight: 700;padding: 5px 23px;transition: all .3s;} +.server button svg {fill: #49cc90;vertical-align: middle;} +.serverv {font-size: 1.5rem;margin: 1rem 0;} +.serveinput input {height: 100%;width: 100%;background: #fff;border: 1px solid #d9d9d9;border-radius: 4px;margin: 5px 0;min-width: 100px;padding: 8px 10px;} +input.user {max-width: 340px;width: 100%;color: #888;cursor: not-allowed;background: #fff;border: 1px solid #d9d9d9;border-radius: 4px;margin: 5px 0;min-width: 100px;padding: 8px 10px;font-size: 16px;margin: 1rem 0;} +.codetype {display: flex;gap: 30px;} +.none, .none ul, .none div {background: hsla(0,0%,92%,.1) !important;border-color: #ebebeb !important;opacity: .8;} +.noneline {text-decoration: line-through;} + +.api-name {margin-bottom: 1.5rem;} +.api-name .top {display: flex;align-items: center;justify-content: space-between;border-bottom: 1px solid rgba(59,65,81,.3);} +.api-name h4 {color: #3b4151;font-size: 24px;align-items: center;cursor: pointer;display: flex;padding: 10px 20px 10px 10px;} +.api-name h4 span {font-size: 14px;padding: 0 10px;} + +.apinfo {background: rgba(97,175,254,.1);border: 1px solid #61affe;border-radius: 4px;display: flex;justify-content: space-between;align-items: center;box-shadow: 0 0 3px rgb(0 0 0 / 19%);margin-top: 10px;cursor: pointer;padding: 5px;color: #3b4151;} +.apinfo.post {border-color: #49cc90;background: #e6f5f1;} +.apinfo li {display: flex;align-items: center;} +.apinfo li em {margin-right: 10px;background: #61affe;border-radius: 3px;color: #fff;font-size: 14px;font-weight: 700;min-width: 50px;padding: 6px 15px;text-align: center;text-shadow: 0 1px 0 rgb(0 0 0 / 10%);} +.apinfo li em.post {background: #49cc90;} +.apinfoWrap {border: 1px solid #61affe;border-top: 0;border-radius: 0 0 4px 4px;} +.apinfoWrap.post {border-color: #49cc90;} +.apinfoWrap>.pre {color: #3b4151;font-size: 12px;padding: 15px 20px;background: rgba(97,175,254,.1);} +.apinfoWrap.post .pre {background: #e6f5f1;} +.apinfoTop {align-items: center;background: #fff;box-shadow: 0 1px 2px rgba(0 0 0 / 10%);display: flex;justify-content: space-between;min-height: 35px;padding: 8px 20px;color: #3b4151;font-size: 14px;} +.apinfoTop li.on {position: relative;} +.apinfoTop li.on:after {background: #61affe;bottom: -15px;content: "";height: 4px;left: 50%;position: absolute;transform: translateX(-50%);width: 120%;} +.apinfoWrap .apinfoTop li.on:after {background: #49cc90;} +.trybtn {cursor: pointer;background: transparent;border: 2px solid grey;border-radius: 4px;box-shadow: 0 1px 2px rgb(0 0 0 / 10%);color: #3b4151;font-size: 14px;font-weight: bold;padding: 5px 23px;transition: all .3s;} +.agentCode small{display: block;font-size: .9em;margin: 0.2em 0;} +.agentCode select {min-width: 230px;-webkit-appearance: none;-moz-appearance: none;appearance: none;background: #f7f7f7 url(../img/select.svg) right 10px center no-repeat;background-size: 20px;border: 2px solid green;border-radius: 4px;box-shadow: 0 1px 2px 0 rgb(0 0 0 / 25%);color: #3b4151;font-size: 14px;font-weight: bold;padding: 5px 40px 5px 10px;} +.agentCode select.bks {border: 2px solid #000;} +.exbtn {display: inline-block;} +.required {position: relative;} +.required:after {content: "* required";color: rgba(255,0,0,.6);font-size: 10px;padding: 5px;position: relative;top: -6px;} + +.schemas {border: 1px solid rgba(59,65,81,.3);border-radius: 4px;margin: 30px 0;} +.schemas h4 {display: flex;justify-content: space-between;align-items: center;padding: 10px 20px 10px 10px;} +.schemas img {height: 20px;} +.schemas .con {border-top: 1px solid rgba(59,65,81,.3);padding: 0 20px 20px;color: #505050;font-weight: bold;} +.schemas .con li {background: rgba(0,0,0,.05);border-radius: 4px;margin-top: 20px;padding: 20px;} +.schemas .con li:hover {background: rgba(0,0,0,.07);} +.schemas .con img {vertical-align: middle;} + +.row {display: flex;gap: 10px;} +.row>div {width: 100%;margin-bottom: 10px !important;} +.row .card {position: relative;min-width: 0;word-wrap: break-word;background-clip: border-box;border-radius: 5px;border: solid 1px #dfedff;background-color: #fff;} +.row .card .card-body {min-height: 1px;height: 100px;padding: 0 20px;display: flex;justify-content: space-between;align-items: center;position: relative;} +.row .card .card-body .left {font-weight: bold;color: #5a5c69;font-size: 1.25rem;} +.row .card .card-body .left div:first-child {font-size: 14px;color: #56687c;font-weight: normal;margin-bottom: 10px;} +.row .card .card-body .left div {font-size: 16px;color: #56687c;} +.row .card .card-body .left div.upDown {font-size: 16px;color: #8e9598;display: flex;align-items: center;gap: 5px;font-weight: normal;} +.row .card .card-body .left div.upDown em {width: 20px;height: 20px;border-radius: 30px;display: flex;align-items: center;justify-content: center;} +.row .card .card-body .left div.upDown em.up {background: #defced;} +.row .card .card-body .left div.upDown em.down {background: #feecec;} +.row .card .card-body .left div.upDown span.up {color: #2be77e;} +.row .card .card-body .left div.upDown span.down {color: #f34a4a;} +.row .card .card-body .right {position: absolute;right: 12px;top: 0;width: 35px;height: 38px;background: url(/img/dash_bg.svg);display: flex;align-items: center;justify-content: center;} +.row2 {display: flex;gap: 20px;} +.row2 .card.left {flex: 0 0 64%;} +.row2 .card.right {flex: 0 0 34%;} +.row2 .card {border-radius: 8px;box-shadow: 0 3px 6px 0 rgba(0, 0, 0, 0.16);margin-bottom: 1.5rem;position: relative;display: flex;flex-direction: column;min-width: 0;word-wrap: break-word;background-color: #fff;background-clip: border-box;border: 1px solid #e3e6f0;border-radius: 0.35rem;} +.row2 .card-header {border-radius: calc(0.35rem - 1px) calc(0.35rem - 1px) 0 0;padding: 0.75rem 1.25rem;margin-bottom: 0;background-color: #f8f9fc;border-bottom: 1px solid #e3e6f0;display: flex;flex-direction: row;justify-content: space-between;align-items: center;} +.row2 .card-header h6 {color: #3c4350;font-size: 16px;} +.row2 .card-header i {color: #d1d3e2;font-weight: bold;} +.row2 .card-body {flex: 1 1 auto;min-height: 1px;padding: 1.25rem;} +.row2 .card-body .chart-area {height: 20rem;position: relative;height: 10rem;width: 100%;} + +/* mypage */ +.table {margin-bottom: 1.5rem;border-radius: 5px;position: relative;display: flex;flex-direction: column;min-width: 0;word-wrap: break-word;background-color: #fff;overflow-x: auto;} +.table .head {padding: 22px 20px;margin-bottom: 0;border-bottom: 1px dashed #c2cfe0;} +.table .head h6 {color: #56687c;font-size: 20px;} +.table .head h6.bg {color: #fff;background: #297efc;display: inline-block;border-radius: 5px;padding: 1px 7px;margin-right: 10px;} +.table .head h6.bold {font-size: 18px;font-weight: bold;} +.table .head .text {font-size: 80%;} +.table .head .num {color: #297efc;font-weight: bold;} +.table .between {justify-content: space-between;} +.table .check-wrap {display: flex;align-items: center;gap: 15px;font-size: 13px;} +.table .check-wrap input {width: auto;height: auto;} +.table .check-wrap .inputs {display: flex;align-items: center;gap: 5px;cursor: pointer;} +.table .body {flex: 1 1 auto;} +.table-responsive .nonDetail {display: block;width: 100%;overflow-x: auto;/*min-height: 500px;*/} +.table-responsive .h4 {margin-bottom: 1.25rem;color: #474f60;} +.table-responsive > table {border: 0;width: calc(100% - 40px);color: #56687c;} +.table-responsive > table th { background: #f8fbff; } +.table-responsive table.nonDetail {border: 0;color: #56687c; } +table.center {text-align: center;} +.table td, .table th {word-break: keep-all;white-space: nowrap;vertical-align: middle;} +.table-responsive .nonDetail th {color: #56687c;font-weight: bold;background: #f8fbff;} +.table-responsive td {color: #474f60;} +.table-responsive td, .table-responsive th {border: 1px dashed #c2cfe0;} +.table-responsive td, .table-responsive th {font-size: 14px;padding: 6px 10px;vertical-align: top;word-break: keep-all;white-space: nowrap;vertical-align: middle; text-align: center;} +.table-responsive a {color: #03add2;} +.table-responsive .btn {cursor: pointer;color: #fff;background-color: #03add2;border-color: #03add2;padding: 6px 22px;font-size: 14px;line-height: 1.5;border-radius: 0.2rem;} +.table-responsive .btn.success {background: #87d203;} +.table-responsive .input , +.table-responsive .select {width: 400px;display: inline-block;height: 35px;padding-left: 15px;font-size: 14px;font-weight: 400;line-height: 1.5;color: #56687c;background-color: #fff;background-clip: padding-box;border: 1px solid #c2cfe0;border-radius: 5px;} +.table-responsive .select {width: 417px;} +.table-responsive .inputbtn {color: #fff;background-color: #03add2;border-color: #03add2;padding: 0.45rem 0.7rem;font-size: 14px;line-height: 1.5;border-radius: 3px;margin-left: 5px;} +.table-responsive .text {display: block;color: #7a8eab;font-size: 14px;margin-top: 10px;} +.table-responsive select {width: 380px;padding-left: 0.75rem;height: calc(1.5em + 0.75rem + 2px);font-size: 1rem;background-color: #fff;border: 1px solid #ced4da;border-radius: 0.25rem;line-height: calc(1.5em + .75rem);color: #495057;display: block;padding-right: 20px;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;} +.table-responsive .black {color: gray;} +.table-responsive .stop a {color: red;} +.table-responsive td.detailSec { position: relative; } +.table-responsive .bold {font-size: 15px;color: #e90000;font-weight: bold;} +.table-responsive .mr-5 {margin: 0 5px !important;} +.table-responsive .lowA {background: #cd82e526;} +.table-responsive .lowB {background: #b1e58226;} + + +.ps {padding: 5px !important;} +.ps2 {padding: 2px !important;background: #c2cfe0} + +.detailpopup { display:none; border: 2px solid; background:#fff; position: fixed; right: 1.5rem; top: 50%; left:50%; transform: translate(-50%, -50%); width:1000px; z-index:1; } +.detailpopup table { border: 1px solid #c2cfe0; } +.detailpopup h3 { font-size: 18px; line-height: 1.8; font-weight: bold; position: relative; } +.detailpopup .detailClose { display: inline-block; position: absolute; right: 5px; cursor: pointer; } +.detailpopup .detailTb { width: 99%; margin: 0px auto 5px; } +.detailpopup .detailTb table { width: 100% } +.detailpopup td, .detailpopup th { padding: 5px; } +.detailpopup td .betType { padding: 3px 7px; color: #fff; font-weight: bold; border-radius: 8px; } +.detailpopup td .typeT { background: rgb(70, 180, 65); } +.detailpopup td .typeB { background: rgb(0, 147, 255); } +.detailpopup td .typeP { background: rgb(206, 53, 57); } +.detailpopup td .notypeP { background: rgb(0, 0, 0); margin-left: 1px; border-radius: 100%; color:yellow; } +.detailpopup .cardWrap { display: flex; margin: 0 auto; width: 45%; max-height: 72px; justify-content: center; font-size: 40px; font-weight: bold;} +.detailpopup .cardWrap span:nth-child(2) { padding: 0 20px; } +.detailpopup .cardWrap .ro90 { transform: rotate(90deg); color: red; } +#bank { color:blue; } +#player { color:red; } +.detailpopup .cardWrapB .ro90 { margin-top: 20px; } +.detailpopup .cardWrapP .ro90 { margin-bottom: -20px; } +.blhover {color: #4e73df;cursor: pointer;} +.blhover:hover {text-decoration: underline;} +.table .body.read .top {display: flex;gap: 20px;margin-bottom: 20px;} +.table .body.read .top span {font-weight: bold;margin-right: 5px;} + +.table .body.fix {display: flex;justify-content: space-around;} +.table .body.fix ul:first-child {margin-top: 0;} +.table .body.fix ul {display: flex;align-items: center;gap: 20px;margin-top: 1rem;} +.table .body.fix li:first-child {width: 200px;} +.table .body.fix li.chk {color: #e74a3b;display: flex;gap: 20px;} +.table .body.fix li.chk span:first-child {color: #1cc88a;} +.table .body.fix li.chk input {margin-right: 5px;} + +.insur .insurTable td{ + font-size: 14px; + padding: 10px 20px; + word-break: keep-all; + white-space: nowrap; + vertical-align: middle; + text-align: center; +} +.insur .insurTable input{ + width: 60px; + text-align: center; + border: 1px solid #c5c5c5; + border-radius: 3px; + padding: 5px 0px; + margin-right: 5px; + color: black; +} +.insur .insurTable .btinsureRate{ + border: 0px solid black; +} + +/* charge */ +.tabletab {margin: 40px 0 20px;display: flex;gap: 40px;flex-wrap: wrap;border-bottom: 2px solid #eff2f5;} +.tabletab a {font-size: 18px;color: #7a8eab;padding-bottom: 10px;display: flex;align-items: center;justify-content: center;} +.tabletab .active {border-bottom: 2px solid #03add2;} +.tabletab .active a {color: #56687c;} +.tabText {color: #7a8eab;font-size: 12px;margin: -20px 0 30px;display: block;} +.tableserach {justify-content: flex-end;display: flex;flex-wrap: wrap;gap: 15px;padding-left: 0;} +.tableserach li {display: flex;align-items: center;} +.input-group {position: relative;display: flex;flex-wrap: wrap;align-items: center;gap: 10px;width: 100%;height: 45px;border: 1px dashed #c2cfe0;padding: 0 20px;color: #c2cfe0;background: #fff;} +.input-group-text {display: flex;align-items: center;font-size: 14px;line-height: 1.5;color: #5f799b;text-align: center;white-space: nowrap;} +.input-group select {position: relative;flex: 1 1 auto;font-size: 14px;line-height: 1.5;color: #474f60;background: none;border: 0;} +.input-group input {border: 0; + padding: 0; + color: #56687c; + height: 25px; + font-size: 14px; + text-align: right;} +.input-group input::placeholder {color: #c2cfe0;} +.tableserach .btn {cursor: pointer;color: #fff;display: flex;align-items: center;justify-content: center;text-align: center;vertical-align: middle;user-select: none;padding: 0 13px;border-radius: 5px;background-color: #03add2;height: 45px;} +.tableserach .btn.btnn {width: auto;padding: 0 10px;font-size: 14px;} +.tableserachwrap {display: flex;justify-content: space-between; margin-bottom: 20px; align-items: flex-end; } +.insur .tableserachwrap {display: flex;justify-content: space-between; margin: 20px;} +.download {font-size: 14px;display: flex;gap: 15px;align-items: center;color: #323c47;} +.download a {display: flex;align-items: center;justify-content: center;gap: 15px;width: 100px;height: 45px;cursor: pointer;border-radius: 5px;border: solid 1px #03add2;background-color: #fff;} +.download img {vertical-align: middle;} +.mb-1 {margin-bottom: 0.25rem;} +.mb-1 .info {color: #fff;background-color: #36b9cc;display: inline-block;padding: 0.25em 0.4em;font-size: 12px;line-height: 1;text-align: center;white-space: nowrap;vertical-align: baseline;border-radius: 0.35rem;} +.mb-1 .primary {color: #0494b4;background-color: #e8fbff;display: inline-block;padding: 0.25em 0.4em;font-size: 12px;line-height: 1;text-align: center;white-space: nowrap;vertical-align: baseline;border-radius: 0.35rem;} +.mb-1 .success {color: #fff;background-color: #1cc88a;display: inline-block;padding: 0.25em 0.4em;font-size: 75%;font-weight: 700;line-height: 1;text-align: center;white-space: nowrap;vertical-align: baseline;border-radius: 0.35rem;} +.title {color: #5a5c69;font-size: 14px;} +.round {font-size: 87.5%;color: #e83e8c;word-wrap: break-word;} +.bottomText {color: #b7b9cc;text-align: right;} + +/* sumPrice */ +#sumPriceWrap { margin-bottom: 20px; display: flex; justify-content: space-between; font-size: 15px; } +#sumPriceWrap > div { display: flex; gap: 40px; align-items: flex-end; } +#sumPriceWrap .sumPrice { display: flex; gap: 15px; align-items: center; } +#sumPriceWrap .sumPrice > li { border: 1px dashed #c2cfe0; } +#sumPriceWrap .sumPriceSec { display: flex; gap: 20px; align-items: center; padding: 8px 20px; } +#sumPriceWrap .sumPriceSec > li:first-child { position: relative; } +#sumPriceWrap .sumPriceSec > li:first-child::after { content:""; position: absolute; display: inline-block; width: 1px; height: 25px; border-right: 1px solid #c2cfe0; top: -1px; right: -20px; } +.priceArea { font-weight: bold; font-size: 16px; color: #00b2d9; min-width: 135px; text-align: right; } + +/* linePrint_with Excel [ ex) betist ] */ +#sumPriceWrap .linePrintWrap { gap: 5px; } +#sumPriceWrap .linePrintWrap .linePrint { display: flex; gap: 5px; font-size: 14px; align-items: center; } +#sumPriceWrap .linePrintWrap .linePrint li { padding: 3px 10px; border-radius: 5px; background: #03add2; } +#sumPriceWrap .linePrintWrap .linePrint li a { color: #fff; } +.btnExcel { display:flex; align-items: flex-end; background:none; border-radius: 5px; color: #fff; background: #03add2; border: 0; cursor:pointer; font-size: 16px; padding: 5px 4px 5px 6px; } +.btnExcel:hover { font-weight: bold; background: #03add2; opacity: 0.8; } +.btnExcel img { width:24px; margin-right:2px; } + +/* linePrint_without [ other ] */ +#lineWrap { display: flex; justify-content: space-between; font-size: 15px; } +#lineWrap .linePrintWrap { display: flex; gap: 5px; align-items: flex-end; } +#lineWrap .linePrintWrap .linePrint { display: flex; gap: 5px; font-size: 14px; align-items: center; } +#lineWrap .linePrintWrap .linePrint li { padding: 3px 10px; border-radius: 5px; background: #03add2; } +#lineWrap .linePrintWrap .linePrint li a { color: #fff; } + +/* stste */ +.success {color: #56687c;text-align: center;white-space: nowrap;vertical-align: baseline;} +.confirm {color: #f82929;font-size: 75%;text-align: center;white-space: nowrap;vertical-align: baseline;cursor: pointer;} +.apply {color: #fff;background-color: #e74a3b;display: inline-block;padding: 0.5em;font-size: 75%;font-weight: 700;line-height: 1;text-align: center;white-space: nowrap;vertical-align: baseline;border-radius: 0.35rem;cursor: pointer;} + +/* bottom btn */ +.btnwrap {display: flex;justify-content: flex-end;align-items: center;gap: 10px;} +.btnwrap .btn {color: #fff;background-color: #03add2;border: 1px solid #03add2;display: inline-block;;text-align: center;vertical-align: middle;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;padding: 11px 48px;font-size: 14px;line-height: 1.5;border-radius: 0.35rem;cursor: pointer;} +.btnwrap .btn i {color: #fff;font-weight: 900;} +.btnwrap .btn+.btn {background: #2be77e;border-color: #12c561;} +.btnwrap .btn.blbtn {background-color: #4e73df;} + +/* pagenation */ +.pagenation-wrap {display: flex;align-items: center;justify-content: center;gap: 15px;margin: 20px 0;} +.pagenation-wrap button {width: 18px;height: 18px;background: #fff;border: 0;color: #56687c;display: flex;align-items: center;justify-content: center;font-size: 14px; cursor: pointer;} +.pagenation-wrap button.on {background: #03add2;color: #fff;} + +.totalBtn {display: flex;align-items: center;justify-content: center;gap: 10px;font-size: 14px;} +.totalBtn li {background: #e3e0e0;padding: 5px 10px;border-radius: 5px;} +.totalBtn li.on {color: #fff;background: #59baff;} +.totalBtn a {cursor: pointer;} + +/* modal */ +.selectFlex {display: flex;justify-content: left;align-items: center;border: 0 !important;} +.selectFlex a {cursor: pointer;color: #3a3b45;} +.selectBox {cursor: pointer;} +.selectBox em {display: block;} +.selectBox em::after {display: inline-block;margin-left: 0.255em;vertical-align: 0.255em;content: "";border-top: 0.3em solid;border-right: 0.3em solid transparent;border-bottom: 0;border-left: 0.3em solid transparent;} +.selectBox.bl {color: #0494b4;} +.selectRight {margin: 1.5rem 1rem;} +.tgBox {position: relative;} +.tgBoxcon {display: none;position: absolute;font-size: 14px;background-color: #3c4350;border-radius: 8px;color: #fff;padding: 0.5rem 0; margin-top: 20px; min-width: 10rem;z-index: 1;} +.tgBoxcon.head {width: 14rem;} +.tgBoxcon.head li:hover, .tgBoxcon li:hover {background-color: #282d37;} +.tgBoxcon.head li:first-child {font-weight: normal;font-size: .85rem;color: #3a3b45;} +.tgBoxcon li:first-child:hover {background: none;} +.tgBoxcon.head li a {padding: 0;height: auto;color: #3a3b45;} +.tgBoxcon.head i {color: #d1d3e2;margin-right: 0.5rem;} +.tgBoxcon ul:first-child {padding-bottom: 0.5rem;} +.tgBoxcon li:first-child {font-size: 12px;color: #a7adb7;padding-top: 0.5rem;} +.tgBoxcon li {padding: 0.25rem 1.5rem;cursor: pointer;} +.tgBoxcon li a {color: #fff;} + +.modal-content {position:fixed;top:50%;left:50%;transform: translate(-50%,-50%);display: block;width: 500px;pointer-events: auto;background-color: #fff;background-clip: padding-box;border: 1px solid rgba(0,0,0,.2);border-radius: 0.3rem;outline: 0;z-index: 1;display: none;} +.modal-content1 {position:fixed;top:50%;left:50%;transform: translate(-50%,-50%);display: block;width: 500px;pointer-events: auto;background-color: #fff;background-clip: padding-box;border: 1px solid rgba(0,0,0,.2);border-radius: 0.3rem;outline: 0;z-index: 1;display: none;} +.modal-content2 {position:fixed;top:50%;left:50%;transform: translate(-50%,-50%);display: block;width: 500px;pointer-events: auto;background-color: #fff;background-clip: padding-box;border: 1px solid rgba(0,0,0,.2);border-radius: 0.3rem;outline: 0;z-index: 1;display: none;} +.modal-content3 {position:fixed;top:50%;left:50%;transform: translate(-50%,-50%);display: block;width: 500px;pointer-events: auto;background-color: #fff;background-clip: padding-box;border: 1px solid rgba(0,0,0,.2);border-radius: 0.3rem;outline: 0;z-index: 1;display: none;} +.modal-content4 {position:fixed;top:50%;left:50%;transform: translate(-50%,-50%);display: block;width: 500px;pointer-events: auto;background-color: #fff;background-clip: padding-box;border: 1px solid rgba(0,0,0,.2);border-radius: 0.3rem;outline: 0;z-index: 1;display: none;} +.modal-header {display: flex;align-items: center;justify-content: space-between;padding: 14px 20px;background: #282d37;} +.modal-header h5 {font-size: 14px;color: #fff;} +.modal-header a {font-size: 1.5rem;cursor: pointer;width: 22px;height: 22px;background: #fff;border-radius: 30px;display: flex;align-items: center;justify-content: center;} +.modal-body {position: relative;flex: 1 1 auto;padding: 13px 20px 20px;} +.modal-body select, .modal-body textarea, .modal-body input {display: block;width: 100%;height: calc(1.5em + 0.75rem + 2px);padding: 0 0.5rem;font-size: 14px;line-height: 1.5;color: #3c4350;background-color: #fff;background-clip: padding-box;border: 1px solid #a7adb7;border-radius: 3px;} +.modal-body textarea, .modal-body input {width: calc(100% - 1rem);} +.modal-body textarea {height: 130px;resize: none;padding: 0.5rem;} +.modal-body .chk {align-items: center;display: flex;} +.modal-body .chk input {width: auto;height: auto;} +.modal-body span {color: #858796;font-size: 80%;} +.modal-body ul {margin-top: 13px;display: flex;flex-wrap: wrap;} +.modal-body ul li {flex: 0 0 66.66667%;max-width: 66.66667%;position: relative;} +.modal-body ul li:first-child {flex: 0 0 33.33333%;max-width: 33.33333%;color: #3c4350;font-size: 14px;} +.modal-footer {display: flex;flex-wrap: wrap;align-items: center;justify-content: flex-end;padding: 0.75rem;border-top: 1px solid #e3e6f0;border-bottom-right-radius: calc(0.3rem - 1px);border-bottom-left-radius: calc(0.3rem - 1px);} +.modal-footer a:first-child {background-color: #fff;border: 1px solid #a7adb7;color: #3c4350;} +.modal-footer a {cursor: pointer;margin: 0.25rem;color: #fff;display: inline-block;text-align: center;vertical-align: middle;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;background-color: #297efc;border: 1px solid #0057d8;padding: 4px 30px;font-size: 14px;line-height: 1.5;border-radius: 3px;} + +.modal-body em.pot {position: absolute;right: -2px;top: 0;display: flex;align-items: center;padding: 0.46rem 0.75rem;margin-bottom: 0;font-size: 1rem;font-weight: 400;line-height: 1.5;color: #6e707e;text-align: center;white-space: nowrap;background-color: #eaecf4;border: 1px solid #d1d3e2;border-radius: 0 0.35rem 0.35rem 0;} + +.table .head {display: flex;align-items: center;gap: 15px;} +.table .head .rateSet{ display: contents;} +.table .head .input {display: inline-block;height: 35px;padding-left: 15px;font-size: 14px;font-weight: 400;line-height: 1.5;color: #56687c;background-color: #fff;background-clip: padding-box;border: 1px solid #c2cfe0;border-radius: 5px;} +.btnborder0{border: 0;} +.blBtn {cursor: pointer;color: #fff;background-color: #03add2;display: inline-block;padding: 6px 22px;font-size: 14px;border-radius: 5px;} +.gnBtn {cursor: pointer;color: #fff;background-color: #56687c;display: inline-block;padding: 5px 26px;font-size: 14px;border-radius: 5px;} +.grBtn {cursor: pointer;color: #fff;background-color: #56687c;font-size: 14px;border-radius: 5px;width: 30px;height: 30px;display: flex;align-items: center;justify-content: center;} +.creditBtnWrap {display: flex;gap: 15px;margin: 0 0 45px;} +.creditBtnWrap a {display: block;width: 100%;font-size: 14px;color: #323c47;text-align: center;padding: 14px 0;cursor: pointer;border-radius: 5px;border: solid 1px #0494b4;background-color: #fff;} +.memo {margin: 30px 20px;} +.memo textarea {width: calc(100% - 40px);height: 157px;border-radius: 5px;border: solid 1px #c2cfe0;resize: none;padding: 20px;} + + +.creditPopWrap {display: none;z-index:99;position: fixed;top: 50%;left: 50%;transform: translate(-50%, -50%);background: #fff;width: 500px;border: 1px solid #e3e6f0;box-shadow: 0 0.15rem 1.75rem 0 rgb(58 59 69 / 15%);} +.creditPopWrap h4 {display: flex;align-items: center;justify-content: space-between;padding: 10px 20px;color: #56687c;background: #f8fbff;border-bottom: 1px solid #e3e6f0;} +.creditPopWrap h4 a {display: inline-block;background: #f8fbff;color: #0494b4;padding: 5px 10px;width: auto;} +.creditPopWrap .creditPopn {display: flex;align-items: center;gap: 10px;padding-left: 20px;flex-wrap: wrap;} +.creditPopWrap .creditPopn span {width: 50px;} +.creditPopWrap .creditPopn > input {width: calc(100% - 107px);} +.creditPopWrap input {width: calc(100% - 45px);height: 35px;padding: 0 0 0 5px;border: 1px solid #c2cfe0;border-radius: 5px;margin: 20px;} +.creditPopWrap > a {width: calc(100% - 40px);margin: 0 auto;margin-bottom: 20px;} + +/* report */ +.repSum { background: #f8fbff; font-weight: bold; } + +/* game manage */ +.activeY { background: blue; color: #fff; } +.manageTd { color: #fff; font-weight: bold; border-radius: 10px; } +.managebtn { padding: 8px 15px; background: rgb(91, 172, 232); cursor: pointer; } +.manageKREN { padding: 5px 10px; background: rgb(192, 192, 192); cursor: not-allowed;} +.manageY { padding: 5px 10px; background: rgb(91, 172, 232); } +.manageN {padding: 5px 10px;background: rgb(247, 132, 135);} + +input[type="checkbox"].set-switch { + display: inline-block; + -webkit-appearance: none; + -moz-appearance: none; + -o-appearance: none; + appearance: none; + outline: 0; + cursor: pointer; + width: 40px; + height: 20px; + border-radius: 3em; + background-color: #f0f0f0; + transition: background-color 0.15s ease-in-out; + position: relative; + max-width: 40px; +} +.set-switch:after { + position: absolute; + content: ""; + left: 0; + width: 18px; + height: 18px; + background: #fff; + border-radius: 100%; + top: 50%; + transform: translateY(-50%); + transition: left 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275), padding 0.3s ease, margin 0.3s ease; + box-shadow: 2px 1px 5px 0px rgb(0 0 0 / 41%); +} +input[type="checkbox"].set-switch:checked { + background: #03add2; +} +input[type="checkbox"].set-switch:checked:after { + left: calc(100% - 18px); +} +.toggle-wrap { + display: flex; + width: 100%; + align-items: center; + justify-content: center; + padding: 4px; + box-sizing: border-box; +} +.toggle-text { + text-align: center; + font-weight: 800; + color: #ca1717; + width: 50px; + display: none; +} +.toggle-text.on{ + color: #0c960c; +} + +.nexuswrap { + display: flex; + flex-direction: column; + align-items: center; + gap: 10px; +} +.nexuswrap li { + display: flex; + align-items: center; + gap: 10px; + width: 70%; +} +.nexuswrap li > span:nth-child(1) { + min-width: 65px;; +} + +/* apiset */ + +.table .saveBtnArea { padding: 0 20px 20px; } +.table .apisetBox { padding-top: 15px; font-size: 14px; } +.table .apisetAdd { padding-top: 5px; font-size: 13px; } +.table .pointTxtBlue { color: #4ba4ff; } + +/* intro API */ + +.table .head_sub {padding: 5px 20px 0; margin-bottom: 0;} +.table .head_sub h6 {color: #56687c;font-size: 18px;} +.table .head_sub.secondSec { border-top: 1px dashed #c2cfe0; } +.table .bodyflex { display: flex; } +.table .bodyflex .table-responsive:first-child { width: 30% } +.table .bodyflex .table-responsive:last-child { width: 70% } +.table .topline { border-top: 1px dashed #c2cfe0; } +.table-responsive a.blBtn { color: #fff; margin:0; } +.apiCodeArea { padding: 20px 20px; background: #002b36; color: #2aa198; /* 기호 표시는 #839496 */ min-height: 250px; } +.fix-content .apiCodeArea { max-height: 250px; overflow-y: auto; } +.table .inputTxt { margin-bottom: 20px; max-height: 350px; } +.table input { height: 32px; text-indent: 10px; font-size: 14px; width: 100%; } +.table .inputTxt textarea { width: 100%; height: 290px; border: none; resize: none; } +.table input[type=date] { text-indent: 5px; } +.table .tbIntb { width: 100%; margin: auto; } +.table .tbIntb td { padding: 8px 10px; } +.Ybox { display: inline-block;padding: 5px 10px;background: #9ec5ff;color: #fff;border-radius: 10px;font-weight: bold; } +.Nbox { display: inline-block;padding: 5px 10px;background: #ff9e9e;color: #fff;border-radius: 10px;font-weight: bold; } \ No newline at end of file diff --git a/src/main/resources/static/css/popup.css b/src/main/resources/static/css/popup.css new file mode 100644 index 0000000..a72e60a --- /dev/null +++ b/src/main/resources/static/css/popup.css @@ -0,0 +1,69 @@ +.table .head {display: flex;align-items: center;gap: 15px;} +.table .head .input {display: inline-block;height: 35px;padding-left: 15px;font-size: 14px;font-weight: 400;line-height: 1.5;color: #56687c;background-color: #fff;background-clip: padding-box;border: 1px solid #c2cfe0;border-radius: 5px;} +.blBtn {cursor: pointer;color: #fff;background-color: #03add2;display: inline-block;padding: 6px 22px;font-size: 14px;border-radius: 5px;margin-left: auto;} +.gnBtn {cursor: pointer;color: #fff;background-color: #56687c;display: inline-block;padding: 5px 26px;font-size: 14px;border-radius: 5px;} +.grBtn {cursor: pointer;color: #fff;background-color: #56687c;font-size: 14px;border-radius: 5px;width: 30px;height: 30px;display: flex;align-items: center;justify-content: center;} +.creditBtnWrap {display: flex;gap: 15px;margin: 0 0 45px;} +.creditBtnWrap a {display: block;width: 100%;font-size: 14px;color: #323c47;text-align: center;padding: 14px 0;cursor: pointer;border-radius: 5px;border: solid 1px #0494b4;background-color: #fff;} +.memo {margin: 30px 20px;} +.memo textarea {width: calc(100% - 40px);height: 157px;border-radius: 5px;border: solid 1px #c2cfe0;resize: none;padding: 20px;} + + +.creditAllWrap {background-color: #f8f9fc;display: flex;gap: 20px;padding: 20px;} +.creditWrap {margin-bottom: 20px;box-shadow: 0 0.15rem 1.75rem 0 rgb(58 59 69 / 15%);background-color: #fff;border: 1px solid #e3e6f0;border-radius: 5px;} +.creditName {display: flex;justify-content: space-between;align-items: center;padding: 10px 20px;background-color: #f8f9fc;border-bottom: 1px solid #e3e6f0;} +.creditName li {display: flex;align-items: center;gap: 5px;} +.creditName h4 {color: #4e73df;font-weight: 700;font-size: 18px;} +.creditName input {height: 25px;padding: 0 0 0 10px;border: 1px solid #c5c5c5;border-radius: 4px;} +/*.blBtn {cursor: pointer;color: #fff;background-color: #4e73df;display: inline-block;padding: 5px 10px;font-size: 14px;border-radius: 5px;}*/ +.rdBtn {cursor: pointer;color: #fff;background-color: #e24747;display: inline-block;padding: 5px 10px;font-size: 14px;border-radius: 5px;} +/*.gnBtn {cursor: pointer;color: #fff;background-color: #188b56;display: inline-block;padding: 5px 10px;font-size: 14px;border-radius: 5px;} +.grBtn {cursor: pointer;color: #fff;background-color: #666;display: inline-block;padding: 5px 10px;font-size: 14px;border-radius: 5px;}*/ +.creditInfo {display: flex;gap: 40px;margin: 0 20px 20px;padding-top: 20px;font-size: 14px;border-top: 1px solid #e3e6f0;} +.creditInfo.game {gap: 20px;} +.creditInfo:nth-child(2) {border-top: 0;} +.creditInfo ul {width: 100%;position: relative;} +.creditInfo ul:first-child::before {content: none;} +.creditInfo ul::before {content: '';width: 1px;height: 100%;position: absolute;top: 0;left: -20px;background: #e3e6f0;} +.creditInfo.game ul::before {left: -10px;} +.creditInfo li {display: flex;align-items: center;margin-top: 10px;} +.creditInfo ul li:first-child {margin-top: 0;} + +.creditInfo.game li {margin: 0 0 10px 15px;float: left;width: calc(25% - 15px);} +.creditInfo.game li:nth-child(4n+1) {margin-left: 0;} +.creditInfo.game li span {display: flex;gap: 3px;} +.creditInfo li span:first-child {width: 140px;} +.creditInfo.game li span:first-child {width: 100px;font-size: 12px;word-break: keep-all;} +.creditInfo input {height: 20px;padding: 0 0 0 5px;border: 1px solid #c5c5c5;border-radius: 4px;} +.creditInfo.game input {font-size: 12px;} +/*.creditBtnWrap {display: flex;gap: 10px;padding: 0 20px 20px;} +.creditBtnWrap a {display: block;width: 100%;font-size: 12px;color: #fff;text-align: center;padding: 10px 5px;background: #4e73df;border-radius: 5px;cursor: pointer;}*/ +.companyList {display: flex;padding: 20px;} +.companyList li:first-child::before {content: none;} +.companyList li::before {content: "▶";display: inline;margin-left: 5px;color: #858796;} +.companyList li:last-child {color: red;} +.companytable {padding: 20px;overflow-y: auto;max-height: 400px;} +.companytable ul {display: flex;text-align: center;font-size: 14px;padding: 10px 0;} +.companytable li {width: 100%;} +.companytable ul.head {background: #4e73df;color: #fff;border-radius: 5px 5px 0 0;} +.companyMemo {padding: 20px;} +.companyMemo textarea {border: 1px solid #e3e6f0;border-radius: 5px;resize: none;width: calc(100% - 30px);padding: 15px;height: 88px;} +.creditRight {width: 100%;} +.gameCredit {display: flex;gap: 10px;padding: 20px;} +.gameCredit ul {width: 100%;} +.gameCredit ul li:first-child {margin-top: 0;} +.gameCredit li {border: 1px solid #e3e6f0;border-radius: 5px;font-size: 13px;margin-top: 10px;} +.gameCredit span:first-child {background: #4e73df;color: #fff;justify-content: center;border-radius: 5px 5px 0 0;} +.gameCredit span {display: flex;justify-content: space-between;align-items: center;padding: 5px;} +.gameCredit input {border: 0;width: 50px;text-align: center;} +.gameCredit em {cursor: pointer;color: #000;} + +.creditPop {} +.creditPopWrap {z-index:99;position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);background: #fff;width: 500px;border: 1px solid #e3e6f0;box-shadow: 0 0.15rem 1.75rem 0 rgb(58 59 69 / 15%);} +.creditPopWrap h4 {display: flex;align-items: center;justify-content: space-between;padding: 10px 20px;color: #56687c;background: #f8fbff;border-bottom: 1px solid #e3e6f0;} +.creditPopWrap h4 a {display: inline-block;background: #f8fbff;color: #0494b4;padding: 5px 10px;width: auto;} +.creditPopWrap .creditPopn {display: flex;align-items: center;gap: 10px;padding-left: 20px;flex-wrap: wrap;} +.creditPopWrap .creditPopn span {width: 50px;} +.creditPopWrap .creditPopn > input {width: calc(100% - 107px);} +.creditPopWrap input {width: calc(100% - 45px);height: 35px;padding: 0 0 0 5px;border: 1px solid #c2cfe0;border-radius: 5px;margin: 20px;} +.creditPopWrap > a {width: calc(100% - 40px);margin: 0 auto;margin-bottom: 20px;} \ No newline at end of file diff --git a/src/main/resources/static/fonts/sunn-main/README.md b/src/main/resources/static/fonts/sunn-main/README.md new file mode 100644 index 0000000..286eb30 --- /dev/null +++ b/src/main/resources/static/fonts/sunn-main/README.md @@ -0,0 +1,107 @@ +# 수트(SUIT) + + + SUIT + + +
+@font-face {
+    font-family: 'SUIT';
+    font-weight: 100;
+    font-style: normal;
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Thin.eot');
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Thin.eot?#iefix') format('embedded-opentype'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Thin.woff2') format('woff2'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Thin.woff') format('woff'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Thin.ttf') format("truetype");
+    font-display: swap;
+}
+@font-face {
+    font-family: 'SUIT';
+    font-weight: 200;
+    font-style: normal;
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-ExtraLight.eot');
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-ExtraLight.eot?#iefix') format('embedded-opentype'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-ExtraLight.woff2') format('woff2'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-ExtraLight.woff') format('woff'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-ExtraLight.ttf') format("truetype");
+    font-display: swap;
+}
+@font-face {
+    font-family: 'SUIT';
+    font-weight: 300;
+    font-style: normal;
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Light.eot');
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Light.eot?#iefix') format('embedded-opentype'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Light.woff2') format('woff2'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Light.woff') format('woff'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Light.ttf') format("truetype");
+    font-display: swap;
+}
+@font-face {
+    font-family: 'SUIT';
+    font-weight: 400;
+    font-style: normal;
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Regular.eot');
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Regular.eot?#iefix') format('embedded-opentype'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Regular.woff2') format('woff2'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Regular.woff') format('woff'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Regular.ttf') format("truetype");
+    font-display: swap;
+}
+@font-face {
+    font-family: 'SUIT';
+    font-weight: 500;
+    font-style: normal;
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Medium.eot');
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Medium.eot?#iefix') format('embedded-opentype'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Medium.woff2') format('woff2'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Medium.woff') format('woff'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Medium.ttf') format("truetype");
+    font-display: swap;
+}
+@font-face {
+    font-family: 'SUIT';
+    font-weight: 600;
+    font-style: normal;
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-SemiBold.eot');
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-SemiBold.eot?#iefix') format('embedded-opentype'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-SemiBold.woff2') format('woff2'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-SemiBold.woff') format('woff'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-SemiBold.ttf') format("truetype");
+    font-display: swap;
+}
+@font-face {
+    font-family: 'SUIT';
+    font-weight: 700;
+    font-style: normal;
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Bold.eot');
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Bold.eot?#iefix') format('embedded-opentype'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Bold.woff2') format('woff2'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Bold.woff') format('woff'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Bold.ttf') format("truetype");
+    font-display: swap;
+}
+@font-face {
+    font-family: 'SUIT';
+    font-weight: 800;
+    font-style: normal;
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-ExtraBold.eot');
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-ExtraBold.eot?#iefix') format('embedded-opentype'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-ExtraBold.woff2') format('woff2'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-ExtraBold.woff') format('woff'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-ExtraBold.ttf') format("truetype");
+    font-display: swap;
+}
+@font-face {
+    font-family: 'SUIT';
+    font-weight: 900;
+    font-style: normal;
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Heavy.eot');
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Heavy.eot?#iefix') format('embedded-opentype'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Heavy.woff2') format('woff2'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Heavy.woff') format('woff'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Heavy.ttf') format("truetype");
+    font-display: swap;
+}
+
diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Bold.eot b/src/main/resources/static/fonts/sunn-main/SUIT-Bold.eot new file mode 100644 index 0000000..9ef7f87 Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-Bold.eot differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Bold.otf b/src/main/resources/static/fonts/sunn-main/SUIT-Bold.otf new file mode 100644 index 0000000..48390d0 Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-Bold.otf differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Bold.svg b/src/main/resources/static/fonts/sunn-main/SUIT-Bold.svg new file mode 100644 index 0000000..b705dc1 --- /dev/null +++ b/src/main/resources/static/fonts/sunn-main/SUIT-Bold.svg @@ -0,0 +1,8488 @@ + + + + +Created by FontForge 20170731 at Thu Jan 20 04:13:54 2022 + By Aleksey,,, +Copyright (c) 2022 Sunn. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Bold.ttf b/src/main/resources/static/fonts/sunn-main/SUIT-Bold.ttf new file mode 100644 index 0000000..e83ad3e Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-Bold.ttf differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Bold.woff b/src/main/resources/static/fonts/sunn-main/SUIT-Bold.woff new file mode 100644 index 0000000..932091b Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-Bold.woff differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Bold.woff2 b/src/main/resources/static/fonts/sunn-main/SUIT-Bold.woff2 new file mode 100644 index 0000000..36fccff Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-Bold.woff2 differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-ExtraBold.eot b/src/main/resources/static/fonts/sunn-main/SUIT-ExtraBold.eot new file mode 100644 index 0000000..0306f2e Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-ExtraBold.eot differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-ExtraBold.otf b/src/main/resources/static/fonts/sunn-main/SUIT-ExtraBold.otf new file mode 100644 index 0000000..48cb30d Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-ExtraBold.otf differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-ExtraBold.svg b/src/main/resources/static/fonts/sunn-main/SUIT-ExtraBold.svg new file mode 100644 index 0000000..408b6f4 --- /dev/null +++ b/src/main/resources/static/fonts/sunn-main/SUIT-ExtraBold.svg @@ -0,0 +1,8489 @@ + + + + +Created by FontForge 20170731 at Thu Jan 20 04:13:54 2022 + By Aleksey,,, +Copyright (c) 2022 Sunn. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-ExtraBold.ttf b/src/main/resources/static/fonts/sunn-main/SUIT-ExtraBold.ttf new file mode 100644 index 0000000..4aa3d30 Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-ExtraBold.ttf differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-ExtraBold.woff b/src/main/resources/static/fonts/sunn-main/SUIT-ExtraBold.woff new file mode 100644 index 0000000..bdac27a Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-ExtraBold.woff differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-ExtraBold.woff2 b/src/main/resources/static/fonts/sunn-main/SUIT-ExtraBold.woff2 new file mode 100644 index 0000000..40f298e Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-ExtraBold.woff2 differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-ExtraLight.eot b/src/main/resources/static/fonts/sunn-main/SUIT-ExtraLight.eot new file mode 100644 index 0000000..66cbe5c Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-ExtraLight.eot differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-ExtraLight.otf b/src/main/resources/static/fonts/sunn-main/SUIT-ExtraLight.otf new file mode 100644 index 0000000..10b64a1 Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-ExtraLight.otf differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-ExtraLight.svg b/src/main/resources/static/fonts/sunn-main/SUIT-ExtraLight.svg new file mode 100644 index 0000000..bba2711 --- /dev/null +++ b/src/main/resources/static/fonts/sunn-main/SUIT-ExtraLight.svg @@ -0,0 +1,8614 @@ + + + + +Created by FontForge 20170731 at Thu Jan 20 04:13:52 2022 + By Aleksey,,, +Copyright (c) 2022 Sunn. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-ExtraLight.ttf b/src/main/resources/static/fonts/sunn-main/SUIT-ExtraLight.ttf new file mode 100644 index 0000000..9d3ec9f Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-ExtraLight.ttf differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-ExtraLight.woff b/src/main/resources/static/fonts/sunn-main/SUIT-ExtraLight.woff new file mode 100644 index 0000000..f4600f9 Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-ExtraLight.woff differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-ExtraLight.woff2 b/src/main/resources/static/fonts/sunn-main/SUIT-ExtraLight.woff2 new file mode 100644 index 0000000..697a8ca Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-ExtraLight.woff2 differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Heavy.eot b/src/main/resources/static/fonts/sunn-main/SUIT-Heavy.eot new file mode 100644 index 0000000..888eb85 Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-Heavy.eot differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Heavy.otf b/src/main/resources/static/fonts/sunn-main/SUIT-Heavy.otf new file mode 100644 index 0000000..a706c1a Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-Heavy.otf differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Heavy.svg b/src/main/resources/static/fonts/sunn-main/SUIT-Heavy.svg new file mode 100644 index 0000000..f5370dc --- /dev/null +++ b/src/main/resources/static/fonts/sunn-main/SUIT-Heavy.svg @@ -0,0 +1,8334 @@ + + + + +Created by FontForge 20170731 at Thu Jan 20 04:13:57 2022 + By Aleksey,,, +Copyright (c) 2022 Sunn. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Heavy.ttf b/src/main/resources/static/fonts/sunn-main/SUIT-Heavy.ttf new file mode 100644 index 0000000..3696746 Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-Heavy.ttf differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Heavy.woff b/src/main/resources/static/fonts/sunn-main/SUIT-Heavy.woff new file mode 100644 index 0000000..b92934f Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-Heavy.woff differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Heavy.woff2 b/src/main/resources/static/fonts/sunn-main/SUIT-Heavy.woff2 new file mode 100644 index 0000000..cff23e6 Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-Heavy.woff2 differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Light.eot b/src/main/resources/static/fonts/sunn-main/SUIT-Light.eot new file mode 100644 index 0000000..e863957 Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-Light.eot differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Light.otf b/src/main/resources/static/fonts/sunn-main/SUIT-Light.otf new file mode 100644 index 0000000..1ceb4d2 Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-Light.otf differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Light.svg b/src/main/resources/static/fonts/sunn-main/SUIT-Light.svg new file mode 100644 index 0000000..ff9da30 --- /dev/null +++ b/src/main/resources/static/fonts/sunn-main/SUIT-Light.svg @@ -0,0 +1,8600 @@ + + + + +Created by FontForge 20170731 at Thu Jan 20 04:13:52 2022 + By Aleksey,,, +Copyright (c) 2022 Sunn. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Light.ttf b/src/main/resources/static/fonts/sunn-main/SUIT-Light.ttf new file mode 100644 index 0000000..021afff Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-Light.ttf differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Light.woff b/src/main/resources/static/fonts/sunn-main/SUIT-Light.woff new file mode 100644 index 0000000..ea817a8 Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-Light.woff differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Light.woff2 b/src/main/resources/static/fonts/sunn-main/SUIT-Light.woff2 new file mode 100644 index 0000000..9aea313 Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-Light.woff2 differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Medium.eot b/src/main/resources/static/fonts/sunn-main/SUIT-Medium.eot new file mode 100644 index 0000000..6885b7e Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-Medium.eot differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Medium.otf b/src/main/resources/static/fonts/sunn-main/SUIT-Medium.otf new file mode 100644 index 0000000..1f2ca9d Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-Medium.otf differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Medium.svg b/src/main/resources/static/fonts/sunn-main/SUIT-Medium.svg new file mode 100644 index 0000000..6b40ed5 --- /dev/null +++ b/src/main/resources/static/fonts/sunn-main/SUIT-Medium.svg @@ -0,0 +1,8544 @@ + + + + +Created by FontForge 20170731 at Thu Jan 20 04:13:56 2022 + By Aleksey,,, +Copyright (c) 2022 Sunn. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Medium.ttf b/src/main/resources/static/fonts/sunn-main/SUIT-Medium.ttf new file mode 100644 index 0000000..68899e0 Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-Medium.ttf differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Medium.woff b/src/main/resources/static/fonts/sunn-main/SUIT-Medium.woff new file mode 100644 index 0000000..021aaa7 Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-Medium.woff differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Medium.woff2 b/src/main/resources/static/fonts/sunn-main/SUIT-Medium.woff2 new file mode 100644 index 0000000..a3a58e5 Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-Medium.woff2 differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Regular.eot b/src/main/resources/static/fonts/sunn-main/SUIT-Regular.eot new file mode 100644 index 0000000..34a4c1b Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-Regular.eot differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Regular.otf b/src/main/resources/static/fonts/sunn-main/SUIT-Regular.otf new file mode 100644 index 0000000..8203fc2 Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-Regular.otf differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Regular.svg b/src/main/resources/static/fonts/sunn-main/SUIT-Regular.svg new file mode 100644 index 0000000..ed8bfec --- /dev/null +++ b/src/main/resources/static/fonts/sunn-main/SUIT-Regular.svg @@ -0,0 +1,8554 @@ + + + + +Created by FontForge 20170731 at Thu Jan 20 04:13:53 2022 + By Aleksey,,, +Copyright (c) 2022 Sunn. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Regular.ttf b/src/main/resources/static/fonts/sunn-main/SUIT-Regular.ttf new file mode 100644 index 0000000..687c774 Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-Regular.ttf differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Regular.woff b/src/main/resources/static/fonts/sunn-main/SUIT-Regular.woff new file mode 100644 index 0000000..416b640 Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-Regular.woff differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Regular.woff2 b/src/main/resources/static/fonts/sunn-main/SUIT-Regular.woff2 new file mode 100644 index 0000000..0c095b2 Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-Regular.woff2 differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-SemiBold.eot b/src/main/resources/static/fonts/sunn-main/SUIT-SemiBold.eot new file mode 100644 index 0000000..3f87ebd Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-SemiBold.eot differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-SemiBold.otf b/src/main/resources/static/fonts/sunn-main/SUIT-SemiBold.otf new file mode 100644 index 0000000..f19d67a Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-SemiBold.otf differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-SemiBold.svg b/src/main/resources/static/fonts/sunn-main/SUIT-SemiBold.svg new file mode 100644 index 0000000..a72bcb3 --- /dev/null +++ b/src/main/resources/static/fonts/sunn-main/SUIT-SemiBold.svg @@ -0,0 +1,8545 @@ + + + + +Created by FontForge 20170731 at Thu Jan 20 04:13:55 2022 + By Aleksey,,, +Copyright (c) 2022 Sunn. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-SemiBold.ttf b/src/main/resources/static/fonts/sunn-main/SUIT-SemiBold.ttf new file mode 100644 index 0000000..6e90e31 Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-SemiBold.ttf differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-SemiBold.woff b/src/main/resources/static/fonts/sunn-main/SUIT-SemiBold.woff new file mode 100644 index 0000000..f436366 Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-SemiBold.woff differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-SemiBold.woff2 b/src/main/resources/static/fonts/sunn-main/SUIT-SemiBold.woff2 new file mode 100644 index 0000000..1550d45 Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-SemiBold.woff2 differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Thin.eot b/src/main/resources/static/fonts/sunn-main/SUIT-Thin.eot new file mode 100644 index 0000000..4fbf88b Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-Thin.eot differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Thin.otf b/src/main/resources/static/fonts/sunn-main/SUIT-Thin.otf new file mode 100644 index 0000000..4de6d74 Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-Thin.otf differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Thin.svg b/src/main/resources/static/fonts/sunn-main/SUIT-Thin.svg new file mode 100644 index 0000000..c9a448c --- /dev/null +++ b/src/main/resources/static/fonts/sunn-main/SUIT-Thin.svg @@ -0,0 +1,8575 @@ + + + + +Created by FontForge 20170731 at Thu Jan 20 04:13:51 2022 + By Aleksey,,, +Copyright (c) 2022 Sunn. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Thin.ttf b/src/main/resources/static/fonts/sunn-main/SUIT-Thin.ttf new file mode 100644 index 0000000..d705b45 Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-Thin.ttf differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Thin.woff b/src/main/resources/static/fonts/sunn-main/SUIT-Thin.woff new file mode 100644 index 0000000..434000e Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-Thin.woff differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT-Thin.woff2 b/src/main/resources/static/fonts/sunn-main/SUIT-Thin.woff2 new file mode 100644 index 0000000..9a75099 Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT-Thin.woff2 differ diff --git a/src/main/resources/static/fonts/sunn-main/SUIT.css b/src/main/resources/static/fonts/sunn-main/SUIT.css new file mode 100644 index 0000000..6328e11 --- /dev/null +++ b/src/main/resources/static/fonts/sunn-main/SUIT.css @@ -0,0 +1,99 @@ +@font-face { + font-family: 'SUIT'; + font-weight: 100; + font-style: normal; + src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Thin.eot'); + src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Thin.eot?#iefix') format('embedded-opentype'), + url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Thin.woff2') format('woff2'), + url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Thin.woff') format('woff'), + url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Thin.ttf') format("truetype"); + font-display: swap; +} +@font-face { + font-family: 'SUIT'; + font-weight: 200; + font-style: normal; + src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-ExtraLight.eot'); + src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-ExtraLight.eot?#iefix') format('embedded-opentype'), + url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-ExtraLight.woff2') format('woff2'), + url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-ExtraLight.woff') format('woff'), + url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-ExtraLight.ttf') format("truetype"); + font-display: swap; +} +@font-face { + font-family: 'SUIT'; + font-weight: 300; + font-style: normal; + src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Light.eot'); + src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Light.eot?#iefix') format('embedded-opentype'), + url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Light.woff2') format('woff2'), + url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Light.woff') format('woff'), + url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Light.ttf') format("truetype"); + font-display: swap; +} +@font-face { + font-family: 'SUIT'; + font-weight: 400; + font-style: normal; + src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Regular.eot'); + src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Regular.eot?#iefix') format('embedded-opentype'), + url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Regular.woff2') format('woff2'), + url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Regular.woff') format('woff'), + url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Regular.ttf') format("truetype"); + font-display: swap; +} +@font-face { + font-family: 'SUIT'; + font-weight: 500; + font-style: normal; + src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Medium.eot'); + src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Medium.eot?#iefix') format('embedded-opentype'), + url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Medium.woff2') format('woff2'), + url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Medium.woff') format('woff'), + url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Medium.ttf') format("truetype"); + font-display: swap; +} +@font-face { + font-family: 'SUIT'; + font-weight: 600; + font-style: normal; + src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-SemiBold.eot'); + src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-SemiBold.eot?#iefix') format('embedded-opentype'), + url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-SemiBold.woff2') format('woff2'), + url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-SemiBold.woff') format('woff'), + url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-SemiBold.ttf') format("truetype"); + font-display: swap; +} +@font-face { + font-family: 'SUIT'; + font-weight: 700; + font-style: normal; + src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Bold.eot'); + src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Bold.eot?#iefix') format('embedded-opentype'), + url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Bold.woff2') format('woff2'), + url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Bold.woff') format('woff'), + url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Bold.ttf') format("truetype"); + font-display: swap; +} +@font-face { + font-family: 'SUIT'; + font-weight: 800; + font-style: normal; + src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-ExtraBold.eot'); + src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-ExtraBold.eot?#iefix') format('embedded-opentype'), + url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-ExtraBold.woff2') format('woff2'), + url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-ExtraBold.woff') format('woff'), + url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-ExtraBold.ttf') format("truetype"); + font-display: swap; +} +@font-face { + font-family: 'SUIT'; + font-weight: 900; + font-style: normal; + src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Heavy.eot'); + src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Heavy.eot?#iefix') format('embedded-opentype'), + url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Heavy.woff2') format('woff2'), + url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Heavy.woff') format('woff'), + url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Heavy.ttf') format("truetype"); + font-display: swap; +} \ No newline at end of file diff --git a/src/main/resources/static/fonts/sunn-main/SUIT.html b/src/main/resources/static/fonts/sunn-main/SUIT.html new file mode 100644 index 0000000..1cfe5c8 --- /dev/null +++ b/src/main/resources/static/fonts/sunn-main/SUIT.html @@ -0,0 +1,890 @@ + + + + + + + Webfontworld + + + + +
+
+ + +
+

웹 폰트 사용하기

+ +
+
+
font-family: 'SUIT';
+
+
+
<link href="https://webfontworld.github.io/sunn/SUIT.css" rel="stylesheet">
+
+
+
@import url('https://webfontworld.github.io/sunn/SUIT.css');
+
+
+
@font-face {
+    font-family: 'SUIT';
+    font-weight: 100;
+    font-style: normal;
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Thin.eot');
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Thin.eot?#iefix') format('embedded-opentype'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Thin.woff2') format('woff2'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Thin.woff') format('woff'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Thin.ttf') format("truetype");
+    font-display: swap;
+}
+@font-face {
+    font-family: 'SUIT';
+    font-weight: 200;
+    font-style: normal;
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-ExtraLight.eot');
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-ExtraLight.eot?#iefix') format('embedded-opentype'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-ExtraLight.woff2') format('woff2'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-ExtraLight.woff') format('woff'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-ExtraLight.ttf') format("truetype");
+    font-display: swap;
+}
+@font-face {
+    font-family: 'SUIT';
+    font-weight: 300;
+    font-style: normal;
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Light.eot');
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Light.eot?#iefix') format('embedded-opentype'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Light.woff2') format('woff2'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Light.woff') format('woff'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Light.ttf') format("truetype");
+    font-display: swap;
+}
+@font-face {
+    font-family: 'SUIT';
+    font-weight: 400;
+    font-style: normal;
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Regular.eot');
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Regular.eot?#iefix') format('embedded-opentype'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Regular.woff2') format('woff2'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Regular.woff') format('woff'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Regular.ttf') format("truetype");
+    font-display: swap;
+}
+@font-face {
+    font-family: 'SUIT';
+    font-weight: 500;
+    font-style: normal;
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Medium.eot');
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Medium.eot?#iefix') format('embedded-opentype'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Medium.woff2') format('woff2'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Medium.woff') format('woff'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Medium.ttf') format("truetype");
+    font-display: swap;
+}
+@font-face {
+    font-family: 'SUIT';
+    font-weight: 600;
+    font-style: normal;
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-SemiBold.eot');
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-SemiBold.eot?#iefix') format('embedded-opentype'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-SemiBold.woff2') format('woff2'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-SemiBold.woff') format('woff'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-SemiBold.ttf') format("truetype");
+    font-display: swap;
+}
+@font-face {
+    font-family: 'SUIT';
+    font-weight: 700;
+    font-style: normal;
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Bold.eot');
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Bold.eot?#iefix') format('embedded-opentype'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Bold.woff2') format('woff2'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Bold.woff') format('woff'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Bold.ttf') format("truetype");
+    font-display: swap;
+}
+@font-face {
+    font-family: 'SUIT';
+    font-weight: 800;
+    font-style: normal;
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-ExtraBold.eot');
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-ExtraBold.eot?#iefix') format('embedded-opentype'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-ExtraBold.woff2') format('woff2'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-ExtraBold.woff') format('woff'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-ExtraBold.ttf') format("truetype");
+    font-display: swap;
+}
+@font-face {
+    font-family: 'SUIT';
+    font-weight: 900;
+    font-style: normal;
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Heavy.eot');
+    src: url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Heavy.eot?#iefix') format('embedded-opentype'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Heavy.woff2') format('woff2'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Heavy.woff') format('woff'),
+        url('https://cdn.jsdelivr.net/gh/webfontworld/sunn/SUIT-Heavy.ttf') format("truetype");
+    font-display: swap;
+}
+
+
+
+
+
+ +
+

폰트 살펴보기 100200300400500600700800900

+
+ + + + + + + + + + + + + +
+
+
+ 수트 + SUIT +
+
+
+ +
+ +
+

font-weight

+ +
    +
  • 이 폰트의 WEIGHT는 여러가지가 있습니다. 이 폰트의 weight는 여러가지가 있습니다. 이 폰트의 두께는 여러가지가 있습니다.
  • +
  • 이 폰트의 WEIGHT는 여러가지가 있습니다. 이 폰트의 weight는 여러가지가 있습니다. 이 폰트의 두께는 여러가지가 있습니다.
  • +
  • 이 폰트의 WEIGHT는 여러가지가 있습니다. 이 폰트의 weight는 여러가지가 있습니다. 이 폰트의 두께는 여러가지가 있습니다.
  • +
  • 이 폰트의 WEIGHT는 여러가지가 있습니다. 이 폰트의 weight는 여러가지가 있습니다. 이 폰트의 두께는 여러가지가 있습니다.
  • +
  • 이 폰트의 WEIGHT는 여러가지가 있습니다. 이 폰트의 weight는 여러가지가 있습니다. 이 폰트의 두께는 여러가지가 있습니다.
  • +
  • 이 폰트의 WEIGHT는 여러가지가 있습니다. 이 폰트의 weight는 여러가지가 있습니다. 이 폰트의 두께는 여러가지가 있습니다.
  • +
  • 이 폰트의 WEIGHT는 여러가지가 있습니다. 이 폰트의 weight는 여러가지가 있습니다. 이 폰트의 두께는 여러가지가 있습니다.
  • +
  • 이 폰트의 WEIGHT는 여러가지가 있습니다. 이 폰트의 weight는 여러가지가 있습니다. 이 폰트의 두께는 여러가지가 있습니다.
  • +
  • 이 폰트의 WEIGHT는 여러가지가 있습니다. 이 폰트의 weight는 여러가지가 있습니다. 이 폰트의 두께는 여러가지가 있습니다.
  • +
+
+ + +
+

font-size 100200300400500600700800900

+ +
    +
  • 가 나 다 라 마 바 사 아 자 차 카 타 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 + 가 나 다 라 마 바 사 아 자 차 카 타 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 가 나 다 라 마 바 + 사 아 자 차 카 타 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 가 나 다 라 마 바 사 아 자 차 카 타 + 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9
  • +
  • 가 나 다 라 마 바 사 아 자 차 카 타 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 + 가 나 다 라 마 바 사 아 자 차 카 타 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 가 나 다 라 마 바 + 사 아 자 차 카 타 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 가 나 다 라 마 바 사 아 자 차 카 타 + 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9
  • +
  • 가 나 다 라 마 바 사 아 자 차 카 타 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 + 가 나 다 라 마 바 사 아 자 차 카 타 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9
  • +
  • 가 나 다 라 마 바 사 아 자 차 카 타 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 + 가 나 다 라 마 바 사 아 자 차 카 타 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9
  • +
  • 가 나 다 라 마 바 사 아 자 차 카 타 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 + 가 나 다 라 마 바 사 아 자 차 카 타 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9
  • +
  • 가 나 다 라 마 바 사 아 자 차 카 타 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 + 가 나 다 라 마 바 사 아 자 차 카 타 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9
  • +
  • 가 나 다 라 마 바 사 아 자 차 카 타 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 + 가 나 다 라 마 바 사 아 자 차 카 타 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9
  • +
  • 가 나 다 라 마 바 사 아 자 차 카 타 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 + 가 나 다 라 마 바 사 아 자 차 카 타 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9
  • +
  • 가 나 다 라 마 바 사 아 자 차 카 타 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 + 가 나 다 라 마 바 사 아 자 차 카 타 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9
  • +
  • 가 나 다 라 마 바 사 아 자 차 카 타 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 + 가 나 다 라 마 바 사 아 자 차 카 타 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9
  • +
  • 가 나 다 라 마 바 사 아 자 차 카 타 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 + 가 나 다 라 마 바 사 아 자 차 카 타 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9
  • +
  • 가 나 다 라 마 바 사 아 자 차 카 타 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 + 가 나 다 라 마 바 사 아 자 차 카 타 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9
  • +
  • 가 나 다 라 마 바 사 아 자 차 카 타 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 + 가 나 다 라 마 바 사 아 자 차 카 타 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9
  • +
  • 가 나 다 라 마 바 사 아 자 차 카 타 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 + 가 나 다 라 마 바 사 아 자 차 카 타 파 하 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9
  • +
+
+ + +
+

Font-layout 100200300400500600700800900

+ +
+
모든 국민은 인간으로서의 존엄과 가치를 가지며, 행복을 추구할 권리를 가진다. 국가는 개인이 가지는 불가침의 기본적 인권을 확인하고 이를 보장할 의무를 진다. 대한민국의 주권은 + 국민에게 있고, 모든 권력은 국민으로부터 나온다.
+
모든 국민은 인간으로서의 존엄과 가치를 가지며, 행복을 추구할 권리를 가진다. 국가는 개인이 가지는 불가침의 기본적 인권을 확인하고 이를 보장할 의무를 진다. 대한민국의 주권은 + 국민에게 있고, 모든 권력은 국민으로부터 나온다.
+
모든 국민은 인간으로서의 존엄과 가치를 가지며, 행복을 추구할 권리를 가진다. 국가는 개인이 가지는 불가침의 기본적 인권을 확인하고 이를 보장할 의무를 진다. 대한민국의 주권은 + 국민에게 있고, 모든 권력은 국민으로부터 나온다.
+
모든 국민은 인간으로서의 존엄과 가치를 가지며, 행복을 추구할 권리를 가진다. 국가는 개인이 가지는 불가침의 기본적 인권을 확인하고 이를 보장할 의무를 진다. + 대한민국의 주권은 국민에게 있고, 모든 권력은 국민으로부터 나온다.
+
모든 국민은 인간으로서의 존엄과 가치를 가지며, 행복을 추구할 권리를 가진다. 국가는 개인이 가지는 불가침의 기본적 인권을 확인하고 이를 보장할 의무를 진다. 대한민국의 주권은 + 국민에게 있고, 모든 권력은 국민으로부터 나온다.
+
모든 국민은 인간으로서의 존엄과 가치를 가지며, 행복을 추구할 권리를 가진다. 국가는 개인이 가지는 불가침의 기본적 인권을 확인하고 이를 보장할 의무를 진다. 대한민국의 주권은 + 국민에게 있고, 모든 권력은 국민으로부터 나온다.
+
모든 국민은 인간으로서의 존엄과 가치를 가지며, 행복을 추구할 권리를 가진다. 국가는 개인이 가지는 불가침의 기본적 인권을 확인하고 이를 보장할 의무를 진다. + 대한민국의 주권은 국민에게 있고, 모든 권력은 국민으로부터 나온다.
+
모든 국민은 인간으로서의 존엄과 가치를 가지며, 행복을 추구할 권리를 가진다. 국가는 개인이 가지는 불가침의 기본적 인권을 확인하고 이를 보장할 의무를 진다. 대한민국의 주권은 + 국민에게 있고, 모든 권력은 국민으로부터 나온다. 모든 국민은 신체의 자유를 가진다. 누구든지 법률에 의하지 아니하고는 체포ㆍ구속ㆍ압수ㆍ수색 또는 심문을 받지 아니하며, 법률과 적법한 절차에 의하지 + 아니하고는 처벌ㆍ보안처분 또는 강제노역을 받지 아니한다.
+
모든 국민은 인간으로서의 존엄과 가치를 가지며, 행복을 추구할 권리를 가진다. 국가는 개인이 가지는 불가침의 기본적 인권을 확인하고 이를 보장할 의무를 진다. + 대한민국의 주권은 국민에게 있고, 모든 권력은 국민으로부터 나온다. 모든 국민은 신체의 자유를 가진다. 누구든지 법률에 의하지 아니하고는 체포ㆍ구속ㆍ압수ㆍ수색 또는 심문을 받지 아니하며, 법률과 적법한 + 절차에 의하지 아니하고는 처벌ㆍ보안처분 또는 강제노역을 받지 아니한다.
+
모든 국민은 인간으로서의 존엄과 가치를 가지며, 행복을 추구할 권리를 가진다. 국가는 개인이 가지는 불가침의 기본적 인권을 확인하고 이를 보장할 의무를 진다. 대한민국의 주권은 + 국민에게 있고, 모든 권력은 국민으로부터 나온다. 모든 국민은 신체의 자유를 가진다. 누구든지 법률에 의하지 아니하고는 체포ㆍ구속ㆍ압수ㆍ수색 또는 심문을 받지 아니하며, 법률과 적법한 절차에 의하지 + 아니하고는 처벌ㆍ보안처분 또는 강제노역을 받지 아니한다. 모든 국민은 행위시의 법률에 의하여 범죄를 구성하지 아니하는 행위로 소추되지 아니하며, 동일한 범죄에 대하여 거듭 처벌받지 아니한다.
+
+
+ +
+ +
+
+

라이센스 사용 범위 확인하기

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
카테고리사용 범위허용여부
인쇄브로슈어, 카탈로그, DM, 전단지, 포스터, 패키지, 캘린더 등 인쇄물
책, 만화책, 잡지, 정기간행물, 신문 등 출판물
간판, 현수막, 판넬 등 제작물
신문광고, 잡지광고, 차량광고 등 광고물
인쇄 및 문서 공유를 위한 PDF 파일 제작
웹사이트웹페이지, 광고 배너, 메일, E-브로슈어 등
웹서버용 폰트
영상방송 및 영상물 자막
TV-CF, 온라인 영상광고
영화(DVD / 비디오), 오프닝, 엔딩크레딧 자막
개인 UCC 및 홍보물
E-Learning 콘텐츠, 온라인 동영상강좌, 플래시 강좌
포장지판매용 상품의 패키지
임베딩웹사이트 및 프로그램 서버 내 폰트 탑재, E-book 제작
BI/CI회사명, 브랜드명, 상품명, 로고, 마크, 슬로건, 캐치프레이즈
OFL폰트 파일의 수정, 편집 및 재배포금지
폰트 파일의 유료 판매금지
용도개인적 용도 사용
상업적 용도 사용
출처출처 표시권장
+
+
    +
  • SUIT―수트는 오픈소스입니다. SIL 오픈 폰트 라이선스에 따라 자유롭게 사용하고 수정 및 재배포 할 수 있습니다.
  • +
  • 제공되는 모든 서체의 지적 재산권을 포함한 모든 권리는 제작사에 있으니, 사용하기 전에 제작사 사이트에 가셔서 꼭 확인하시길 바랍니다.
  • +
+
+ +
+ +
+

웹 폰트 호환성

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
익스플로러엣지파이어폭스사파리오페라크롬웨일
TTF
OTF
WOFF
WOFF2지원안함
SVG지원안함지원안함지원안함지원안함지원안함지원안함
EOT지원안함지원안함지원안함지원안함지원안함
+
+ + +
+ + + + + + + \ No newline at end of file diff --git a/src/main/resources/static/fonts/sunn-main/SUIT.jpg b/src/main/resources/static/fonts/sunn-main/SUIT.jpg new file mode 100644 index 0000000..e5daf1f Binary files /dev/null and b/src/main/resources/static/fonts/sunn-main/SUIT.jpg differ diff --git a/src/main/resources/static/html/health.html b/src/main/resources/static/html/health.html new file mode 100644 index 0000000..080655f --- /dev/null +++ b/src/main/resources/static/html/health.html @@ -0,0 +1 @@ +alive \ No newline at end of file diff --git a/src/main/resources/static/html/jquery-2.2.4.min.js b/src/main/resources/static/html/jquery-2.2.4.min.js new file mode 100644 index 0000000..4024b66 --- /dev/null +++ b/src/main/resources/static/html/jquery-2.2.4.min.js @@ -0,0 +1,4 @@ +/*! jQuery v2.2.4 | (c) jQuery Foundation | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=a.document,e=c.slice,f=c.concat,g=c.push,h=c.indexOf,i={},j=i.toString,k=i.hasOwnProperty,l={},m="2.2.4",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return e.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:e.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a){return n.each(this,a)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(e.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:g,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){var b=a&&a.toString();return!n.isArray(a)&&b-parseFloat(b)+1>=0},isPlainObject:function(a){var b;if("object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;if(a.constructor&&!k.call(a,"constructor")&&!k.call(a.constructor.prototype||{},"isPrototypeOf"))return!1;for(b in a);return void 0===b||k.call(a,b)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?i[j.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=d.createElement("script"),b.text=a,d.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(s(a)){for(c=a.length;c>d;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):g.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:h.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,g=0,h=[];if(s(a))for(d=a.length;d>g;g++)e=b(a[g],g,c),null!=e&&h.push(e);else for(g in a)e=b(a[g],g,c),null!=e&&h.push(e);return f.apply([],h)},guid:1,proxy:function(a,b){var c,d,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(d=e.call(arguments,2),f=function(){return a.apply(b||this,d.concat(e.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:l}),"function"==typeof Symbol&&(n.fn[Symbol.iterator]=c[Symbol.iterator]),n.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){i["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=!!a&&"length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ga(),z=ga(),A=ga(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+M+"))|)"+L+"*\\]",O=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+N+")*)|.*)\\)|)",P=new RegExp(L+"+","g"),Q=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),R=new RegExp("^"+L+"*,"+L+"*"),S=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),T=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),U=new RegExp(O),V=new RegExp("^"+M+"$"),W={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M+"|[*])"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},X=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Z=/^[^{]+\{\s*\[native \w/,$=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,_=/[+~]/,aa=/'|\\/g,ba=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),ca=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},da=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(ea){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fa(a,b,d,e){var f,h,j,k,l,o,r,s,w=b&&b.ownerDocument,x=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==x&&9!==x&&11!==x)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==x&&(o=$.exec(a)))if(f=o[1]){if(9===x){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(w&&(j=w.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(o[2])return H.apply(d,b.getElementsByTagName(a)),d;if((f=o[3])&&c.getElementsByClassName&&b.getElementsByClassName)return H.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==x)w=b,s=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(aa,"\\$&"):b.setAttribute("id",k=u),r=g(a),h=r.length,l=V.test(k)?"#"+k:"[id='"+k+"']";while(h--)r[h]=l+" "+qa(r[h]);s=r.join(","),w=_.test(a)&&oa(b.parentNode)||b}if(s)try{return H.apply(d,w.querySelectorAll(s)),d}catch(y){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(Q,"$1"),b,d,e)}function ga(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ha(a){return a[u]=!0,a}function ia(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ja(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function ka(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function la(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function na(a){return ha(function(b){return b=+b,ha(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function oa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=fa.support={},f=fa.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fa.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ia(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ia(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Z.test(n.getElementsByClassName),c.getById=ia(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return"undefined"!=typeof b.getElementsByClassName&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=Z.test(n.querySelectorAll))&&(ia(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ia(function(a){var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Z.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ia(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",O)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Z.test(o.compareDocumentPosition),t=b||Z.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return ka(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?ka(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},fa.matches=function(a,b){return fa(a,null,null,b)},fa.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(T,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fa(b,n,null,[a]).length>0},fa.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fa.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fa.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fa.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fa.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fa.selectors={cacheLength:50,createPseudo:ha,match:W,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ba,ca),a[3]=(a[3]||a[4]||a[5]||"").replace(ba,ca),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fa.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fa.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return W.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&U.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ba,ca).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fa.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(P," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fa.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ha(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ha(function(a){var b=[],c=[],d=h(a.replace(Q,"$1"));return d[u]?ha(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ha(function(a){return function(b){return fa(a,b).length>0}}),contains:ha(function(a){return a=a.replace(ba,ca),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ha(function(a){return V.test(a||"")||fa.error("unsupported lang: "+a),a=a.replace(ba,ca).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Y.test(a.nodeName)},input:function(a){return X.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:na(function(){return[0]}),last:na(function(a,b){return[b-1]}),eq:na(function(a,b,c){return[0>c?c+b:c]}),even:na(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:na(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:na(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:na(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function ra(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j,k=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(j=b[u]||(b[u]={}),i=j[b.uniqueID]||(j[b.uniqueID]={}),(h=i[d])&&h[0]===w&&h[1]===f)return k[2]=h[2];if(i[d]=k,k[2]=a(b,c,g))return!0}}}function sa(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ta(a,b,c){for(var d=0,e=b.length;e>d;d++)fa(a,b[d],c);return c}function ua(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function va(a,b,c,d,e,f){return d&&!d[u]&&(d=va(d)),e&&!e[u]&&(e=va(e,f)),ha(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ta(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ua(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ua(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ua(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function wa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ra(function(a){return a===b},h,!0),l=ra(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[ra(sa(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return va(i>1&&sa(m),i>1&&qa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(Q,"$1"),c,e>i&&wa(a.slice(i,e)),f>e&&wa(a=a.slice(e)),f>e&&qa(a))}m.push(c)}return sa(m)}function xa(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=F.call(i));u=ua(u)}H.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&fa.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ha(f):f}return h=fa.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xa(e,d)),f.selector=a}return f},i=fa.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ba,ca),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=W.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ba,ca),_.test(j[0].type)&&oa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qa(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||_.test(a)&&oa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ia(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ia(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ja("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ia(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ja("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ia(function(a){return null==a.getAttribute("disabled")})||ja(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fa}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.uniqueSort=n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},v=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},w=n.expr.match.needsContext,x=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,y=/^.[^:#\[\.,]*$/;function z(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(y.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return h.call(b,a)>-1!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(z(this,a||[],!1))},not:function(a){return this.pushStack(z(this,a||[],!0))},is:function(a){return!!z(this,"string"==typeof a&&w.test(a)?n(a):a||[],!1).length}});var A,B=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=n.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||A,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:B.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),x.test(e[1])&&n.isPlainObject(b))for(e in b)n.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&f.parentNode&&(this.length=1,this[0]=f),this.context=d,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?void 0!==c.ready?c.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};C.prototype=n.fn,A=n(d);var D=/^(?:parents|prev(?:Until|All))/,E={children:!0,contents:!0,next:!0,prev:!0};n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=w.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?h.call(n(a),this[0]):h.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.uniqueSort(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function F(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return u(a,"parentNode")},parentsUntil:function(a,b,c){return u(a,"parentNode",c)},next:function(a){return F(a,"nextSibling")},prev:function(a){return F(a,"previousSibling")},nextAll:function(a){return u(a,"nextSibling")},prevAll:function(a){return u(a,"previousSibling")},nextUntil:function(a,b,c){return u(a,"nextSibling",c)},prevUntil:function(a,b,c){return u(a,"previousSibling",c)},siblings:function(a){return v((a.parentNode||{}).firstChild,a)},children:function(a){return v(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(E[a]||n.uniqueSort(e),D.test(a)&&e.reverse()),this.pushStack(e)}});var G=/\S+/g;function H(a){var b={};return n.each(a.match(G)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?H(a):n.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),h>=c&&h--}),this},has:function(a){return a?n.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().progress(c.notify).done(c.resolve).fail(c.reject):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=e.call(arguments),d=c.length,f=1!==d||a&&n.isFunction(a.promise)?d:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?e.call(arguments):d,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(d>1)for(i=new Array(d),j=new Array(d),k=new Array(d);d>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().progress(h(b,j,i)).done(h(b,k,c)).fail(g.reject):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(d,[n]),n.fn.triggerHandler&&(n(d).triggerHandler("ready"),n(d).off("ready"))))}});function J(){d.removeEventListener("DOMContentLoaded",J),a.removeEventListener("load",J),n.ready()}n.ready.promise=function(b){return I||(I=n.Deferred(),"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(n.ready):(d.addEventListener("DOMContentLoaded",J),a.addEventListener("load",J))),I.promise(b)},n.ready.promise();var K=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)K(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},L=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function M(){this.expando=n.expando+M.uid++}M.uid=1,M.prototype={register:function(a,b){var c=b||{};return a.nodeType?a[this.expando]=c:Object.defineProperty(a,this.expando,{value:c,writable:!0,configurable:!0}),a[this.expando]},cache:function(a){if(!L(a))return{};var b=a[this.expando];return b||(b={},L(a)&&(a.nodeType?a[this.expando]=b:Object.defineProperty(a,this.expando,{value:b,configurable:!0}))),b},set:function(a,b,c){var d,e=this.cache(a);if("string"==typeof b)e[b]=c;else for(d in b)e[d]=b[d];return e},get:function(a,b){return void 0===b?this.cache(a):a[this.expando]&&a[this.expando][b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=a[this.expando];if(void 0!==f){if(void 0===b)this.register(a);else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in f?d=[b,e]:(d=e,d=d in f?[d]:d.match(G)||[])),c=d.length;while(c--)delete f[d[c]]}(void 0===b||n.isEmptyObject(f))&&(a.nodeType?a[this.expando]=void 0:delete a[this.expando])}},hasData:function(a){var b=a[this.expando];return void 0!==b&&!n.isEmptyObject(b)}};var N=new M,O=new M,P=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Q=/[A-Z]/g;function R(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(Q,"-$&").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:P.test(c)?n.parseJSON(c):c; +}catch(e){}O.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return O.hasData(a)||N.hasData(a)},data:function(a,b,c){return O.access(a,b,c)},removeData:function(a,b){O.remove(a,b)},_data:function(a,b,c){return N.access(a,b,c)},_removeData:function(a,b){N.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=O.get(f),1===f.nodeType&&!N.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),R(f,d,e[d])));N.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){O.set(this,a)}):K(this,function(b){var c,d;if(f&&void 0===b){if(c=O.get(f,a)||O.get(f,a.replace(Q,"-$&").toLowerCase()),void 0!==c)return c;if(d=n.camelCase(a),c=O.get(f,d),void 0!==c)return c;if(c=R(f,d,void 0),void 0!==c)return c}else d=n.camelCase(a),this.each(function(){var c=O.get(this,d);O.set(this,d,b),a.indexOf("-")>-1&&void 0!==c&&O.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){O.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=N.get(a,b),c&&(!d||n.isArray(c)?d=N.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return N.get(a,c)||N.access(a,c,{empty:n.Callbacks("once memory").add(function(){N.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length",""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};$.optgroup=$.option,$.tbody=$.tfoot=$.colgroup=$.caption=$.thead,$.th=$.td;function _(a,b){var c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function aa(a,b){for(var c=0,d=a.length;d>c;c++)N.set(a[c],"globalEval",!b||N.get(b[c],"globalEval"))}var ba=/<|&#?\w+;/;function ca(a,b,c,d,e){for(var f,g,h,i,j,k,l=b.createDocumentFragment(),m=[],o=0,p=a.length;p>o;o++)if(f=a[o],f||0===f)if("object"===n.type(f))n.merge(m,f.nodeType?[f]:f);else if(ba.test(f)){g=g||l.appendChild(b.createElement("div")),h=(Y.exec(f)||["",""])[1].toLowerCase(),i=$[h]||$._default,g.innerHTML=i[1]+n.htmlPrefilter(f)+i[2],k=i[0];while(k--)g=g.lastChild;n.merge(m,g.childNodes),g=l.firstChild,g.textContent=""}else m.push(b.createTextNode(f));l.textContent="",o=0;while(f=m[o++])if(d&&n.inArray(f,d)>-1)e&&e.push(f);else if(j=n.contains(f.ownerDocument,f),g=_(l.appendChild(f),"script"),j&&aa(g),c){k=0;while(f=g[k++])Z.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),l.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="",l.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var da=/^key/,ea=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,fa=/^([^.]*)(?:\.(.+)|)/;function ga(){return!0}function ha(){return!1}function ia(){try{return d.activeElement}catch(a){}}function ja(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)ja(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=ha;else if(!e)return a;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=N.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return"undefined"!=typeof n&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(G)||[""],j=b.length;while(j--)h=fa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=N.hasData(a)&&N.get(a);if(r&&(i=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=fa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&N.remove(a,"handle events")}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(N.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())a.rnamespace&&!a.rnamespace.test(g.namespace)||(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!==this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,la=/\s*$/g;function pa(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function qa(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function ra(a){var b=na.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function sa(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(N.hasData(a)&&(f=N.access(a),g=N.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}O.hasData(a)&&(h=O.access(a),i=n.extend({},h),O.set(b,i))}}function ta(a,b){var c=b.nodeName.toLowerCase();"input"===c&&X.test(a.type)?b.checked=a.checked:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}function ua(a,b,c,d){b=f.apply([],b);var e,g,h,i,j,k,m=0,o=a.length,p=o-1,q=b[0],r=n.isFunction(q);if(r||o>1&&"string"==typeof q&&!l.checkClone&&ma.test(q))return a.each(function(e){var f=a.eq(e);r&&(b[0]=q.call(this,e,f.html())),ua(f,b,c,d)});if(o&&(e=ca(b,a[0].ownerDocument,!1,a,d),g=e.firstChild,1===e.childNodes.length&&(e=g),g||d)){for(h=n.map(_(e,"script"),qa),i=h.length;o>m;m++)j=e,m!==p&&(j=n.clone(j,!0,!0),i&&n.merge(h,_(j,"script"))),c.call(a[m],j,m);if(i)for(k=h[h.length-1].ownerDocument,n.map(h,ra),m=0;i>m;m++)j=h[m],Z.test(j.type||"")&&!N.access(j,"globalEval")&&n.contains(k,j)&&(j.src?n._evalUrl&&n._evalUrl(j.src):n.globalEval(j.textContent.replace(oa,"")))}return a}function va(a,b,c){for(var d,e=b?n.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||n.cleanData(_(d)),d.parentNode&&(c&&n.contains(d.ownerDocument,d)&&aa(_(d,"script")),d.parentNode.removeChild(d));return a}n.extend({htmlPrefilter:function(a){return a.replace(ka,"<$1>")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=_(h),f=_(a),d=0,e=f.length;e>d;d++)ta(f[d],g[d]);if(b)if(c)for(f=f||_(a),g=g||_(h),d=0,e=f.length;e>d;d++)sa(f[d],g[d]);else sa(a,h);return g=_(h,"script"),g.length>0&&aa(g,!i&&_(a,"script")),h},cleanData:function(a){for(var b,c,d,e=n.event.special,f=0;void 0!==(c=a[f]);f++)if(L(c)){if(b=c[N.expando]){if(b.events)for(d in b.events)e[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);c[N.expando]=void 0}c[O.expando]&&(c[O.expando]=void 0)}}}),n.fn.extend({domManip:ua,detach:function(a){return va(this,a,!0)},remove:function(a){return va(this,a)},text:function(a){return K(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return ua(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=pa(this,a);b.appendChild(a)}})},prepend:function(){return ua(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=pa(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return ua(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return ua(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(_(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return K(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!la.test(a)&&!$[(Y.exec(a)||["",""])[1].toLowerCase()]){a=n.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(_(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return ua(this,arguments,function(b){var c=this.parentNode;n.inArray(this,a)<0&&(n.cleanData(_(this)),c&&c.replaceChild(b,this))},a)}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),f=e.length-1,h=0;f>=h;h++)c=h===f?this:this.clone(!0),n(e[h])[b](c),g.apply(d,c.get());return this.pushStack(d)}});var wa,xa={HTML:"block",BODY:"block"};function ya(a,b){var c=n(b.createElement(a)).appendTo(b.body),d=n.css(c[0],"display");return c.detach(),d}function za(a){var b=d,c=xa[a];return c||(c=ya(a,b),"none"!==c&&c||(wa=(wa||n(" + + + + diff --git a/src/main/resources/templates/admin/payments.html b/src/main/resources/templates/admin/payments.html new file mode 100644 index 0000000..d353a6e --- /dev/null +++ b/src/main/resources/templates/admin/payments.html @@ -0,0 +1,104 @@ + + + + + +
+
+

유저 지급 내역

+
+ +
+ +
+
    +
  • +
    +
    + +
    + +
    +
  • +
  • +
    +
    + +
    + +
    +
  • +
  • +
    +
    + +
    + +
    +
  • +
  • +
    +
    + +
    + + +
    +
  • +
  • + + 전체검색 + +
  • +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
번호주는 에이전시명받는 유저명타입지급 금액지급 전 잔액지급 후 잔액처리 시각상태관리
+
+
+
+ +
+ +
diff --git a/src/main/resources/templates/admin/popup.html b/src/main/resources/templates/admin/popup.html new file mode 100644 index 0000000..0e49d94 --- /dev/null +++ b/src/main/resources/templates/admin/popup.html @@ -0,0 +1,1589 @@ + + + + + + + + +
+
+

에이전시 1234567 의 정보

+
+
    + + + +
+
+
+
+
에이전시 정보
+ 저장 +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
아이디moka
도메인 +
비밀번호
Credit0
CA0
CB0
SA0
SB0
Credit 서브포인트0
보유포인트-
에이전시등급3
에이전시명
보험금0
보험서브포인트0
보유머니-
총 회원 수
+
+
+
+ +
+ 크레딧 신청내역 + 크레딧 환전내역 + 크레딧 서브포인트 내역 + 크레딧 지급 +
+

크레딧 지급닫기

+
+ 크레딧 + +
+ +
+ CA + +
+
+ CB + +
+
+ SA + +
+
+ SB + +
+
+
+ OTP + +
+ 지급 +
+ 크레딧 회수 + + 포인트 지급 +
+

포인트 지급닫기

+
+ 포인트 + +
+
+ OTP + +
+ 지급 +
+ 포인트 회수 + +
+ +
+
+
에이전시 통계
+ 저장 +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
총 입금0
총 보험포인트0
총 베팅금0
총 출금0
총 게임머니0
총 윈루즈0
+
+
+
+ +
+
+
메모
+ 저장 +
+
+
+
+ +
+
+
+
+ +
+
+
Credit 설정
+ 저장 +
+
+
+ + + + + + + + + + + + +
Credit 구매 수수료율 + %
+
+
+
+ +
+
+
+
게임별 Credit수수료율 설정
+ + 일괄적용 + + 저장 +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
CpnyCredit수수료롤링요율게임이용여부
+ 에볼루션 % + % +
+ + +
+
+
+
+
+
+
+
+
+
기본 정보
+
+ 저장 +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
소속 에이전시 +
+ 토브로@tobro +
+ + +
+
+ +
+ no.1@no.1 +
+ + +
+
+
아이디no.1
비밀번호비밀번호 변경
API KEY + + API KEY는 개발에 필요한 정보입니다. 개발자에게 전달해주세요. +
API 호출 허용 IP 설정 +
+ + + 변경 +
+ +
관리자 접속 허용 아이피 +
+ + + 저장 +
+ +
Callback URL + + 정확한 주소값을 전부 입력해주세요. (http 혹 https 사용인지 정확하게 입력) +
계좌 번호 + +
현재 보유 금액1,000,000
하부 에이전시 현재 총 보유 금액1,000,000
요율0 %
총 지급받은 금액1,000,000
총 충전받은 금액1,000,000
총 지급해준 금액1,000,000
총 충전해준 금액1,000,000
하부 에이전시 수0
하부 유저 수0
가입 시각22-01-29 02:01
하이브리드 전환 금액 설정 +
    +
  • 전환 기준 금액 : 저장
  • +
+
+
+
+
+ + + + + + + + +
+ +
+
+
+
에이전시 의 게임회사 연결설정
+
+
+
+
    + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
게임명벤더사 선택설정 요율저장
에볼루션 + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
게임명벤더사 선택현재 나의 요율저장
에볼루션 + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
게임명벤더사 선택현재 나의 요율저장
에볼루션 + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
게임명벤더사 선택현재 나의 요율저장
에볼루션 + + +
+
+
+
+
+
+
diff --git a/src/main/resources/templates/admin/popup2.html b/src/main/resources/templates/admin/popup2.html new file mode 100644 index 0000000..d02da89 --- /dev/null +++ b/src/main/resources/templates/admin/popup2.html @@ -0,0 +1,1345 @@ + + + + + + + + +
+
+

에이전시 1234567 의 정보

+
+
    + + + +
+
+
+
+
에이전시 정보
+ 저장 +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
아이디moka
도메인 +
비밀번호
Credit0
Credit 서브포인트0
보유포인트-
에이전시등급3
에이전시명
보험금0
보험서브포인트0
보유머니-
총 회원 수
+
+
+
+ + + +
+
+
에이전시 통계
+ 저장 +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
총 입금0
총 보험포인트0
총 베팅금0
총 출금0
총 게임머니0
총 윈루즈0
+
+
+
+ +
+
+
메모
+ 저장 +
+
+
+
+ +
+
+
+
+ +
+
+
Credit 설정
+ 저장 +
+
+
+ + + + + + + + + + + + +
Credit 구매 수수료율 + %
+
+
+
+ +
+
+
+
게임별 Credit수수료율 설정
+ + 일괄적용 + + 저장 +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
CpnyCredit수수료롤링요율게임이용여부
+ 에볼루션 % + % +
+ + +
+
+
+
+
+
+
+
+
+
기본 정보
+
+
+ + +
+ 저장 +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
번호1907
분류총판
타입병행
소속 에이전시 +
+ 토브로@tobro +
+ + +
+
+ +
+ no.1@no.1 +
+ + +
+
+
아이디no.1
닉네임no.1
비밀번호비밀번호 변경
API KEY + + API KEY는 개발에 필요한 정보입니다. 개발자에게 전달해주세요. +
API 호출 허용 IP 설정 +
+ + + 변경 +
+ +
관리자 접속 허용 아이피 +
+ + + 저장 +
+ +
Callback URL + + 정확한 주소값을 전부 입력해주세요. (http 혹 https 사용인지 정확하게 입력) +
계좌 번호 + +
현재 보유 금액1,000,000
하부 에이전시 현재 총 보유 금액1,000,000
요율0 %
총 지급받은 금액1,000,000
총 충전받은 금액1,000,000
총 지급해준 금액1,000,000
총 충전해준 금액1,000,000
하부 에이전시 수0
하부 유저 수0
가입 시각22-01-29 02:01
기본설정기본설정
Nexus 전용설정 + +
Xtreem 전용설정 + +
+
+
+
+ + + + + + + + +
+
+ +
+
+
에이전시 의 게임회사 연결설정
+
+
+
+ +
    + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
게임명벤더사 선택선택 벤더사 요율현재 나의 요율저장
에볼루션 + + 4.23.9
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
게임명벤더사 선택선택 벤더사 요율현재 나의 요율저장
에볼루션 + + + 4.23.9
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
게임명벤더사 선택선택 벤더사 요율현재 나의 요율저장
에볼루션 + + + 4.23.9
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
게임명벤더사 선택선택 벤더사 요율현재 나의 요율저장
에볼루션 + + + 4.23.9
+
+
+
+ +
+
+
\ No newline at end of file diff --git a/src/main/resources/templates/admin/simpleReport.html b/src/main/resources/templates/admin/simpleReport.html new file mode 100644 index 0000000..4f1e7ce --- /dev/null +++ b/src/main/resources/templates/admin/simpleReport.html @@ -0,0 +1,190 @@ + + + + + +
+
+

에이전시 목록

+
+ + +
+
+
+ +
    +
  • +
    +
    + +
    + + +
    +
  • +
  • +
    +
    + +
    + +
    +
  • +
  • + 검색 +
  • +
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
-WINLOSEBETWIN
EVO [A] 정품딥코어 윈루즈딥코어 베팅금딥코어 당첨금
EVO [A] HYB딥코어(파싱) 윈루즈딥코어(파싱) 베팅금딥코어(파싱) 당첨금
EVO [B] 정품핀트리 윈루즈핀트리 베팅금핀트리 당첨금
EVO [B] HYB핀트리(파싱) 윈루즈핀트리(파싱) 베팅금핀트리(파싱) 당첨금
EVO 정품EVO 윈루즈EVO 베팅금EVO 당첨금
EVO [All]EVO 윈루즈EVO 베팅금EVO 당첨금
ProgmaticSlotPRA 윈루즈PRA 베팅금PRA 당첨금
Total총 윈루즈총 베팅금총 당첨금
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ 아이디 + 에이전시
+ [에이전시] +
WINLOSEBETWIN
EVO [A] 정품딥코어 윈루즈딥코어 베팅금딥코어 당첨금
EVO [A] HYB딥코어(파싱) 윈루즈딥코어(파싱) 베팅금딥코어(파싱) 당첨금
EVO [B] 정품핀트리 윈루즈핀트리 베팅금핀트리 당첨금
EVO [B] HYB핀트리(파싱) 윈루즈핀트리(파싱) 베팅금핀트리(파싱) 당첨금
EVO 정품EVO 윈루즈EVO 베팅금EVO 당첨금
EVO [All]EVO 윈루즈EVO 베팅금EVO 당첨금
ProgmaticSlotPRA 윈루즈PRA 베팅금PRA 당첨금
Total총 윈루즈총 베팅금총 당첨금
+ +
+
+
+
+ +
+ \ No newline at end of file diff --git a/src/main/resources/templates/admin/stat.html b/src/main/resources/templates/admin/stat.html new file mode 100644 index 0000000..1f7513c --- /dev/null +++ b/src/main/resources/templates/admin/stat.html @@ -0,0 +1,70 @@ + + + + + +
+
+

마이 에이전시 수익 리스트

+ 소수점 자리는 첫째 자리에서 반올림 되어집니다.
매일 00시 기준으로 업데이트 되어집니다.
+
+ +
2022년 07월 수익 현황
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
일자베팅금액당첨금액수익베팅 횟수딩첨 횟수
2022-07-014,997,185,334 C4,806,942,674 C190,242,660 C2,660 건2,660 건
+ +
+
+
+ + + +
+ +
\ No newline at end of file diff --git a/src/main/resources/templates/admin/statBottom.html b/src/main/resources/templates/admin/statBottom.html new file mode 100644 index 0000000..857adb3 --- /dev/null +++ b/src/main/resources/templates/admin/statBottom.html @@ -0,0 +1,64 @@ + + + + +
+
+

하부 에이전시 수익 리스트

+ 소수점 자리는 첫째 자리에서 반올림 되어집니다.
매일 00시 기준으로 업데이트 되어집니다.
+
+ +
2022년 07월 수익 현황
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
에이전시명베팅 금액당첨 금액수익
aaa4,997,185,334 C4,806,942,674 C190,242,660 C
데이터가 없습니다
+ +
+
+
+ +
+ +
\ No newline at end of file diff --git a/src/main/resources/templates/admin/statCasino.html b/src/main/resources/templates/admin/statCasino.html new file mode 100644 index 0000000..703b89b --- /dev/null +++ b/src/main/resources/templates/admin/statCasino.html @@ -0,0 +1,88 @@ + + + + + + + +
+
+

게임 회사별 수익 리스트

+
+ +
+
게임 회사별 수익 리스트
매일 새벽 5시에 통계내용이 갱신 됩니다.
+
+
+
+
+
+
    +
  • +
    +
    + +
    + + + +
    +
  • +
  • + + + +
  • +
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
카지노 벤더베팅 금액당첨 금액손익 금액 (총합)베팅 건수당첨 건수
evolution4,997,185,334 C4,806,942,674 C190,242,660 C2,660 건2,660 건
데이터가 없습니다
+
+

베팅, 당첨 건수는 2022-02-13 부터 통계작성이 시작되었습니다.

+
+
+
+ +
diff --git a/src/main/resources/templates/admin/statDate.html b/src/main/resources/templates/admin/statDate.html new file mode 100644 index 0000000..af66e2c --- /dev/null +++ b/src/main/resources/templates/admin/statDate.html @@ -0,0 +1,96 @@ + + + + + + + +
+
+

기간내 유저 수익 내역

+
+ + 금일 00시 까지의 통계 데이터만 표시됩니다. +
+
+
+
    +
  • +
    +
    + +
    + +
    +
  • +
  • +
    +
    + +
    + + +
    +
  • +
  • 전체검색
  • +
+
+ +
+ CSV + Excel +
+
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
유저명베팅 금액당첨 금액손익 금액베팅 횟수당첨 횟수
aaa4,997,185,334 C4,806,942,674 C190,242,660 C2,660 건2,660 건
데이터가 없습니다
+
+
+
+
+ +
\ No newline at end of file diff --git a/src/main/resources/templates/admin/statPot.html b/src/main/resources/templates/admin/statPot.html new file mode 100644 index 0000000..c7dc850 --- /dev/null +++ b/src/main/resources/templates/admin/statPot.html @@ -0,0 +1,71 @@ + + + + + +
+
+

크레딧 거래 내역

+ 소수점 자리는 첫째 자리에서 반올림 되어집니다. +
+ +
유통 통계
+
+ +
+
+ + + + + + + + + + + + + + + + + + + +
일자충전받은 총액하부에이전시유통한 총액상위사이트지급(관)상위사이트회수(관)
7월 총합600,000,000 C600,000,000 C600,000,000 C600,000,000 C
+ +
+
+
+ +
+ +
\ No newline at end of file diff --git a/src/main/resources/templates/admin/statReportday.html b/src/main/resources/templates/admin/statReportday.html new file mode 100644 index 0000000..7fdeb42 --- /dev/null +++ b/src/main/resources/templates/admin/statReportday.html @@ -0,0 +1,121 @@ + + + + + + + + + +
+
+

일간 통계

+
+ +
+ +
+
+
+
+
+
    +
  • +
    +
    + +
    + + + +
    +
  • +
  • + + + +
  • +
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
일자게임베팅취소수익금
에볼류션 카지노에볼류션 카지노123,456,789123,456,789000
에볼류션 카지노에볼류션 카지노123,456,789123,456,789000
데이터가 없습니다
+
+
+
+
+ +
\ No newline at end of file diff --git a/src/main/resources/templates/admin/statReportmonth.html b/src/main/resources/templates/admin/statReportmonth.html new file mode 100644 index 0000000..6cb5e7e --- /dev/null +++ b/src/main/resources/templates/admin/statReportmonth.html @@ -0,0 +1,138 @@ + + + + + + + + + +
+
+

1월간 통계

+
+ +
+ +
+
+
+
+
+
    +
  • +
    +
    + +
    + + + + +
    +
  • +
  • + + + +
  • +
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
게임베팅취소수익금
에볼류션 카지노에볼류션 카지노123,456,789123,456,789000
에볼류션 카지노에볼류션 카지노123,456,789123,456,789000
데이터가 없습니다
+
+
+
+
+ +
\ No newline at end of file diff --git a/src/main/resources/templates/admin/statUser.html b/src/main/resources/templates/admin/statUser.html new file mode 100644 index 0000000..acc0b53 --- /dev/null +++ b/src/main/resources/templates/admin/statUser.html @@ -0,0 +1,108 @@ + + + + + + + +
+
+

유저 수익 검색

+
+
    +
  • 수익 통계월
  • +
+
+
+
+
    +
  • +
    +
    + +
    + +
    +
  • +
  • +
    +
    + +
    + + + + +
    +
  • +
  • 전체검색
  • +
+
+
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
날짜베팅 금액당첨 금액손익 금액베팅 횟수당첨 횟수
2022-07-014,997,185,334 C4,806,942,674 C190,242,660 C2,660 건2,660 건
데이터가 없습니다
+
+
+
+
+ +
\ No newline at end of file diff --git a/src/main/resources/templates/admin/std.html b/src/main/resources/templates/admin/std.html new file mode 100644 index 0000000..7bc44f1 --- /dev/null +++ b/src/main/resources/templates/admin/std.html @@ -0,0 +1,184 @@ + + + + + + + + +
+
+

상위벤더 보유머니 현황

+
+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + +
계정벤더사명보유머니전체
mama유니온0
+
+
+
+
+ +
\ No newline at end of file diff --git a/src/main/resources/templates/admin/transaction.html b/src/main/resources/templates/admin/transaction.html new file mode 100644 index 0000000..7af67fb --- /dev/null +++ b/src/main/resources/templates/admin/transaction.html @@ -0,0 +1,163 @@ + + + + + + + + +
+
+

에이전시 전체 트랜잭션 내역

+
+ +
+
+ + + +
+ + +
+
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
베팅 번호관련 번호대상자 (에이전시)원인자 (에이전시/유저)타입변동 전 잔액변동 금액변동 후 잔액상태처리 시각
베팅 번호관련 번호대상자 (에이전시) + + + + + (관)중전 + (관)회수 + 충전 + 지급 + 베팅 + 베팅결과 + + 변동 전 잔액변동 금액변동 후 잔액완료됨처리 시각
+ +
+
+
+ + + +
+
\ No newline at end of file diff --git a/src/main/resources/templates/admin/transactionList.html b/src/main/resources/templates/admin/transactionList.html new file mode 100644 index 0000000..c27bb1e --- /dev/null +++ b/src/main/resources/templates/admin/transactionList.html @@ -0,0 +1,119 @@ + + + + +
+
+

유저 전체 트랜잭션 내역

+
+ +
+ +
+
    +
  • +
    +
    + +
    + +
    +
  • +
  • +
    +
    + +
    + +
    +
  • +
  • +
    +
    + +
    + + +
    +
  • + +
  • +
    +
    + +
    + +
    +
  • +
  • + + 전체검색 + +
  • +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + +
베팅 번호관련 번호외부 번호원인자 (에이전시)대상자 (유저)타입변동 전 잔액변동 금액변동 후 잔액상태처리 시각
검색된 내역이 없습니다.
+
+
+
+ +
+ +
\ No newline at end of file diff --git a/src/main/resources/templates/admin/user.html b/src/main/resources/templates/admin/user.html new file mode 100644 index 0000000..dd65efe --- /dev/null +++ b/src/main/resources/templates/admin/user.html @@ -0,0 +1,175 @@ + + + + + + +
+
+

유저 목록

+
+ +
+ +
+
+
    +
  • +
    +
    + +
    + +
    +
  • +
  • +
    +
    + +
    + +
    +
  • +
  • +
    +
    + +
    + +
    +
  • +
  • + + 검색 + +
  • +
+
+
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
번호소속 에이전시유저IDUUID닉네임변환아이디가입 시각누적 베팅금하이브리드 허용관리
516398 +
+ @no.1 +
+
+ + ---22-03-11 17:18-- + 허용 + 불가 +
+ +
+
+
+ + + +
+ + +
diff --git a/src/main/resources/templates/admin/venderlist.html b/src/main/resources/templates/admin/venderlist.html new file mode 100644 index 0000000..b61cc5b --- /dev/null +++ b/src/main/resources/templates/admin/venderlist.html @@ -0,0 +1,82 @@ + + + + + + +
+
+

상위 벤더 개별 연결

+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
사이트인덱스벤더인덱스벤더코드벤더api URL벤더인증 URL상위 벤더 ID벤더키벤더 비밀번호벤더 게임코드트랜스퍼여부콜백토큰생성시간저장
+
+
+
+
+
\ No newline at end of file diff --git a/src/main/resources/templates/api.html b/src/main/resources/templates/api.html new file mode 100644 index 0000000..967e4de --- /dev/null +++ b/src/main/resources/templates/api.html @@ -0,0 +1,121 @@ +$(function() { + var springfox = { + "baseUrl": function() { + return window.location.origin; + }, + "securityConfig": function(cb) { + $.getJSON(this.baseUrl() + "/swagger-resources/configuration/security", function(data) { + cb(data); + }); + }, + "uiConfig": function(cb) { + $.getJSON(this.baseUrl() + "/swagger-resources/configuration/ui", function(data) { + cb(data); + }); + } + }; + window.springfox = springfox; + window.oAuthRedirectUrl = springfox.baseUrl() + '/webjars/springfox-swagger-ui/o2c.html'; + + window.springfox.uiConfig(function(data) { + window.swaggerUi = new SwaggerUi({ + dom_id: "swagger-ui-container", + validatorUrl: data.validatorUrl, + supportedSubmitMethods: data.supportedSubmitMethods || ['get', 'post', 'put', 'delete', 'patch'], + docExpansion: data.docExpansion || 'none', + jsonEditor: JSON.parse(data.jsonEditor) || false, + apisSorter: data.apisSorter || 'alpha', + defaultModelRendering: data.defaultModelRendering || 'schema', + showRequestHeaders: data.showRequestHeaders || true, + timeout: data.requestTimeout, + onComplete: function(swaggerApi, swaggerUi) { + + initializeSpringfox(); + + if (window.SwaggerTranslator) { + window.SwaggerTranslator.translate(); + } + + $('pre code').each(function(i, e) { + hljs.highlightBlock(e) + }); + + }, + onFailure: function(data) { + log("Unable to Load SwaggerUI"); + }, + }); + + initializeBaseUrl(); + + function addApiKeyAuthorization(security) { + var apiKeyVehicle = security.apiKeyVehicle || 'query'; + var apiKeyName = security.apiKeyName || 'api_key'; + var apiKey = security.apiKey || ''; + if (apiKey && apiKey.trim() != "") { + var apiKeyAuth = new SwaggerClient.ApiKeyAuthorization(apiKeyName, apiKey, apiKeyVehicle); + window.swaggerUi.api.clientAuthorizations.add(apiKeyName, apiKeyAuth); + log("added key " + apiKey); + } + } + + function log() { + if ('console' in window) { + console.log.apply(console, arguments); + } + } + + function oAuthIsDefined(security) { + return security.clientId + && security.clientSecret + && security.appName + && security.realm; + } + + function initializeSpringfox() { + var security = {}; + window.springfox.securityConfig(function(data) { + security = data; + addApiKeyAuthorization(security); + if (typeof initOAuth == "function" && oAuthIsDefined(security)) { + initOAuth(security); + } + }); + } + }); + + $('#select_baseUrl').change(function() { + window.swaggerUi.headerView.trigger('update-swagger-ui', { + url: $('#select_baseUrl').val() + }); + }); + + function maybePrefix(location, withRelativePath) { + var pat = /^https?:\/\//i; + if (pat.test(location)) { + return location; + } + return withRelativePath + location; + } + + function initializeBaseUrl() { + var relativeLocation = springfox.baseUrl(); + + $('#input_baseUrl').hide(); + + $.getJSON(relativeLocation + "/swagger-resources", function(data) { + + var $urlDropdown = $('#select_baseUrl'); + $urlDropdown.empty(); + $.each(data, function(i, resource) { + var option = $('') + .attr("value", maybePrefix(resource.location, relativeLocation)) + .text(resource.name + " (" + resource.location + ")"); + $urlDropdown.append(option); + }); + $urlDropdown.change(); + }); + + } + +}); \ No newline at end of file diff --git a/src/main/resources/templates/error/404.html b/src/main/resources/templates/error/404.html new file mode 100644 index 0000000..f491258 --- /dev/null +++ b/src/main/resources/templates/error/404.html @@ -0,0 +1,36 @@ + + + + + 404 Not Found + + + +
+

404

+

페이지를 찾을 수 없습니다.

+
+ + \ No newline at end of file diff --git a/src/main/resources/templates/front/lunch.html b/src/main/resources/templates/front/lunch.html new file mode 100644 index 0000000..cf9b591 --- /dev/null +++ b/src/main/resources/templates/front/lunch.html @@ -0,0 +1,10 @@ + + + + +
+ + + +
diff --git a/src/main/resources/templates/front/splus/callback.html b/src/main/resources/templates/front/splus/callback.html new file mode 100644 index 0000000..53dc781 --- /dev/null +++ b/src/main/resources/templates/front/splus/callback.html @@ -0,0 +1,5 @@ + + + + diff --git a/src/test/java/com/bb/ApiServerApplicationTests.java b/src/test/java/com/bb/ApiServerApplicationTests.java new file mode 100644 index 0000000..dd52274 --- /dev/null +++ b/src/test/java/com/bb/ApiServerApplicationTests.java @@ -0,0 +1,13 @@ +package com.bb; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class ApiServerApplicationTests { + + @Test + void contextLoads() { + } + +}