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

You can click on the arrows next to the breadcrumb elements to quickly navigate to sibling and children pages.

Need help?

If you need help with XWiki you can contact: