From version 6.1
edited by Thomas Warren
on 2020/01/23 13:26
To version 7.1
edited by Thomas Warren
on 2020/01/23 13:27
Change comment: There is no comment for this version

Summary

Details

Page properties
Content
... ... @@ -1,33 +1,17 @@
1 -##~#~# Overview##
1 +## Prerequisites
2 2  
3 -##~-~--##
3 +---
4 4  
5 -##This API is a gateway for receiving payments through our system. It's ment to simplify external integration between different domains such as credit cards, prepaid cards and value codes.##
5 +* Java 11
6 +* VueJS
7 +* Maven
8 +* Postgres
6 6  
7 -##~#~# Swagger documentation##
10 +## Project setup
8 8  
9 -##~-~--##
12 +---
10 10  
11 -##* [VasPublicPaymentApi](https:~/~/stage-evc.payex.com/payment-api/swagger-ui.html)##
12 -
13 -### Public Payment API Client##
14 -
15 -##~-~--##
16 -
17 -##~#~# Prerequisites##
18 -
19 -##~-~--##
20 -
21 -##* Java 11
22 -~* VueJS
23 -~* Maven
24 -~* Postgres##
25 -
26 -##~#~# Project setup##
27 -
28 -##~-~--##
29 -
30 -## vas-payment-api-client
14 + vas-payment-api-client
31 31   ├─┬ backend → backend module with Spring Boot code
32 32   │ ├── src
33 33   │ └── pom.xml
... ... @@ -34,20 +34,20 @@
34 34   ├─┬ frontend → frontend module with Vue.js code
35 35   │ ├── src
36 36   │ └── pom.xml
37 - └── pom.xml → Maven parent pom managing both modules##
21 + └── pom.xml → Maven parent pom managing both modules
38 38  
39 -##~#~# Security##
23 +## Security
40 40  
41 -##~-~--##
25 +---
42 42  
43 -##<details>
44 -<summary>Oauth2:</summary>##
27 +<details>
28 +<summary>Oauth2:</summary>
45 45  
46 -##VasPublicPaymentApi requires an OAuth2 access token for interaction.
47 -This application automatically handles token fetching and refreshing by using [Spring Security](https:~/~/docs.spring.io/spring-security-oauth2-boot/docs/current/reference/htmlsingle/#boot-features-security-custom-user-info-client).
48 -Configuration values are set in [application.yml](https:~/~/github.com/PayEx/vas-payment-api-client/blob/master/backend/src/main/resources/application.yml): ##
30 +VasPublicPaymentApi requires an OAuth2 access token for interaction.
31 +This application automatically handles token fetching and refreshing by using [Spring Security](https://docs.spring.io/spring-security-oauth2-boot/docs/current/reference/htmlsingle/#boot-features-security-custom-user-info-client).
32 +Configuration values are set in [application.yml](https://github.com/PayEx/vas-payment-api-client/blob/master/backend/src/main/resources/application.yml):
49 49  
50 -##```yaml
34 +```yaml
51 51  # "XXX" Should be replaced by value provided by PayEx
52 52  # CLIENT_ID/CLIENT_SECRET/VAS_AUTH_SERVER_URL can also be set in docker-compose.yml as environment variables if running with docker
53 53  # The application will see if environment variables are present, if not fall back to "XXX" values.
... ... @@ -58,51 +58,51 @@
58 58   clientId: "${CLIENT_ID}:XXX"
59 59   clientSecret: "${CLIENT_SECRET}:XXX"
60 60   accessTokenUri: "${VAS_AUTH_SERVER_URL}:XXX"
61 - scope: publicapi
62 -
63 -```##
45 + scope: publicapi
46 +
47 +```
64 64  
65 -##And the implementation of these are located in [Oauth2RestTemplateConfiguration.java](https:~/~/github.com/PayEx/vas-payment-api-client/blob/master/backend/src/main/java/com/payex/vas/demo/config/security/Oauth2RestTemplateConfiguration.java):##
49 +And the implementation of these are located in [Oauth2RestTemplateConfiguration.java](https://github.com/PayEx/vas-payment-api-client/blob/master/backend/src/main/java/com/payex/vas/demo/config/security/Oauth2RestTemplateConfiguration.java):
66 66  
67 -##```java
51 +```java
68 68  public class Oauth2RestTemplateConfiguration {
69 - ~/~/...
53 + //...
70 70   @Bean
71 71   @ConfigurationProperties("vas-payment-api.oauth2.client")
72 72   protected ClientCredentialsResourceDetails oAuthDetails() {
73 73   return new ClientCredentialsResourceDetails();
74 - }##
58 + }
75 75  
76 -## @Bean
60 + @Bean
77 77   protected RestTemplate restTemplate() {
78 78   var restTemplate = new OAuth2RestTemplate(oAuthDetails());
79 - restTemplate.setInterceptors(ImmutableList.of(externalRequestInterceptor(~)~)~);
63 + restTemplate.setInterceptors(ImmutableList.of(externalRequestInterceptor()));
80 80   restTemplate.setRequestFactory(httpRequestFactory());
81 81   return restTemplate;
82 82   }
83 - ~/~/...
67 + //...
84 84  }
85 85  ```
86 -</details>##
70 +</details>
87 87  
88 -##<details>##
72 +<details>
89 89  
90 -##<summary>HMAC:</summary>##
74 +<summary>HMAC:</summary>
91 91  
92 -##The API also requires HMAC authentication to be present in a request.
93 -In this client the HMAC value is automatically calculated by [HmacSignatureBuilder.java](https:~/~/github.com/PayEx/vas-payment-api-client/blob/master/backend/src/main/java/com/payex/vas/demo/config/security/HmacSignatureBuilder.java) and added to all outgoing requests in [ExternalRequestInterceptor.java](https:~/~/github.com/PayEx/vas-payment-api-client/blob/master/backend/src/main/java/com/payex/vas/demo/config/ExternalRequestInterceptor.java)##
76 +The API also requires HMAC authentication to be present in a request.
77 +In this client the HMAC value is automatically calculated by [HmacSignatureBuilder.java](https://github.com/PayEx/vas-payment-api-client/blob/master/backend/src/main/java/com/payex/vas/demo/config/security/HmacSignatureBuilder.java) and added to all outgoing requests in [ExternalRequestInterceptor.java](https://github.com/PayEx/vas-payment-api-client/blob/master/backend/src/main/java/com/payex/vas/demo/config/ExternalRequestInterceptor.java)
94 94  
95 -##HMAC is implemented using SHA-512 secure hash algorithm. ##
79 +HMAC is implemented using SHA-512 secure hash algorithm.
96 96  
97 -##Expected `Hmac` header format is:##
81 +Expected `Hmac` header format is:
98 98  
99 -##```text
100 -HmacSHA512 <user>:<nonce>:<digest>
101 -```##
83 +```text
84 +HmacSHA512 <user>:<nonce>:<digest>
85 +```
102 102  
103 -##where `digest` is a Base64 formatted HMAC SHA512 digest of the following string: ##
87 +where `digest` is a Base64 formatted HMAC SHA512 digest of the following string:
104 104  
105 -##```text
89 +```text
106 106  METHOD\n
107 107  RESOURCE\n
108 108  USER\
... ... @@ -109,16 +109,16 @@
109 109  NONCE\n
110 110  DATE\n
111 111  PAYLOAD\n
112 -```##
96 +```
113 113  
114 -##`METHOD` (mandatory) the requested method (in upper case) `RESOURCE` (mandatory) the path to desired resource (without hostname and any query parameters)
115 -`NONSE` (mandatory) a unique value for each request ([UUID](https:~/~/tools.ietf.org/rfc/rfc4122.txt)) `DATE`(optional) same as `Transmission-Time` if provided as seperate header. Uses [ISO8601 standard](https:~/~/en.wikipedia.org/wiki/ISO_8601) `PAYLOAD` (optional) body of request ##
98 +`METHOD` (mandatory) the requested method (in upper case) `RESOURCE` (mandatory) the path to desired resource (without hostname and any query parameters)
99 +`NONSE` (mandatory) a unique value for each request ([UUID](https://tools.ietf.org/rfc/rfc4122.txt)) `DATE`(optional) same as `Transmission-Time` if provided as seperate header. Uses [ISO8601 standard](https://en.wikipedia.org/wiki/ISO_8601) `PAYLOAD` (optional) body of request
116 116  
117 -##Example request:##
101 +Example request:
118 118  
119 -##```bash
103 +```bash
120 120  curl -X POST \
121 - https:~/~/stage-evc.payex.com/payment-api/api/payments/payment-account/balance \
105 + https://stage-evc.payex.com/payment-api/api/payments/payment-account/balance \
122 122   -H 'Accept: */*' \
123 123   -H 'Agreement-Merchant-Id: XXX' \
124 124   -H 'Authorization: Bearer XXX' \
... ... @@ -133,13 +133,13 @@
133 133   "instrument": "GC"
134 134   }
135 135  }'
136 -```##
120 +```
137 137  
138 -##In this example `USER` is user and `SECRET` is secret. ##
122 +In this example `USER` is user and `SECRET` is secret.
139 139  
140 -##The plain string to `digest` would then be:##
124 +The plain string to `digest` would then be:
141 141  
142 -##```text
126 +```text
143 143  POST
144 144  /payment-api/api/payments/payment-account/balance
145 145  user
... ... @@ -153,45 +153,45 @@
153 153   "instrument": "CC"
154 154   }
155 155  }
156 -```##
140 +```
157 157  
158 -##The plain `digest` string is then hashed with `HmacSHA512` algorithm and the `SECRET`. Finally we Base64 encode the hashed value. This is the final `digest` to be provided in the `Hmac` header.##
142 +The plain `digest` string is then hashed with `HmacSHA512` algorithm and the `SECRET`. Finally we Base64 encode the hashed value. This is the final `digest` to be provided in the `Hmac` header.
159 159  
160 -##Final `Hmac` header value: ##
144 +Final `Hmac` header value:
161 161  
162 -##```text
146 +```text
163 163  HmacSHA512 user:21a0213e-30eb-85ab-b355-a310d31af30e:oY5Q5Rf1anCz7DRm3GyWR0dvJDnhl/psylfnNCn6FA0NOrQS3L0fvyUsQ1IQ9gQPeLUt9J3IM2zwoSfZpDgRJA==
164 -```##
148 +```
165 165  
166 -##~#~#~#~# Postman example script##
150 +#### Postman example script
167 167  
168 -##In pre-request script copy/paste the following snippet:##
152 +In pre-request script copy/paste the following snippet:
169 169  
170 -##```javascript##
154 +```javascript
171 171  
172 -##var user = 'user';
156 +var user = 'user';
173 173  var secret = 'secret';
174 174  var transmissionTime = (new Date()).toISOString();
175 -var sessionId = guid();##
159 +var sessionId = guid();
176 176  
177 -##var hmac = generateHMAC(user, secret, transmissionTime);
178 -console.log('hmac: ' + hmac);##
161 +var hmac = generateHMAC(user, secret, transmissionTime);
162 +console.log('hmac: ' + hmac);
179 179  
180 -##~/~/Set header values
164 +//Set header values
181 181  pm.request.headers.add({key: 'Hmac', value: hmac });
182 182  pm.request.headers.add({key: 'Transmission-Time', value: transmissionTime });
183 -pm.request.headers.add({key: 'Session-Id', value: sessionId });##
167 +pm.request.headers.add({key: 'Session-Id', value: sessionId });
184 184  
185 -##function generateHMAC(user, secret, transmissionTime) {##
169 +function generateHMAC(user, secret, transmissionTime) {
186 186  
187 -## var algorithm = "HmacSHA512";
171 + var algorithm = "HmacSHA512";
188 188   var separator = ":";
189 189   var method = request.method.toUpperCase();
190 - var nonce = generateNonce(); ~/~/UUID
174 + var nonce = generateNonce(); //UUID
191 191   var date = transmissionTime;
192 -
193 - var uri_path = replaceRequestEnv(request.url.trim()).trim().replace(new RegExp('^https?:~/~/[^/]+/'), '/'); ~/~/ strip hostname
194 - uri_path = uri_path.split("?")[0]; ~/~/Remove query paramters
176 +
177 + var uri_path = replaceRequestEnv(request.url.trim()).trim().replace(new RegExp('^https?://[^/]+/'), '/'); // strip hostname
178 + uri_path = uri_path.split("?")[0]; //Remove query paramters
195 195   var payload = _.isEmpty(request.data) ? "" : request.data;
196 196   var macData = method + '\n'
197 197   + uri_path + '\n'
... ... @@ -198,92 +198,91 @@
198 198   + user + '\n'
199 199   + nonce + '\n'
200 200   + date + '\n'
201 - + payload + '\n';##
185 + + payload + '\n';
202 202  
203 -## macData = replaceRequestEnv(macData);
204 - console.log('data to mac: ' + macData);##
187 + macData = replaceRequestEnv(macData);
188 + console.log('data to mac: ' + macData);
205 205  
206 -## var hash = CryptoJS.HmacSHA512(macData, secret);
190 + var hash = CryptoJS.HmacSHA512(macData, secret);
207 207   var digest = CryptoJS.enc.Base64.stringify(hash);
208 208   return algorithm + " " + user + separator + nonce + separator + digest;
209 -}##
193 +}
210 210  
211 -##function replaceRequestEnv(input) { ~/~/manually set environments to they are populated before hashing
212 - return input.replace(/~{~{([^)]+)}}/g, function (str, key) {
195 +function replaceRequestEnv(input) { //manually set environments to they are populated before hashing
196 + return input.replace(/{{([^)]+)}}/g, function (str, key) {
213 213   var value = pm.environment.get(key);
214 214   return value === null ? pm.varables.get(key) : value;
215 215   });
216 -}##
200 +}
217 217  
218 -##function generateNonce() {
202 +function generateNonce() {
219 219   return guid();
220 -}##
204 +}
221 221  
222 -##function guid() {
206 +function guid() {
223 223   function s4() {
224 224   return Math.floor((1 + Math.random()) * 0x10000)
225 225   .toString(16)
226 226   .substring(1);
227 - }##
211 + }
228 228  
229 -## return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
213 + return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
230 230   s4() + '-' + s4() + s4() + s4();
231 -}##
215 +}
232 232  
233 -##```
234 -</details>##
217 +```
218 +</details>
235 235  
236 -##~#~## Security documentation##
220 +### Security documentation
237 237  
238 -##~-~--##
222 +---
239 239  
240 -##* [OAuth2](https:~/~/oauth.net/2/)
241 -~* [Client Credentials](https:~/~/www.oauth.com/oauth2-servers/access-tokens/client-credentials/)
242 -~* [The RESTful CookBook: HMAC](http:~/~/restcookbook.com/Basics/loggingin/)
243 -~* [HMAC - Wikipedia](https:~/~/en.wikipedia.org/wiki/HMAC)##
224 +* [OAuth2](https://oauth.net/2/)
225 +* [Client Credentials](https://www.oauth.com/oauth2-servers/access-tokens/client-credentials/)
226 +* [The RESTful CookBook: HMAC](http://restcookbook.com/Basics/loggingin/)
227 +* [HMAC - Wikipedia](https://en.wikipedia.org/wiki/HMAC)
244 244  
245 -##~#~# First App run##
229 +## First App run
246 246  
247 -##~-~--##
231 +---
248 248  
249 -##~*~*NB! The application expects a PostgreSQL server to be running on localhost with a username `test` and password `test` to exist.~*~*
250 -~*~*This can automatically be configured if PostgreSQL server is started in docker with environment variables `POSTGRES_USER=test` and `POSTGRES_PASSWORD=test` are set (See [docker-compose.yml](https:~/~/github.com/PayEx/vas-payment-api-client/blob/master/docker-compose.yml)).~*~*##
233 +**NB! The application expects a PostgreSQL server to be running on localhost with a username `test` and password `test` to exist.**
234 +**This can automatically be configured if PostgreSQL server is started in docker with environment variables `POSTGRES_USER=test` and `POSTGRES_PASSWORD=test` are set (See [docker-compose.yml](https://github.com/PayEx/vas-payment-api-client/blob/master/docker-compose.yml)).**
251 251  
252 -##Inside the root directory, do a: ##
236 +Inside the root directory, do a:
253 253  
254 -##```bash
238 +```bash
255 255  mvn clean install
256 -```##
240 +```
257 257  
258 -##Run the Spring Boot App:##
242 +Run the Spring Boot App:
259 259  
260 -##```bash
261 -mvn ~-~-projects backend spring-boot:run
262 -```##
244 +```bash
245 +mvn --projects backend spring-boot:run
246 +```
263 263  
264 -##Now go to <http:~/~/localhost:8080/> and have a look at your new client.##
248 +Now go to <http://localhost:8080/> and have a look at your new client.
265 265  
266 -##~#~# Testing application##
250 +## Testing application
267 267  
268 -##~-~--##
252 +---
269 269  
270 -##1. Add a new card with provided details from PayEx.
271 -~1. Click on newly added Card
272 -~1. Click on "initiate payment" to create a new transaction##
254 +1. Add a new card with provided details from PayEx.
255 +1. Click on newly added Card
256 +1. Click on "initiate payment" to create a new transaction
273 273  
274 -##~#~# Build docker image~:##
258 +## Build docker image:
275 275  
276 -##~-~--##
260 +---
277 277  
278 -##```bash
279 -mvn ~-~-projects backend clean compile jib:dockerBuild
280 -```##
262 +```bash
263 +mvn --projects backend clean compile jib:dockerBuild
264 +```
281 281  
282 -##~#~# Deploy to local docker:##
266 +## Deploy to local docker:
283 283  
284 -##~-~--##
268 +---
285 285  
286 -##```bash
270 +```bash
287 287  docker-compose up -d
288 -```##
289 -
272 +```

Tips

Did you know that you can improve XWiki? Take 5 minutes to fill this survey and help this open source project!

Need help?

If you need help with XWiki you can contact: