├── .github
└── workflows
│ └── maven.yml
├── .gitignore
├── .mvn
└── wrapper
│ ├── maven-wrapper.jar
│ └── maven-wrapper.properties
├── .travis.yml
├── README.md
├── checkstyle-suppressions.xml
├── checkstyle.xml
├── circle.yml
├── doc
├── diagram.png
└── diagram.uxf
├── docker
├── amd64
│ └── Dockerfile
├── arm32v7
│ └── Dockerfile
└── arm64v8
│ └── Dockerfile
├── integration-testing
└── pom.xml
├── mvnw
├── mvnw.cmd
├── pom.xml
├── server
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── com
│ │ └── payneteasy
│ │ └── pos
│ │ └── proxy
│ │ ├── Configs.java
│ │ ├── IPaymentService.java
│ │ ├── JsonMessages.java
│ │ ├── PosProxyApplication.java
│ │ ├── WebServer.java
│ │ ├── impl
│ │ ├── InpasNetworkClientExtended.java
│ │ ├── InpasNetworkManager.java
│ │ └── PaymentServiceImpl.java
│ │ └── messages
│ │ ├── CloseDayRequest.java
│ │ ├── CloseDayResponse.java
│ │ ├── PaymentRequest.java
│ │ ├── PaymentResponse.java
│ │ └── RefundRequest.java
│ └── resources
│ └── swagger-ui
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── index.html
│ ├── oauth2-redirect.html
│ ├── pos-proxy.json
│ ├── swagger-ui-bundle.js
│ ├── swagger-ui-bundle.js.map
│ ├── swagger-ui-standalone-preset.js
│ ├── swagger-ui-standalone-preset.js.map
│ ├── swagger-ui.css
│ ├── swagger-ui.css.map
│ ├── swagger-ui.js
│ └── swagger-ui.js.map
└── swagger
├── make-bundle.sh
├── messages
├── CloseDayRequest.yaml
├── CloseDayResponse.yaml
├── PaymentRequest.yaml
├── PaymentResponse.yaml
└── RefundRequest.yaml
├── pos-proxy.yaml
└── run-ui.sh
/.github/workflows/maven.yml:
--------------------------------------------------------------------------------
1 | # This workflow will build a Java project with Maven
2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
3 |
4 | name: Java CI with Maven
5 |
6 | on:
7 | push:
8 | branches: [ master ]
9 | pull_request:
10 | branches: [ master ]
11 |
12 | jobs:
13 | build:
14 |
15 | runs-on: ubuntu-latest
16 |
17 | steps:
18 | - uses: actions/checkout@v2
19 | - name: Set up JDK 11
20 | uses: actions/setup-java@v2
21 | with:
22 | java-version: '11'
23 | distribution: 'adopt'
24 | - name: Build with Maven
25 | run: ./mvnw -B package --file pom.xml
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | classpath
2 | .project
3 | .settings/
4 | target/
5 | *.iml
6 | *.ipr
7 | *.iws
8 | *~
9 | .idea
10 | gen/
11 | classes/
12 | gen-external-apklibs/
13 | .vertx
14 | .DS_Store
15 |
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/payneteasy/pos-proxy/4b261fc96dfaf95f2829ece62c59e3dd810c37eb/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.2/apache-maven-3.5.2-bin.zip
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 | sudo: true # faster builds
3 |
4 | jdk:
5 | - oraclejdk8
6 |
7 | cache:
8 | directories:
9 | - $HOME/.m2
10 |
11 | script: "./mvnw clean install"
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # pos-proxy
2 |
3 | ## How it works
4 |
5 | POS Proxy is a web server that redirects json requests to a POS terminal connected via USB.
6 | You can also use this example to see how to integrate the Payneteasy mPOS SDK to your java application.
7 |
8 | 
9 |
10 | * Client - a client code to start a payment
11 | * POS Proxy - this application
12 | * gate.payneteasy.com - Our authorisation server
13 | * Merchant site - we can make a callback to your server with a final order status
14 |
15 | ## Swagger UI
16 |
17 | * Run the application
18 | * Go to the http://0.0.0.0:8081/pos-proxy/swagger-ui
19 |
20 | Please see the video below:
21 |
22 | [](https://youtu.be/_A6wEbFHIOI)
23 |
24 | ## How to generate a client code
25 |
26 | * Install swagger-codegen from https://github.com/swagger-api/swagger-codegen
27 | * Run swagger-codegen with your language
28 |
29 | ```bash
30 | swagger-codegen generate -i http://0.0.0.0:8081/pos-proxy/swagger-ui/pos-proxy.json -l java
31 | ```
32 |
33 | ## Run it from docker
34 |
35 | ### amd64
36 |
37 | ```bash
38 | docker run -it -p 8081:8081/tcp payneteasy/pos-proxy:amd64
39 | ```
40 |
41 | ### arm 64 v8 (Raspberry PI 3)
42 |
43 | ```bash
44 | docker run -it -p 8081:8081/tcp payneteasy/pos-proxy:arm64v8
45 | ```
46 |
47 | ### arm 32 v7 (Raspberry PI 1/2)
48 |
49 | ```bash
50 | docker run -it -p 8081:8081/tcp payneteasy/pos-proxy:arm32v7
51 | ```
52 |
53 | ## Requirements
54 |
55 | * Java 1.8 (Oracle or OpenJDK)
56 |
57 | ## How to build and run
58 |
59 | ```bash
60 | ./mvnw clean package
61 | cd server/target && java -jar server-1.3-SNAPSHOT-jar-with-dependencies.jar
62 | ```
63 |
64 | ## How to run from release page
65 |
66 | ```bash
67 | wget https://github.com/payneteasy/pos-proxy/releases/download/1.3.0/pos-proxy-1.3.0.jar
68 | java -jar server-1.0-1-SNAPSHOT-jar-with-dependencies.jar
69 | ```
70 |
71 | ## How to change a listening port
72 |
73 | You can change the listening port by pass this via -D option or via environment variable.
74 |
75 | Via environment variable:
76 | ```bash
77 | export HTTP_SERVER_PORT=9090
78 | java -jar server-1.3-SNAPSHOT-jar-with-dependencies.jar
79 | ```
80 |
81 | Via -D option:
82 | ```bash
83 | java -DHTTP_SERVER_PORT=9090 -jar server-1.3-SNAPSHOT-jar-with-dependencies.jar
84 | ```
85 |
86 | ## How to connect to a Verifone terminal via USB cable
87 |
88 | Run socat program to listen 27016 tcp port and redirects all tcp packets to a tty device.
89 |
90 | ```bash
91 | socat -d -d -v -x tcp4-listen:27015,reuseaddr,fork file:/dev/ttyACM0,nonblock,echo=0,raw
92 | ```
93 |
--------------------------------------------------------------------------------
/checkstyle-suppressions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/checkstyle.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
--------------------------------------------------------------------------------
/circle.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | jobs:
3 | build:
4 | docker:
5 | - image: circleci/openjdk:8-jdk
6 |
7 | working_directory: ~/repo
8 |
9 | environment:
10 | MAVEN_OPTS: -Xmx3200m
11 |
12 | steps:
13 | - checkout
14 |
15 | # Download and cache dependencies
16 | - restore_cache:
17 | keys:
18 | - v1-dependencies-{{ checksum "pom.xml" }}
19 | # fallback to using the latest cache if no exact match is found
20 | - v1-dependencies-
21 |
22 | - run: mvn test
23 |
24 | - save_cache:
25 | paths:
26 | - ~/.m2
27 | key: v1-dependencies-{{ checksum "pom.xml" }}
28 |
29 | # run tests!
30 | - run: ./mvnw clean install
31 |
--------------------------------------------------------------------------------
/doc/diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/payneteasy/pos-proxy/4b261fc96dfaf95f2829ece62c59e3dd810c37eb/doc/diagram.png
--------------------------------------------------------------------------------
/doc/diagram.uxf:
--------------------------------------------------------------------------------
1 |
2 |
3 | 10
4 |
5 | UMLGeneric
6 |
7 | 60
8 | 30
9 | 100
10 | 30
11 |
12 | _:Client_
13 |
14 |
15 |
16 | Relation
17 |
18 | 90
19 | 50
20 | 30
21 | 600
22 |
23 | lt=.
24 | 10.0;10.0;10.0;580.0
25 |
26 |
27 | UMLGeneric
28 |
29 | 260
30 | 30
31 | 100
32 | 30
33 |
34 | _:POS Proxy_
35 |
36 |
37 |
38 | UMLGeneric
39 |
40 | 520
41 | 30
42 | 200
43 | 30
44 |
45 | _:gate.payneteasy.com_
46 |
47 |
48 |
49 | Relation
50 |
51 | 90
52 | 110
53 | 230
54 | 40
55 |
56 | lt=<<-
57 | POST /pos-proxy/pay
58 | 210.0;20.0;10.0;20.0
59 |
60 |
61 | Relation
62 |
63 | 290
64 | 50
65 | 30
66 | 240
67 |
68 | lt=.
69 | 10.0;10.0;10.0;220.0
70 |
71 |
72 | Relation
73 |
74 | 600
75 | 50
76 | 30
77 | 590
78 |
79 | lt=.
80 | 10.0;10.0;10.0;570.0
81 |
82 |
83 | Relation
84 |
85 | 90
86 | 320
87 | 540
88 | 110
89 |
90 | lt=<<-
91 | POST https://gate.payneteasy.com/paynet/api/v2/status
92 | with Order ID
93 |
94 | see http://doc.payneteasy.com/card_payment_API/
95 | sale-transactions.html#order-status
96 |
97 | 520.0;20.0;10.0;20.0
98 |
99 |
100 | Relation
101 |
102 | 90
103 | 470
104 | 540
105 | 40
106 |
107 | lt=<<-
108 | Responses with Order Status
109 | 10.0;20.0;520.0;20.0
110 |
111 |
112 | UMLGeneric
113 |
114 | 90
115 | 120
116 | 20
117 | 100
118 |
119 |
120 | bg=yellow
121 |
122 |
123 |
124 | UMLGeneric
125 |
126 | 290
127 | 110
128 | 20
129 | 120
130 |
131 |
132 | bg=yellow
133 |
134 |
135 |
136 | Relation
137 |
138 | 90
139 | 170
140 | 230
141 | 50
142 |
143 | lt=<<-
144 | Returns Order ID
145 |
146 | 10.0;20.0;210.0;20.0
147 |
148 |
149 | UMLGeneric
150 |
151 | 90
152 | 320
153 | 20
154 | 200
155 |
156 |
157 | bg=yellow
158 |
159 |
160 |
161 | UMLGeneric
162 |
163 | 600
164 | 320
165 | 20
166 | 190
167 |
168 |
169 | bg=yellow
170 |
171 |
172 |
173 | UMLGeneric
174 |
175 | 1100
176 | 40
177 | 100
178 | 30
179 |
180 | _:Merchant Site_
181 |
182 |
183 |
184 | Relation
185 |
186 | 1140
187 | 60
188 | 30
189 | 560
190 |
191 | lt=.
192 | 10.0;10.0;10.0;540.0
193 |
194 |
195 | Relation
196 |
197 | 600
198 | 260
199 | 570
200 | 50
201 |
202 | lt=<-
203 | Makes a callback
204 | see http://doc.payneteasy.com/common_utilities/merchants_callbacks.html
205 | 550.0;20.0;10.0;20.0
206 |
207 |
208 |
--------------------------------------------------------------------------------
/docker/amd64/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:8-jre-slim
2 | ADD https://github.com/payneteasy/pos-proxy/releases/download/1.3.1/pos-proxy-1.3.1.jar /opt/app.jar
3 | WORKDIR /opt
4 | EXPOSE 8081/tcp
5 | CMD ["java", "-jar", "app.jar"]
6 |
--------------------------------------------------------------------------------
/docker/arm32v7/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM arm32v7/openjdk:8-jre-slim
2 | ADD https://github.com/payneteasy/pos-proxy/releases/download/1.3.1/pos-proxy-1.3.1.jar /opt/app.jar
3 | WORKDIR /opt
4 | EXPOSE 8081/tcp
5 | CMD ["java", "-jar", "app.jar"]
6 |
--------------------------------------------------------------------------------
/docker/arm64v8/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM arm64v8/openjdk:8-jre-slim
2 | ADD https://github.com/payneteasy/pos-proxy/releases/download/1.3.1/pos-proxy-1.3.1.jar /opt/app.jar
3 | WORKDIR /opt
4 | EXPOSE 8081/tcp
5 | CMD ["java", "-jar", "app.jar"]
6 |
--------------------------------------------------------------------------------
/integration-testing/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 | jar
4 |
5 | com.payneteasy.pos-proxy
6 | integration-testing
7 |
8 | Robot integration testing ${project.version}
9 |
10 |
11 | com.payneteasy
12 | pos-proxy
13 | 1.3-SNAPSHOT
14 |
15 |
16 |
17 | UTF-8
18 | true
19 |
20 |
21 |
22 |
23 | integration-test
24 |
25 | false
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | com.google.code.findbugs
35 | jsr305
36 |
37 |
38 |
39 | junit
40 | junit
41 | test
42 |
43 |
44 |
45 | ch.qos.logback
46 | logback-classic
47 |
48 |
49 | ch.qos.logback
50 | logback-core
51 |
52 |
53 |
54 | org.slf4j
55 | slf4j-api
56 |
57 |
58 |
59 | org.slf4j
60 | jcl-over-slf4j
61 |
62 |
63 | org.slf4j
64 | log4j-over-slf4j
65 |
66 |
67 | org.slf4j
68 | jul-to-slf4j
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/mvnw:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # ----------------------------------------------------------------------------
3 | # Licensed to the Apache Software Foundation (ASF) under one
4 | # or more contributor license agreements. See the NOTICE file
5 | # distributed with this work for additional information
6 | # regarding copyright ownership. The ASF licenses this file
7 | # to you under the Apache License, Version 2.0 (the
8 | # "License"); you may not use this file except in compliance
9 | # with the License. You may obtain a copy of the License at
10 | #
11 | # http://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing,
14 | # software distributed under the License is distributed on an
15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | # KIND, either express or implied. See the License for the
17 | # specific language governing permissions and limitations
18 | # under the License.
19 | # ----------------------------------------------------------------------------
20 |
21 | # ----------------------------------------------------------------------------
22 | # Maven2 Start Up Batch script
23 | #
24 | # Required ENV vars:
25 | # ------------------
26 | # JAVA_HOME - location of a JDK home dir
27 | #
28 | # Optional ENV vars
29 | # -----------------
30 | # M2_HOME - location of maven2's installed home dir
31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven
32 | # e.g. to debug Maven itself, use
33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files
35 | # ----------------------------------------------------------------------------
36 |
37 | if [ -z "$MAVEN_SKIP_RC" ] ; then
38 |
39 | if [ -f /etc/mavenrc ] ; then
40 | . /etc/mavenrc
41 | fi
42 |
43 | if [ -f "$HOME/.mavenrc" ] ; then
44 | . "$HOME/.mavenrc"
45 | fi
46 |
47 | fi
48 |
49 | # OS specific support. $var _must_ be set to either true or false.
50 | cygwin=false;
51 | darwin=false;
52 | mingw=false
53 | case "`uname`" in
54 | CYGWIN*) cygwin=true ;;
55 | MINGW*) mingw=true;;
56 | Darwin*) darwin=true
57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
59 | if [ -z "$JAVA_HOME" ]; then
60 | if [ -x "/usr/libexec/java_home" ]; then
61 | export JAVA_HOME="`/usr/libexec/java_home`"
62 | else
63 | export JAVA_HOME="/Library/Java/Home"
64 | fi
65 | fi
66 | ;;
67 | esac
68 |
69 | if [ -z "$JAVA_HOME" ] ; then
70 | if [ -r /etc/gentoo-release ] ; then
71 | JAVA_HOME=`java-config --jre-home`
72 | fi
73 | fi
74 |
75 | if [ -z "$M2_HOME" ] ; then
76 | ## resolve links - $0 may be a link to maven's home
77 | PRG="$0"
78 |
79 | # need this for relative symlinks
80 | while [ -h "$PRG" ] ; do
81 | ls=`ls -ld "$PRG"`
82 | link=`expr "$ls" : '.*-> \(.*\)$'`
83 | if expr "$link" : '/.*' > /dev/null; then
84 | PRG="$link"
85 | else
86 | PRG="`dirname "$PRG"`/$link"
87 | fi
88 | done
89 |
90 | saveddir=`pwd`
91 |
92 | M2_HOME=`dirname "$PRG"`/..
93 |
94 | # make it fully qualified
95 | M2_HOME=`cd "$M2_HOME" && pwd`
96 |
97 | cd "$saveddir"
98 | # echo Using m2 at $M2_HOME
99 | fi
100 |
101 | # For Cygwin, ensure paths are in UNIX format before anything is touched
102 | if $cygwin ; then
103 | [ -n "$M2_HOME" ] &&
104 | M2_HOME=`cygpath --unix "$M2_HOME"`
105 | [ -n "$JAVA_HOME" ] &&
106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
107 | [ -n "$CLASSPATH" ] &&
108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
109 | fi
110 |
111 | # For Mingw, ensure paths are in UNIX format before anything is touched
112 | if $mingw ; then
113 | [ -n "$M2_HOME" ] &&
114 | M2_HOME="`(cd "$M2_HOME"; pwd)`"
115 | [ -n "$JAVA_HOME" ] &&
116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
117 | # TODO classpath?
118 | fi
119 |
120 | if [ -z "$JAVA_HOME" ]; then
121 | javaExecutable="`which javac`"
122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
123 | # readlink(1) is not available as standard on Solaris 10.
124 | readLink=`which readlink`
125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
126 | if $darwin ; then
127 | javaHome="`dirname \"$javaExecutable\"`"
128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
129 | else
130 | javaExecutable="`readlink -f \"$javaExecutable\"`"
131 | fi
132 | javaHome="`dirname \"$javaExecutable\"`"
133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'`
134 | JAVA_HOME="$javaHome"
135 | export JAVA_HOME
136 | fi
137 | fi
138 | fi
139 |
140 | if [ -z "$JAVACMD" ] ; then
141 | if [ -n "$JAVA_HOME" ] ; then
142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
143 | # IBM's JDK on AIX uses strange locations for the executables
144 | JAVACMD="$JAVA_HOME/jre/sh/java"
145 | else
146 | JAVACMD="$JAVA_HOME/bin/java"
147 | fi
148 | else
149 | JAVACMD="`which java`"
150 | fi
151 | fi
152 |
153 | if [ ! -x "$JAVACMD" ] ; then
154 | echo "Error: JAVA_HOME is not defined correctly." >&2
155 | echo " We cannot execute $JAVACMD" >&2
156 | exit 1
157 | fi
158 |
159 | if [ -z "$JAVA_HOME" ] ; then
160 | echo "Warning: JAVA_HOME environment variable is not set."
161 | fi
162 |
163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
164 |
165 | # traverses directory structure from process work directory to filesystem root
166 | # first directory with .mvn subdirectory is considered project base directory
167 | find_maven_basedir() {
168 |
169 | if [ -z "$1" ]
170 | then
171 | echo "Path not specified to find_maven_basedir"
172 | return 1
173 | fi
174 |
175 | basedir="$1"
176 | wdir="$1"
177 | while [ "$wdir" != '/' ] ; do
178 | if [ -d "$wdir"/.mvn ] ; then
179 | basedir=$wdir
180 | break
181 | fi
182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc)
183 | if [ -d "${wdir}" ]; then
184 | wdir=`cd "$wdir/.."; pwd`
185 | fi
186 | # end of workaround
187 | done
188 | echo "${basedir}"
189 | }
190 |
191 | # concatenates all lines of a file
192 | concat_lines() {
193 | if [ -f "$1" ]; then
194 | echo "$(tr -s '\n' ' ' < "$1")"
195 | fi
196 | }
197 |
198 | BASE_DIR=`find_maven_basedir "$(pwd)"`
199 | if [ -z "$BASE_DIR" ]; then
200 | exit 1;
201 | fi
202 |
203 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
204 | if [ "$MVNW_VERBOSE" = true ]; then
205 | echo $MAVEN_PROJECTBASEDIR
206 | fi
207 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
208 |
209 | # For Cygwin, switch paths to Windows format before running java
210 | if $cygwin; then
211 | [ -n "$M2_HOME" ] &&
212 | M2_HOME=`cygpath --path --windows "$M2_HOME"`
213 | [ -n "$JAVA_HOME" ] &&
214 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
215 | [ -n "$CLASSPATH" ] &&
216 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
217 | [ -n "$MAVEN_PROJECTBASEDIR" ] &&
218 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
219 | fi
220 |
221 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
222 |
223 | exec "$JAVACMD" \
224 | $MAVEN_OPTS \
225 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
226 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
227 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
228 |
--------------------------------------------------------------------------------
/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM http://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven2 Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM set title of command window
39 | title %0
40 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
42 |
43 | @REM set %HOME% to equivalent of $HOME
44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
45 |
46 | @REM Execute a user defined script before this one
47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
51 | :skipRcPre
52 |
53 | @setlocal
54 |
55 | set ERROR_CODE=0
56 |
57 | @REM To isolate internal variables from possible post scripts, we use another setlocal
58 | @setlocal
59 |
60 | @REM ==== START VALIDATION ====
61 | if not "%JAVA_HOME%" == "" goto OkJHome
62 |
63 | echo.
64 | echo Error: JAVA_HOME not found in your environment. >&2
65 | echo Please set the JAVA_HOME variable in your environment to match the >&2
66 | echo location of your Java installation. >&2
67 | echo.
68 | goto error
69 |
70 | :OkJHome
71 | if exist "%JAVA_HOME%\bin\java.exe" goto init
72 |
73 | echo.
74 | echo Error: JAVA_HOME is set to an invalid directory. >&2
75 | echo JAVA_HOME = "%JAVA_HOME%" >&2
76 | echo Please set the JAVA_HOME variable in your environment to match the >&2
77 | echo location of your Java installation. >&2
78 | echo.
79 | goto error
80 |
81 | @REM ==== END VALIDATION ====
82 |
83 | :init
84 |
85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
86 | @REM Fallback to current working directory if not found.
87 |
88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
90 |
91 | set EXEC_DIR=%CD%
92 | set WDIR=%EXEC_DIR%
93 | :findBaseDir
94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
95 | cd ..
96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
97 | set WDIR=%CD%
98 | goto findBaseDir
99 |
100 | :baseDirFound
101 | set MAVEN_PROJECTBASEDIR=%WDIR%
102 | cd "%EXEC_DIR%"
103 | goto endDetectBaseDir
104 |
105 | :baseDirNotFound
106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
107 | cd "%EXEC_DIR%"
108 |
109 | :endDetectBaseDir
110 |
111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
112 |
113 | @setlocal EnableExtensions EnableDelayedExpansion
114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
116 |
117 | :endReadAdditionalConfig
118 |
119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
120 |
121 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
122 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
123 |
124 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
125 | if ERRORLEVEL 1 goto error
126 | goto end
127 |
128 | :error
129 | set ERROR_CODE=1
130 |
131 | :end
132 | @endlocal & set ERROR_CODE=%ERROR_CODE%
133 |
134 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
135 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
136 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
137 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
138 | :skipRcPost
139 |
140 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
141 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
142 |
143 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
144 |
145 | exit /B %ERROR_CODE%
146 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 | pom
4 |
5 | pos-proxy
6 | com.payneteasy
7 | 1.3-SNAPSHOT
8 |
9 | pos robot ${project.version}
10 |
11 | POS/mPOS robot for passing ceritification
12 |
13 | https://github.com/evsinev/pos-proxy
14 |
15 |
16 | server
17 | integration-testing
18 |
19 |
20 |
21 | 1.8
22 | UTF-8
23 |
24 | 1.1.11
25 | 1.7.25
26 | 1.8.0
27 |
28 | ${project.basedir}/../target/coverage
29 |
30 | 0.8.0
31 |
32 | ${project.basedir}/../target/jacoco.exec
33 | java
34 | jacoco
35 |
36 | 4.1.1.4
37 |
38 | 1.4-90
39 |
40 |
41 |
42 | scm:git:git@github.com:evsinev/pos-proxy.git
43 | scm:git:git@github.com:evsinev/pos-proxy.git
44 | https://github.com/evsinev/pos-proxy.git
45 | HEAD
46 |
47 |
48 |
49 |
50 | reader-repo
51 | reader repo
52 | http://paynet-qa.clubber.me/reader/maven
53 |
54 |
55 |
56 | jitpack.io
57 | https://jitpack.io
58 |
59 |
60 |
61 |
62 |
65 |
66 |
67 |
68 | sonatype-nexus-staging
69 | sonatype oss RELEASE repository
70 | https://oss.sonatype.org/service/local/staging/deploy/maven2
71 |
72 |
73 |
74 | sonatype-nexus-snapshots
75 | sonatype oss SNAPSHOT repository
76 | https://oss.sonatype.org/content/repositories/snapshots
77 | false
78 |
79 |
80 |
81 | local-site
82 | Store only on local disk
83 | file:///tmp/mysql-scheduler-site
84 |
85 |
86 |
87 |
88 |
89 | The Apache Software License, Version 2.0
90 | http://www.apache.org/licenses/LICENSE-2.0.txt
91 | repo
92 |
93 |
94 |
95 |
96 |
97 | esinev
98 | esinev@gmail.com
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | com.payneteasy.pos-proxy
107 | server
108 | 1.3-SNAPSHOT
109 |
110 |
111 |
112 | com.payneteasy.android.reader.readers
113 | readers-miura-rxtx
114 | ${reader.version}
115 |
116 |
117 |
118 | com.payneteasy.android.reader.readers
119 | readers-inpas
120 | ${reader.version}
121 |
122 |
123 |
124 | com.payneteasy.android.reader.readers
125 | readers-common-rxtx-network
126 | ${reader.version}
127 |
128 |
129 |
130 | com.google.android
131 | android
132 | ${android.version}
133 | provided
134 |
135 |
136 |
137 |
138 | com.google.code.gson
139 | gson
140 | 2.2.4
141 |
142 |
143 |
144 | ru.odnoklassniki
145 | one-nio
146 | 1.0.2
147 |
148 |
149 | com.sun
150 | tools
151 |
152 |
153 |
154 |
155 |
156 | com.google.code.findbugs
157 | jsr305
158 | 3.0.2
159 |
160 |
161 |
162 |
163 | ch.qos.logback
164 | logback-classic
165 | ${logback.version}
166 |
167 |
168 | ch.qos.logback
169 | logback-core
170 | ${logback.version}
171 |
172 |
173 |
174 | org.slf4j
175 | slf4j-api
176 | ${slf4j.version}
177 |
178 |
179 | org.slf4j
180 | jcl-over-slf4j
181 | ${slf4j.version}
182 |
183 |
184 | org.slf4j
185 | log4j-over-slf4j
186 | ${slf4j.version}
187 |
188 |
189 | org.slf4j
190 | jul-to-slf4j
191 | ${slf4j.version}
192 |
193 |
194 |
195 | junit
196 | junit
197 | 4.13.2
198 | test
199 |
200 |
201 |
202 | org.jetbrains
203 | annotations
204 | 15.0
205 |
206 |
207 |
208 | org.mockito
209 | mockito-core
210 | 1.10.19
211 | test
212 |
213 |
214 |
215 | org.projectlombok
216 | lombok
217 | 1.18.12
218 | provided
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 | org.apache.maven.plugins
228 | maven-release-plugin
229 | 2.5.3
230 |
231 |
232 |
233 | org.apache.maven.plugins
234 | maven-compiler-plugin
235 | 3.1
236 |
237 | ${java.version}
238 | ${java.version}
239 | true
240 | true
241 |
242 |
243 |
244 |
245 | org.codehaus.mojo
246 | cobertura-maven-plugin
247 | 2.7
248 |
249 |
250 | html
251 | xml
252 |
253 | true
254 |
255 |
256 |
257 |
258 |
259 | org.jacoco
260 | jacoco-maven-plugin
261 | ${jacoco.version}
262 |
263 | ${sonar.jacoco.reportPaths}
264 | ${sonar.jacoco.reportPaths}
265 | true
266 |
267 |
268 |
269 | agent-for-ut
270 |
271 | prepare-agent
272 |
273 |
274 |
275 |
276 |
277 |
278 | org.apache.maven.plugins
279 | maven-checkstyle-plugin
280 | 3.0.0
281 |
282 |
283 | validate
284 | validate
285 |
286 | checkstyle.xml
287 | UTF-8
288 | true
289 | true
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 | org.sonatype.plugins
300 | nexus-staging-maven-plugin
301 | 1.6.3
302 | true
303 |
304 | sonatype-nexus-staging
305 | https://oss.sonatype.org/
306 | true
307 |
308 |
309 |
310 |
311 | org.apache.maven.plugins
312 | maven-site-plugin
313 | 3.3
314 |
315 | true
316 | true
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 | org.apache.maven.plugins
328 | maven-project-info-reports-plugin
329 | 2.7
330 |
331 |
332 |
333 | summary
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 | release-profile
345 |
346 |
347 | performRelease
348 | true
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 | org.apache.maven.plugins
357 | maven-gpg-plugin
358 | 1.1
359 |
360 |
361 | sign-artifacts
362 | verify
363 |
364 | sign
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
--------------------------------------------------------------------------------
/server/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | jar
5 |
6 | com.payneteasy.pos-proxy
7 | server
8 |
9 | Robot server ${project.version}
10 |
11 |
12 | com.payneteasy
13 | pos-proxy
14 | 1.3-SNAPSHOT
15 |
16 |
17 |
18 | UTF-8
19 | true
20 |
21 |
22 |
23 |
24 | integration-test
25 |
26 | false
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | com.payneteasy.android.reader.readers
36 | readers-miura-rxtx
37 |
38 |
39 |
40 | com.payneteasy.android.reader.readers
41 | readers-common-rxtx-network
42 |
43 |
44 |
45 | com.payneteasy.android.reader.readers
46 | readers-inpas
47 |
48 |
49 |
50 | com.google.android
51 | android
52 | provided
53 |
54 |
55 |
56 | com.google.code.findbugs
57 | jsr305
58 |
59 |
60 |
61 | junit
62 | junit
63 | test
64 |
65 |
66 |
67 | ch.qos.logback
68 | logback-classic
69 |
70 |
71 | ch.qos.logback
72 | logback-core
73 |
74 |
75 |
76 | org.slf4j
77 | slf4j-api
78 |
79 |
80 |
81 | org.slf4j
82 | jcl-over-slf4j
83 |
84 |
85 | org.slf4j
86 | log4j-over-slf4j
87 |
88 |
89 | org.slf4j
90 | jul-to-slf4j
91 |
92 |
93 |
94 | com.google.code.gson
95 | gson
96 |
97 |
98 |
99 | ru.odnoklassniki
100 | one-nio
101 |
102 |
103 |
104 | org.projectlombok
105 | lombok
106 | provided
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 | maven-assembly-plugin
115 |
116 |
117 |
118 | com.payneteasy.pos.proxy.PosProxyApplication
119 | true
120 |
121 |
122 |
123 | jar-with-dependencies
124 |
125 |
126 |
127 |
128 | make-assembly
129 | package
130 |
131 | single
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
--------------------------------------------------------------------------------
/server/src/main/java/com/payneteasy/pos/proxy/Configs.java:
--------------------------------------------------------------------------------
1 | package com.payneteasy.pos.proxy;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 |
6 | import java.io.File;
7 | import java.util.Arrays;
8 |
9 | public enum Configs {
10 |
11 | HTTP_SERVER_ADDRESS ( "0.0.0.0" )
12 | , HTTP_SERVER_PORT ( 8081 )
13 | , HTTP_SERVER_SELECTORS ( 1 )
14 | , HTTP_SERVER_MIN_WORKERS ( 2 )
15 | , HTTP_SERVER_MAX_WORKERS ( 10 )
16 | , API_KEY ( "56CC8E1F-85B3-404E-BB26-7671D45016D6" )
17 | ;
18 |
19 | private static final Logger LOG = LoggerFactory.getLogger(Configs.class);
20 |
21 | static {
22 | LOG.info("Version is " + getVersion());
23 | LOG.info("Configuration (you can change it with -D option or with env variable)");
24 | int maxNameLength = getMaxNameLength();
25 | for (Configs config : Configs.values()) {
26 | String value = config.name().contains("PASSWORD") ? "***" : config.asString();
27 | LOG.info(" {} = {}", padRight(config.propertyName, maxNameLength), value);
28 | }
29 | }
30 |
31 | private static int getMaxNameLength() {
32 | return Arrays.stream(Configs.values()).mapToInt(value -> value.propertyName.length()).max().orElse(10);
33 | }
34 |
35 |
36 | private static String padRight(String aText, int aLength) {
37 | StringBuilder sb = new StringBuilder(aLength);
38 | sb.append(aText);
39 | while(sb.length() < aLength) {
40 | sb.append(" ");
41 | }
42 | return sb.toString();
43 | }
44 |
45 |
46 | Configs(String aDefaultValue) {
47 | propertyName = name();
48 | defaultValue = aDefaultValue;
49 | }
50 |
51 | Configs(long aDefaultValue) {
52 | this(String.valueOf(aDefaultValue));
53 | }
54 |
55 | private final String propertyName;
56 | private final String defaultValue;
57 |
58 | public static String getVersion() {
59 | String version = Configs.class.getPackage().getImplementationVersion();
60 | return version != null ? version : "unknown";
61 | }
62 |
63 | public String asString() {
64 | String value = System.getProperty(propertyName, null);
65 | if(value == null) {
66 | value = System.getenv(propertyName);
67 | }
68 | if(value == null) {
69 | value = defaultValue;
70 | }
71 | return value;
72 | }
73 |
74 | public int asInt() {
75 | return Integer.parseInt(asString());
76 | }
77 |
78 | public boolean asBoolean() {
79 | return Boolean.parseBoolean(asString());
80 | }
81 |
82 | public int asMilliseconds() {
83 | return asInt() * 1_000;
84 | }
85 |
86 | public File asFile() {
87 | return new File(asString());
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/server/src/main/java/com/payneteasy/pos/proxy/IPaymentService.java:
--------------------------------------------------------------------------------
1 | package com.payneteasy.pos.proxy;
2 |
3 | import com.payneteasy.pos.proxy.messages.*;
4 |
5 | public interface IPaymentService {
6 |
7 | PaymentResponse pay(PaymentRequest aRequest);
8 |
9 | PaymentResponse refund(RefundRequest aRequest);
10 |
11 | CloseDayResponse closeDay(CloseDayRequest aRequest);
12 | }
13 |
--------------------------------------------------------------------------------
/server/src/main/java/com/payneteasy/pos/proxy/JsonMessages.java:
--------------------------------------------------------------------------------
1 | package com.payneteasy.pos.proxy;
2 |
3 | import com.google.gson.Gson;
4 | import com.google.gson.GsonBuilder;
5 | import one.nio.http.HttpException;
6 | import one.nio.http.Request;
7 | import one.nio.http.Response;
8 | import org.slf4j.Logger;
9 | import org.slf4j.LoggerFactory;
10 |
11 | import java.nio.charset.Charset;
12 |
13 | public class JsonMessages {
14 |
15 | private static final Logger LOG = LoggerFactory.getLogger(JsonMessages.class);
16 |
17 | private static final Charset UTF_8 = Charset.forName("utf-8");
18 | private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
19 |
20 | private final Request request;
21 | private final String url;
22 |
23 | public JsonMessages(Request aRequest) {
24 | request = aRequest;
25 | url = aRequest.getURI();
26 | }
27 |
28 | public T parse(Class aClass) throws HttpException {
29 | if(request.getBody() == null) {
30 | throw new HttpException("No body");
31 | }
32 | String json = new String(request.getBody(), UTF_8);
33 | LOG.debug("IN {} = {}", url, json);
34 | return GSON.fromJson(json, aClass);
35 | }
36 |
37 | public Response response(Object aObject) {
38 | String json = GSON.toJson(aObject);
39 | LOG.debug("OUT {} = {}", url, json);
40 | Response response = new Response(Response.OK, json.getBytes(UTF_8));
41 | response.addHeader("Content-Type: application/json");
42 | return response;
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/server/src/main/java/com/payneteasy/pos/proxy/PosProxyApplication.java:
--------------------------------------------------------------------------------
1 | package com.payneteasy.pos.proxy;
2 |
3 | import com.payneteasy.pos.proxy.impl.PaymentServiceImpl;
4 | import org.slf4j.Logger;
5 | import org.slf4j.LoggerFactory;
6 |
7 | import java.io.IOException;
8 |
9 | public class PosProxyApplication {
10 |
11 | private static final Logger LOG = LoggerFactory.getLogger(PosProxyApplication.class);
12 |
13 | public static void main(String[] args) throws IOException {
14 | LOG.info("Initialising ...");
15 | LOG.info("Server {} starting on {}:{} ...", Configs.getVersion(), Configs.HTTP_SERVER_ADDRESS.asString(), Configs.HTTP_SERVER_PORT.asInt());
16 | IPaymentService service = new PaymentServiceImpl();
17 | WebServer server = new WebServer(service);
18 | server.start();
19 | server.registerShutdownHook();
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/server/src/main/java/com/payneteasy/pos/proxy/WebServer.java:
--------------------------------------------------------------------------------
1 | package com.payneteasy.pos.proxy;
2 |
3 | import com.payneteasy.pos.proxy.messages.*;
4 | import one.nio.http.*;
5 | import one.nio.server.AcceptorConfig;
6 | import one.nio.util.ByteArrayBuilder;
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 |
10 | import java.io.IOException;
11 | import java.io.InputStream;
12 | import java.util.concurrent.Executor;
13 | import java.util.concurrent.Executors;
14 |
15 |
16 | public class WebServer extends HttpServer {
17 |
18 | private static final Logger LOG = LoggerFactory.getLogger(WebServer.class);
19 | private static final Executor PAYMENT_EXECUTOR = Executors.newSingleThreadExecutor();
20 |
21 | private static final String EXPECTED_API_KEY = ": " + Configs.API_KEY.asString();
22 |
23 | private final IPaymentService paymentService;
24 |
25 | public WebServer(IPaymentService aPaymentService) throws IOException {
26 | super(createConfig(Configs.HTTP_SERVER_ADDRESS.asString(), Configs.HTTP_SERVER_PORT.asInt()));
27 | paymentService = aPaymentService;
28 | }
29 |
30 | private static HttpServerConfig createConfig(String aAddress, int aPort) {
31 | AcceptorConfig acceptorConfig = new AcceptorConfig();
32 | acceptorConfig.address = aAddress;
33 | acceptorConfig.port = aPort;
34 |
35 | HttpServerConfig config = new HttpServerConfig();
36 | config.acceptors = new AcceptorConfig[]{acceptorConfig};
37 | config.selectors = Configs.HTTP_SERVER_SELECTORS.asInt();
38 | config.minWorkers = Configs.HTTP_SERVER_MIN_WORKERS.asInt();
39 | config.maxWorkers = Configs.HTTP_SERVER_MAX_WORKERS.asInt();
40 | return config;
41 |
42 | }
43 |
44 | @Path("/pos-proxy/management/version.txt")
45 | public Response handleVersion() {
46 | return Response.ok(Configs.getVersion());
47 | }
48 |
49 | @Path("/pos-proxy/pay")
50 | public void pay(Request aRequest, HttpSession aSession) throws IOException {
51 | PAYMENT_EXECUTOR.execute(() -> {
52 | try {
53 | if (!checkApiKey(aRequest, aSession)) {
54 | return;
55 | }
56 | JsonMessages json = new JsonMessages(aRequest);
57 | PaymentRequest request = json.parse(PaymentRequest.class);
58 | PaymentResponse response = paymentService.pay(request);
59 | aSession.sendResponse(json.response(response));
60 | } catch (Exception e) {
61 | sendError("Error while processing pay", aSession, e);
62 | }
63 | });
64 | }
65 |
66 | @Path("/pos-proxy/refund")
67 | public void refund(Request aRequest, HttpSession aSession) throws IOException {
68 | PAYMENT_EXECUTOR.execute(() -> {
69 | try {
70 | if (!checkApiKey(aRequest, aSession)) {
71 | return;
72 | }
73 | JsonMessages json = new JsonMessages(aRequest);
74 | RefundRequest request = json.parse(RefundRequest.class);
75 | PaymentResponse response = paymentService.refund(request);
76 | aSession.sendResponse(json.response(response));
77 | } catch (Exception e) {
78 | sendError("Error while processing pay", aSession, e);
79 | }
80 | });
81 | }
82 |
83 | @Path("/pos-proxy/close-day")
84 | public void closeDay(Request aRequest, HttpSession aSession) throws IOException {
85 | PAYMENT_EXECUTOR.execute(() -> {
86 | try {
87 | if (!checkApiKey(aRequest, aSession)) {
88 | return;
89 | }
90 | JsonMessages json = new JsonMessages(aRequest);
91 | CloseDayRequest request = json.parse(CloseDayRequest.class);
92 | CloseDayResponse response = paymentService.closeDay(request);
93 | aSession.sendResponse(json.response(response));
94 | } catch (Exception e) {
95 | sendError("Error while processing pay", aSession, e);
96 | }
97 | });
98 | }
99 |
100 | private boolean checkApiKey(Request aRequest, HttpSession aSession) throws IOException {
101 | String apiKey = aRequest.getHeader("X-API-Key");
102 |
103 | if(EXPECTED_API_KEY.equals(apiKey)) {
104 | return true;
105 | } else {
106 | LOG.error("Expected X-API-Key is '{}' but was '{}'", EXPECTED_API_KEY, apiKey);
107 | aSession.sendError(Response.FORBIDDEN, "Wrong X-API-Key");
108 | return false;
109 |
110 | }
111 | }
112 |
113 |
114 | @Override
115 | public void handleDefault(Request aRequest, HttpSession aSession) throws IOException {
116 | if(aRequest.getURI().startsWith("/pos-proxy/swagger-ui")) {
117 | swagger(aRequest, aSession);
118 | } else {
119 | super.handleDefault(aRequest, aSession);
120 | }
121 | }
122 |
123 | public void swagger(Request aRequest, HttpSession aSession) {
124 | asyncExecute(() -> {
125 | try {
126 | String filename = aRequest.getURI().substring("/pos-proxy/swagger-ui".length());
127 | if(filename.length() == 0) {
128 | aSession.sendResponse(Response.redirect("/pos-proxy/swagger-ui/"));
129 | return;
130 | }
131 | if(filename.length() == 1) {
132 | filename = "/index.html";
133 | }
134 | String resource = "/swagger-ui" + filename;
135 | InputStream in = WebServer.class.getResourceAsStream(resource);
136 | if(in == null) {
137 | LOG.warn("Resource {} -> {} not found", aRequest.getURI(), resource);
138 | aSession.sendError(Response.NOT_FOUND, "Resource " + resource + " not found\n");
139 | return;
140 | }
141 | ByteArrayBuilder byteArrayBuilder = readStream(in);
142 | aSession.sendResponse(new Response(Response.OK, byteArrayBuilder.toBytes()));
143 | } catch (Exception e) {
144 | sendError("Cannot process " + aRequest.getURI(), aSession, e);
145 | }
146 | });
147 | }
148 |
149 | public String getResourceName(String aUri) {
150 | return aUri;
151 | }
152 |
153 | private void sendError(String aMessage, HttpSession aSession, Exception e) {
154 | LOG.error("Error: {}", aMessage, e);
155 | try {
156 | aSession.sendError(Response.INTERNAL_ERROR, e.getMessage());
157 | } catch (IOException e1) {
158 | LOG.error("Cannot send error: {}", aMessage, e);
159 | }
160 |
161 | }
162 |
163 | private static ByteArrayBuilder readStream(InputStream in) throws IOException {
164 | byte[] buffer = new byte[64000];
165 | ByteArrayBuilder builder = new ByteArrayBuilder(buffer.length);
166 | for (int bytes; (bytes = in.read(buffer)) > 0; ) {
167 | builder.append(buffer, 0, bytes);
168 | }
169 | return builder;
170 | }
171 |
172 |
173 | }
174 |
--------------------------------------------------------------------------------
/server/src/main/java/com/payneteasy/pos/proxy/impl/InpasNetworkClientExtended.java:
--------------------------------------------------------------------------------
1 | package com.payneteasy.pos.proxy.impl;
2 |
3 | import com.payneteasy.android.sdk.logger.ILogger;
4 | import com.payneteasy.android.sdk.reader.inpas.config.InpasTerminalConfiguration;
5 | import com.payneteasy.android.sdk.util.LoggerUtil;
6 | import com.payneteasy.inpas.sa.client.SmartAgentClient;
7 | import com.payneteasy.inpas.sa.messages.sale.*;
8 |
9 | import java.io.IOException;
10 | import java.math.BigDecimal;
11 |
12 | public class InpasNetworkClientExtended {
13 |
14 | private static final ILogger LOG = LoggerUtil.create(InpasNetworkClientExtended.class);
15 |
16 | private final SmartAgentClient delegate;
17 | private final String address;
18 | private final InpasTerminalConfiguration configuration;
19 |
20 | public InpasNetworkClientExtended(String aAddress, InpasTerminalConfiguration aConfiguration) {
21 | delegate = new SmartAgentClient(aConfiguration.createNetworkClientOptions(aAddress));
22 | address = aAddress;
23 | configuration = aConfiguration;
24 | }
25 |
26 | public void connect() throws InterruptedException {
27 | while (!Thread.currentThread().isInterrupted()) {
28 | try {
29 | delegate.openConnection();
30 | return;
31 | } catch (IOException e) {
32 | if(configuration.throwExceptionIfCannotConnect()) {
33 | throw new IllegalStateException("Cannot connect to " + address, e);
34 | } else {
35 | LOG.error("Cannot connect to {}. Sleeping 1 second ...", address, e);
36 | Thread.sleep(1_000);
37 | }
38 | }
39 | }
40 |
41 | }
42 |
43 | public Sa1PaymentResponse makeSale(String aCurrency, BigDecimal aAmount, String aTerminalId) throws IOException {
44 | Sa1PaymentResponse saleResponse = delegate.sale(new Sa1PaymentRequest.Builder()
45 | ._04_currencyCode(643)
46 | ._00_amount(aAmount)
47 | ._26_stan(configuration.getInvoice())
48 | ._27_terminalId(aTerminalId)
49 | .build());
50 | return saleResponse;
51 | }
52 |
53 | public Sa29ReversalResponse makeReversal(String aCurrency, BigDecimal aAmount, String aRrn, String aTerminalId) throws IOException {
54 |
55 | Sa29ReversalRequest request = new Sa29ReversalRequest.Builder()
56 | ._00_amount(aAmount)
57 | ._04_currencyCode(643)
58 | ._26_stan(configuration.getInvoice())
59 | ._14_rrn(aRrn)
60 | ._27_terminalId(aTerminalId)
61 | .build();
62 | return delegate.reversal(request);
63 | }
64 |
65 | public void makeReconciliation(String aTerminalId) {
66 | try {
67 | Sa59ReconciliationResponse reconciliation = delegate.reconciliation(new Sa59ReconciliationRequest.Builder()._27_terminalId(aTerminalId).build());
68 | } catch (IOException e) {
69 | LOG.error("Cannot make reconciliation", e);
70 | }
71 | }
72 |
73 | public void closeConnection() {
74 | try {
75 | delegate.close();
76 | } catch (Exception e) {
77 | LOG.error("Error while closing connection", e);
78 | }
79 | }
80 |
81 | public void sendEot() {
82 | try {
83 | delegate.sendEot();
84 | } catch (Exception e) {
85 | LOG.error("Cannot send EOT", e);
86 | }
87 | }
88 |
89 | public Sa26TestConnectionResponse checkConnection(String aTerminalId ) {
90 | try {
91 | LOG.debug("InpasNetworkClient; checkConnection new branch");
92 | return delegate.testConnectionToHost(aTerminalId);
93 | } catch (IOException e) {
94 | LOG.error("Error while testConnectionLocal", e);
95 | }
96 |
97 | return null;
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/server/src/main/java/com/payneteasy/pos/proxy/impl/InpasNetworkManager.java:
--------------------------------------------------------------------------------
1 | package com.payneteasy.pos.proxy.impl;
2 |
3 | import com.payneteasy.android.sdk.reader.inpas.config.InpasTerminalConfiguration;
4 | import com.payneteasy.android.sdk.reader.inpas.network.InpasNetworkClient;
5 | import com.payneteasy.inpas.sa.client.handlers.DefaultClientPacketOptions;
6 | import com.payneteasy.pos.proxy.messages.PaymentResponse;
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 |
10 | import java.io.IOException;
11 |
12 | public class InpasNetworkManager {
13 |
14 | private static final Logger LOG = LoggerFactory.getLogger(InpasNetworkManager.class);
15 |
16 | private final String amount;
17 | private final String currency;
18 | private final String posAddress;
19 |
20 | public InpasNetworkManager(String amount, String currency, String aPosAddress) {
21 | this.amount = amount;
22 | this.currency = currency;
23 | posAddress = aPosAddress;
24 | }
25 |
26 | public interface IInpasOperationHandler {
27 | PaymentResponse invokeOperation(InpasNetworkClientExtended aClient) throws IOException;
28 | }
29 |
30 | public PaymentResponse makeOperation(IInpasOperationHandler aHandler) {
31 | InpasNetworkClientExtended client = new InpasNetworkClientExtended(posAddress, new InpasTerminalConfiguration.Builder()
32 | .packetOptions(new DefaultClientPacketOptions())
33 | .throwExceptionIfCannotConnect(true)
34 | .build()
35 | );
36 | try {
37 | client.connect();
38 | try {
39 |
40 | return aHandler.invokeOperation(client);
41 |
42 | } catch (Exception e) {
43 | client.sendEot();
44 | LOG.error("Cannot process a payment", e);
45 | return error("-1");
46 | } finally {
47 | client.closeConnection();
48 | }
49 | } catch (InterruptedException e) {
50 | Thread.currentThread().interrupt();
51 | throw new IllegalStateException("Interrupted");
52 | } catch (Exception e) {
53 | LOG.error("Cannot connect", e);
54 | return error("-2");
55 | }
56 |
57 | }
58 |
59 | private PaymentResponse error(String aErrorCode) {
60 | return PaymentResponse.builder()
61 | .amount ( amount )
62 | .currency ( currency )
63 | .orderId ( null )
64 | .responseCode ( aErrorCode )
65 | .build();
66 | }
67 |
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/server/src/main/java/com/payneteasy/pos/proxy/impl/PaymentServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.payneteasy.pos.proxy.impl;
2 |
3 | import com.payneteasy.inpas.sa.messages.sale.Sa1PaymentResponse;
4 | import com.payneteasy.inpas.sa.messages.sale.Sa29ReversalResponse;
5 | import com.payneteasy.pos.proxy.IPaymentService;
6 | import com.payneteasy.pos.proxy.messages.*;
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 |
10 | import java.math.BigDecimal;
11 |
12 | public class PaymentServiceImpl implements IPaymentService {
13 |
14 | private static final Logger LOG = LoggerFactory.getLogger(PaymentServiceImpl.class);
15 |
16 | @Override
17 | public PaymentResponse pay(PaymentRequest aRequest) {
18 | InpasNetworkManager manager = new InpasNetworkManager(aRequest.getAmount(), aRequest.getCurrency(), aRequest.getPosAddress());
19 |
20 | return manager.makeOperation(aClient -> {
21 | Sa1PaymentResponse saResponse = aClient.makeSale(
22 | aRequest.getCurrency()
23 | , new BigDecimal(aRequest.getAmount())
24 | , aRequest.getTerminalId()
25 | );
26 |
27 | return PaymentResponse.builder()
28 | .amount ( saResponse.get_00_amount().toString() )
29 | .currency ( aRequest.getCurrency() )
30 | .orderId ( saResponse.get_14_rrn() )
31 | .responseCode ( saResponse.get_15_responseCode() )
32 | .build();
33 | });
34 | }
35 |
36 | @Override
37 | public PaymentResponse refund(RefundRequest aRequest) {
38 | InpasNetworkManager manager = new InpasNetworkManager(aRequest.getRefundAmount(), aRequest.getCurrency(), aRequest.getPosAddress());
39 |
40 | return manager.makeOperation(aClient -> {
41 | Sa29ReversalResponse saResponse = aClient.makeReversal(
42 | aRequest.getCurrency()
43 | , new BigDecimal(aRequest.getRefundAmount())
44 | , aRequest.getOrderId()
45 | , aRequest.getTerminalId()
46 | );
47 |
48 | return PaymentResponse.builder()
49 | .amount ( saResponse.get_00_amount().toString() )
50 | .currency ( aRequest.getCurrency() )
51 | .orderId ( aRequest.getOrderId() )
52 | .responseCode ( saResponse.get_15_responseCode() )
53 | .build();
54 | });
55 | }
56 |
57 | @Override
58 | public CloseDayResponse closeDay(CloseDayRequest aRequest) {
59 | InpasNetworkManager manager = new InpasNetworkManager("0", "RUB", aRequest.getPosAddress());
60 |
61 | PaymentResponse response = manager.makeOperation(aClient -> {
62 | aClient.makeReconciliation(aRequest.getTerminalId());
63 | return PaymentResponse.builder()
64 | .responseCode("00")
65 | .currency("RUB")
66 | .amount("0")
67 | .build();
68 | });
69 |
70 | return new CloseDayResponse(response.getResponseCode());
71 | }
72 |
73 | public static String toRrn(long aOrderId) {
74 | StringBuilder sb = new StringBuilder();
75 | sb.append(aOrderId);
76 | while(sb.length() < 11) {
77 | sb.insert(0, "0");
78 | }
79 | sb.insert(0, "P");
80 | return sb.toString();
81 | }
82 |
83 | private Long getPaynetOrderId(Sa1PaymentResponse saResponse) {
84 | if(saResponse.get_14_rrn() == null) {
85 | return null;
86 | }
87 | return Long.parseLong(saResponse.get_14_rrn().replace("P", ""));
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/server/src/main/java/com/payneteasy/pos/proxy/messages/CloseDayRequest.java:
--------------------------------------------------------------------------------
1 | package com.payneteasy.pos.proxy.messages;
2 |
3 | import lombok.Data;
4 | import lombok.NonNull;
5 |
6 | @Data
7 | public class CloseDayRequest {
8 |
9 | @NonNull
10 | private final String posAddress;
11 |
12 | @NonNull
13 | private final String posType;
14 |
15 | private final String terminalId;
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/server/src/main/java/com/payneteasy/pos/proxy/messages/CloseDayResponse.java:
--------------------------------------------------------------------------------
1 | package com.payneteasy.pos.proxy.messages;
2 |
3 | import lombok.Data;
4 | import lombok.NonNull;
5 |
6 | @Data
7 | public class CloseDayResponse {
8 |
9 | @NonNull
10 | private final String responseCode;
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/server/src/main/java/com/payneteasy/pos/proxy/messages/PaymentRequest.java:
--------------------------------------------------------------------------------
1 | package com.payneteasy.pos.proxy.messages;
2 |
3 | import lombok.Data;
4 | import lombok.NonNull;
5 |
6 | @Data
7 | public class PaymentRequest {
8 |
9 | @NonNull
10 | private final String amount;
11 |
12 | @NonNull
13 | private final String currency;
14 |
15 | @NonNull
16 | private final String posAddress;
17 |
18 | @NonNull
19 | private final String posType;
20 |
21 | private final String terminalId;
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/server/src/main/java/com/payneteasy/pos/proxy/messages/PaymentResponse.java:
--------------------------------------------------------------------------------
1 | package com.payneteasy.pos.proxy.messages;
2 |
3 | import lombok.Builder;
4 | import lombok.Data;
5 | import lombok.NonNull;
6 |
7 | @Data
8 | @Builder
9 | public class PaymentResponse {
10 |
11 |
12 | @NonNull
13 | private final String amount;
14 |
15 | @NonNull
16 | private final String currency;
17 |
18 | @NonNull
19 | private final String responseCode;
20 |
21 | private final String orderId;
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/server/src/main/java/com/payneteasy/pos/proxy/messages/RefundRequest.java:
--------------------------------------------------------------------------------
1 | package com.payneteasy.pos.proxy.messages;
2 |
3 | import lombok.Data;
4 | import lombok.NonNull;
5 |
6 | @Data
7 | public class RefundRequest {
8 |
9 | @NonNull
10 | private final String refundAmount;
11 |
12 | /**
13 | * Paynet order id to refund
14 | */
15 | private final String orderId;
16 |
17 | @NonNull
18 | private final String currency;
19 |
20 | @NonNull
21 | private final String posAddress;
22 |
23 | @NonNull
24 | private final String posType;
25 |
26 | private final String terminalId;
27 | }
28 |
--------------------------------------------------------------------------------
/server/src/main/resources/swagger-ui/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/payneteasy/pos-proxy/4b261fc96dfaf95f2829ece62c59e3dd810c37eb/server/src/main/resources/swagger-ui/favicon-16x16.png
--------------------------------------------------------------------------------
/server/src/main/resources/swagger-ui/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/payneteasy/pos-proxy/4b261fc96dfaf95f2829ece62c59e3dd810c37eb/server/src/main/resources/swagger-ui/favicon-32x32.png
--------------------------------------------------------------------------------
/server/src/main/resources/swagger-ui/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Swagger UI
7 |
8 |
9 |
10 |
11 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/server/src/main/resources/swagger-ui/oauth2-redirect.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
68 |
--------------------------------------------------------------------------------
/server/src/main/resources/swagger-ui/pos-proxy.json:
--------------------------------------------------------------------------------
1 | {
2 | "swagger": "2.0",
3 | "info": {
4 | "title": "Lounge Config Service",
5 | "version": "1.0.1"
6 | },
7 | "host": "0.0.0.0:8081",
8 | "securityDefinitions": {
9 | "APIKeyHeader": {
10 | "type": "apiKey",
11 | "in": "header",
12 | "name": "X-API-Key"
13 | }
14 | },
15 | "security": [
16 | {
17 | "APIKeyHeader": []
18 | }
19 | ],
20 | "schemes": [
21 | "http",
22 | "https"
23 | ],
24 | "basePath": "/pos-proxy",
25 | "produces": [
26 | "application/json"
27 | ],
28 | "paths": {
29 | "/pay": {
30 | "post": {
31 | "tags": [
32 | "proxy"
33 | ],
34 | "summary": "Make a payment",
35 | "parameters": [
36 | {
37 | "in": "body",
38 | "name": "body",
39 | "required": true,
40 | "schema": {
41 | "title": "Payment Request",
42 | "type": "object",
43 | "additionalProperties": false,
44 | "properties": {
45 | "amount": {
46 | "type": "string",
47 | "description": "Amount",
48 | "example": "10.00"
49 | },
50 | "currency": {
51 | "type": "string",
52 | "description": "Currency",
53 | "example": "RUB"
54 | },
55 | "posType": {
56 | "type": "string",
57 | "enum": [
58 | "INPAS"
59 | ],
60 | "description": "POS terminal type",
61 | "example": "INPAS"
62 | },
63 | "posAddress": {
64 | "type": "string",
65 | "description": "POS terminal address",
66 | "example": "10.0.1.20:27015"
67 | },
68 | "terminalId": {
69 | "type": "string",
70 | "description": "Terminal ID",
71 | "example": "3A123456"
72 | }
73 | }
74 | }
75 | }
76 | ],
77 | "responses": {
78 | "200": {
79 | "description": "Status",
80 | "schema": {
81 | "title": "Control Response",
82 | "type": "object",
83 | "additionalProperties": false,
84 | "properties": {
85 | "responseCode": {
86 | "type": "string",
87 | "description": "00 - Approved, other codes - errors"
88 | },
89 | "orderId": {
90 | "type": "integer",
91 | "format": "int64"
92 | }
93 | }
94 | }
95 | }
96 | }
97 | }
98 | },
99 | "/refund": {
100 | "post": {
101 | "tags": [
102 | "proxy"
103 | ],
104 | "summary": "Make a refund",
105 | "parameters": [
106 | {
107 | "in": "body",
108 | "name": "body",
109 | "required": true,
110 | "schema": {
111 | "title": "Refund Request",
112 | "type": "object",
113 | "additionalProperties": false,
114 | "properties": {
115 | "refundAmount": {
116 | "type": "string",
117 | "description": "Refund amount",
118 | "example": "10.00"
119 | },
120 | "currency": {
121 | "type": "string",
122 | "description": "Currency",
123 | "example": "RUB"
124 | },
125 | "orderId": {
126 | "type": "integer",
127 | "format": "int64"
128 | },
129 | "posType": {
130 | "type": "string",
131 | "enum": [
132 | "INPAS"
133 | ],
134 | "description": "POS terminal type",
135 | "example": "INPAS"
136 | },
137 | "posAddress": {
138 | "type": "string",
139 | "description": "POS terminal address",
140 | "example": "10.0.1.20:27015"
141 | },
142 | "terminalId": {
143 | "type": "string",
144 | "description": "Terminal ID",
145 | "example": "3A123456"
146 | }
147 | }
148 | }
149 | }
150 | ],
151 | "responses": {
152 | "200": {
153 | "description": "Status",
154 | "schema": {
155 | "title": "Control Response",
156 | "type": "object",
157 | "additionalProperties": false,
158 | "properties": {
159 | "responseCode": {
160 | "type": "string",
161 | "description": "00 - Approved, other codes - errors"
162 | },
163 | "orderId": {
164 | "type": "integer",
165 | "format": "int64"
166 | }
167 | }
168 | }
169 | }
170 | }
171 | }
172 | },
173 | "/close-day": {
174 | "post": {
175 | "tags": [
176 | "proxy"
177 | ],
178 | "summary": "Close day",
179 | "parameters": [
180 | {
181 | "in": "body",
182 | "name": "body",
183 | "required": true,
184 | "schema": {
185 | "title": "Close Day Request",
186 | "type": "object",
187 | "additionalProperties": false,
188 | "properties": {
189 | "posType": {
190 | "type": "string",
191 | "enum": [
192 | "INPAS"
193 | ],
194 | "description": "POS terminal type",
195 | "example": "INPAS"
196 | },
197 | "posAddress": {
198 | "type": "string",
199 | "description": "POS terminal address",
200 | "example": "10.0.1.20:27015"
201 | },
202 | "terminalId": {
203 | "type": "string",
204 | "description": "Terminal ID",
205 | "example": "3A123456"
206 | }
207 | }
208 | }
209 | }
210 | ],
211 | "responses": {
212 | "200": {
213 | "description": "Status",
214 | "schema": {
215 | "title": "Close Day Response",
216 | "type": "object",
217 | "additionalProperties": false,
218 | "properties": {
219 | "responseCode": {
220 | "type": "string",
221 | "description": "00 - Approved, other codes - errors"
222 | }
223 | }
224 | }
225 | }
226 | }
227 | }
228 | }
229 | }
230 | }
--------------------------------------------------------------------------------
/server/src/main/resources/swagger-ui/swagger-ui.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":[],"names":[],"mappings":"","file":"swagger-ui.css","sourceRoot":""}
--------------------------------------------------------------------------------
/swagger/make-bundle.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -eux
3 | swagger-ui-watcher pos-proxy.yaml --bundle ../server/src/main/resources/swagger-ui/pos-proxy.json
4 |
--------------------------------------------------------------------------------
/swagger/messages/CloseDayRequest.yaml:
--------------------------------------------------------------------------------
1 | title: "Close Day Request"
2 | type: "object"
3 | additionalProperties: false
4 | properties:
5 | posType:
6 | type: "string"
7 | enum:
8 | - "INPAS"
9 | description: "POS terminal type"
10 | example: "INPAS"
11 |
12 | posAddress:
13 | type: "string"
14 | description: "POS terminal address"
15 | example: "10.0.1.20:27015"
16 |
17 | terminalId:
18 | type: "string"
19 | description: "Terminal ID"
20 | example: "3A123456"
21 |
--------------------------------------------------------------------------------
/swagger/messages/CloseDayResponse.yaml:
--------------------------------------------------------------------------------
1 | title: "Close Day Response"
2 | type: "object"
3 | additionalProperties: false
4 | properties:
5 | responseCode:
6 | type: "string"
7 | description: "00 - Approved, other codes - errors"
8 |
9 |
--------------------------------------------------------------------------------
/swagger/messages/PaymentRequest.yaml:
--------------------------------------------------------------------------------
1 | title: "Payment Request"
2 | type: "object"
3 | additionalProperties: false
4 | properties:
5 | amount:
6 | type: "string"
7 | description: "Amount"
8 | example: "10.00"
9 |
10 | currency:
11 | type: "string"
12 | description: "Currency"
13 | example: "RUB"
14 |
15 | posType:
16 | type: "string"
17 | enum:
18 | - "INPAS"
19 | description: "POS terminal type"
20 | example: "INPAS"
21 |
22 |
23 | posAddress:
24 | type: "string"
25 | description: "POS terminal address"
26 | example: "10.0.1.20:27015"
27 |
28 | terminalId:
29 | type: "string"
30 | description: "Terminal ID"
31 | example: "3A123456"
32 |
33 |
--------------------------------------------------------------------------------
/swagger/messages/PaymentResponse.yaml:
--------------------------------------------------------------------------------
1 | title: "Control Response"
2 | type: "object"
3 | additionalProperties: false
4 | properties:
5 | responseCode:
6 | type: "string"
7 | description: "00 - Approved, other codes - errors"
8 |
9 | orderId:
10 | type: "integer"
11 | format: "int64"
12 |
13 |
14 |
--------------------------------------------------------------------------------
/swagger/messages/RefundRequest.yaml:
--------------------------------------------------------------------------------
1 | title: "Refund Request"
2 | type: "object"
3 | additionalProperties: false
4 | properties:
5 | refundAmount:
6 | type: "string"
7 | description: "Refund amount"
8 | example: "10.00"
9 |
10 | currency:
11 | type: "string"
12 | description: "Currency"
13 | example: "RUB"
14 |
15 | orderId:
16 | type: "integer"
17 | format: "int64"
18 |
19 | posType:
20 | type: "string"
21 | enum:
22 | - "INPAS"
23 | description: "POS terminal type"
24 | example: "INPAS"
25 |
26 | posAddress:
27 | type: "string"
28 | description: "POS terminal address"
29 | example: "10.0.1.20:27015"
30 |
31 | terminalId:
32 | type: "string"
33 | description: "Terminal ID"
34 | example: "3A123456"
35 |
--------------------------------------------------------------------------------
/swagger/pos-proxy.yaml:
--------------------------------------------------------------------------------
1 | swagger: '2.0'
2 | info:
3 | title: Lounge Config Service
4 | version: "1.0.1"
5 |
6 | host: 0.0.0.0:8081
7 |
8 | securityDefinitions:
9 | APIKeyHeader:
10 | type: apiKey
11 | in: header
12 | name: X-API-Key
13 | security:
14 | - APIKeyHeader: []
15 |
16 | schemes:
17 | - http
18 | - https
19 | basePath: /pos-proxy
20 | produces:
21 | - application/json
22 |
23 | paths:
24 | /pay:
25 | post:
26 | tags: ['proxy']
27 | summary: Make a payment
28 | parameters:
29 | - in: body
30 | name: body
31 | required: true
32 | schema:
33 | $ref: './messages/PaymentRequest.yaml'
34 | responses:
35 | 200:
36 | description: Status
37 | schema:
38 | $ref: './messages/PaymentResponse.yaml'
39 |
40 | /refund:
41 | post:
42 | tags: ['proxy']
43 | summary: Make a refund
44 | parameters:
45 | - in: body
46 | name: body
47 | required: true
48 | schema:
49 | $ref: './messages/RefundRequest.yaml'
50 | responses:
51 | 200:
52 | description: Status
53 | schema:
54 | $ref: './messages/PaymentResponse.yaml'
55 |
56 | /close-day:
57 | post:
58 | tags: ['proxy']
59 | summary: Close day
60 | parameters:
61 | - in: body
62 | name: body
63 | required: true
64 | schema:
65 | $ref: './messages/CloseDayRequest.yaml'
66 | responses:
67 | 200:
68 | description: Status
69 | schema:
70 | $ref: './messages/CloseDayResponse.yaml'
71 |
--------------------------------------------------------------------------------
/swagger/run-ui.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | swagger-ui-watcher pos-proxy.yaml
3 |
--------------------------------------------------------------------------------