# Wiki source code of PayEx Checkout v1

Last modified by Trieu Tran on 2019/12/04 14:11

#### Export

#### Office Formats

Export as PDF Export as ODT Export as RTF

#### Other Formats

Select the pages to export:

select all / none

Export as HTML
Show last authors

1 | == Introduction ==
2 |
3 | PayEx Checkout v1 is an easy way for customers to complete payments. We provide a two-phase payment method which means that an amount is initially reserved (authorized), then deducted (captured) and described in more detail when you are ready to send out the goods.
4 |
5 | == What you need before you get started ==
6 |
7 | * HTTPS enabled web server
8 | * Agreement that includes PayEx Checkout
9 | * Obtained credentials (access token) from PayEx
10 |
11 | To get a grasp of what we expect of your implementation when you are finished, we recommend that you take a peek at the following sequence diagram before you get started.
12 |
13 |
14 | {{plantuml}}
15 | @startuml
16 | skinparam sequence{
17 | ArrowColor #2DA944
18 |
19 | ActorFontColor #333333
20 | ActorFontStyle bold
21 | ActorFontSize 15
22 | ActorBackgroundColor #fefefe
23 | ActorBorderColor #2DA944
24 |
25 | LifeLineBorderColor #999999
26 | LifeLineBackgroundColor #dddddd
27 |
28 | ParticipantBorderColor #2DA944
29 | ParticipantBackgroundColor #ffffff
30 | ParticipantFontColor #333333
31 | ParticipantFontStyle bold
32 | }
33 |
34 | skinparam Roundcorner 10
35 | skinparam Shadowing false
36 |
37 | skinparam ActivityBorderColor #123123
38 |
39 | skinparam NoteBackgroundColor white
40 | skinparam NoteBorderColor #999999
41 | skinparam NoteFontColor #333333
42 |
43 | skinparam sequenceDividerBackgroundColor white
44 | skinparam sequenceDividerBorderColor #999999
45 | skinparam sequenceDividerFontStyle bold
46 | skinparam sequenceDividerFontSize 15
47 |
48 | Actor Consumer
49 | Participant "Merchant Web Page" as MerchantWebPage
50 | Participant "Merchant Web Server" as MerchantWebServer
51 | Participant PayEx
52 | '//Sequence start//'
53 |
54 | Consumer->MerchantWebPage: Open page with Checkout button
55 | Activate MerchantWebPage
56 | MerchantWebPage->MerchantWebServer: Load web page
57 | Activate MerchantWebServer
58 | ==[[https://wiki.payex.com/xwiki/wiki/developer/view/Main/ECommerce/PayEx%20Checkout/#HStep1:Createpaymentsession step 1: create payment session ]]==
59 | MerchantWebServer->PayEx: GET [[https://wiki.payex.com/xwiki/wiki/developer/view/Main/ECommerce/PayEx%20Checkout/Testdata/#HUsefulURLs <checkout baseUrl>]]
60 | Activate PayEx
61 | note left: First API request
62 | MerchantWebServer<--PayEx: Response: {paymentSessionUrl}
63 | MerchantWebServer->PayEx: POST [[https://wiki.payex.com/xwiki/wiki/developer/view/Main/ECommerce/PayEx%20Checkout/Introduction/Payment-session/ <checkout paymentSessionUrl> $accessToken]]
64 | note left: Second API request
65 | PayEx-->MerchantWebServer: {paymentSessionUrl}
66 | Deactivate PayEx
67 | MerchantWebServer->MerchantWebServer: Save {paymentSessionUrl} to local storage
68 |
69 | MerchantWebServer->MerchantWebPage: Page with Checkout config {paymentSessionUrl}
70 | Deactivate MerchantWebServer
71 | ==[[https://wiki.payex.com/xwiki/wiki/developer/view/Main/ECommerce/PayEx%20Checkout/#HStep2:Configureyourfrontend step 2: configure your frontend]]==
72 |
73 | MerchantWebPage->PayEx: GET checkout.js
74 | Activate PayEx
75 | PayEx->MerchantWebPage: Serve static JavaScript
76 | Deactivate PayEx
77 | MerchantWebPage->Consumer: Show purchase page
78 | Deactivate MerchantWebPage
79 | |||
80 | hnote over MerchantWebPage: Consumer presses Checkout button
81 |
82 | Consumer->MerchantWebPage: Checkout button clicked
83 |
84 |
85 | ==[[https://wiki.payex.com/xwiki/wiki/developer/view/Main/ECommerce/PayEx%20Checkout/#HStep3:Paymentwindow step 3: payment window]]==
86 | Activate MerchantWebPage
87 | MerchantWebPage->Consumer: Display Checkout to Consumer
88 | note right: Checkout window opens. Consumer purchase dialogue
89 | Consumer->MerchantWebPage: Enter payment data
90 | MerchantWebPage->PayEx: Payment data is sent to PayEx for authorization
91 | Activate PayEx
92 | PayEx-->MerchantWebPage: Response purchase dialog
93 | Deactivate PayEx
94 | note left: Checkout windows closes
95 | MerchantWebPage->MerchantWebServer: POST Payment <form>
96 | Deactivate MerchantWebPage
97 |
98 | Activate MerchantWebServer
99 | ==[[https://wiki.payex.com/xwiki/wiki/developer/view/Main/ECommerce/PayEx%20Checkout/#HStep4:Getpaymentstatus step 4: get payment status]]==
100 | MerchantWebServer<-MerchantWebServer: Get {paymentSessionUrl} from storage
101 |
102 | MerchantWebServer->PayEx: GET [[https://wiki.payex.com/xwiki/wiki/developer/view/Main/ECommerce/PayEx%20Checkout/Introduction/Payment-session/ <paymentSessionUrl> $merchantToken]]
103 | note left: Third API request
104 | Activate PayEx
105 | PayEx-->MerchantWebServer: Respons paymentSession Object
106 |
107 | MerchantWebServer->PayEx: GET [[https://wiki.payex.com/xwiki/wiki/developer/view/Main/ECommerce/PayEx%20Checkout/Introduction/Payment/ <paymentUrl> $merchantToken]]
108 | note left: Fourth API request
109 | MerchantWebServer<--PayEx: Response paymentStatus Object
110 | Deactivate PayEx
111 |
112 | MerchantWebServer<-MerchantWebServer: Save paymentStatusObject
113 | MerchantWebServer->MerchantWebPage:Receipt page
114 | Deactivate MerchantWebPage
115 | Deactivate MerchantWebServer
116 |
117 | |||
118 | hnote over MerchantWebServer: Awaiting order fullfilment
119 | |||
120 |
121 | ==[[https://wiki.payex.com/xwiki/wiki/developer/view/Main/ECommerce/PayEx%20Checkout/#HStep5:Capturethepayment step 5: capture the payment]]==
122 |
123 | MerchantWebServer->MerchantWebServer: Complete order
124 | Activate MerchantWebServer
125 | MerchantWebServer->PayEx: POST [[https://wiki.payex.com/xwiki/wiki/developer/view/Main/ECommerce/PayEx%20Checkout/Introduction/Payment/#HCapture <CaptureUrl> $merchantToken]]
126 | Activate PayEx
127 | note left: Fifth API request
128 | PayEx-->MerchantWebServer: Capture response
129 | Deactivate PayEx
130 | MerchantWebServer->MerchantWebServer: Ship goods
131 | MerchantWebServer->Consumer: Consumer recieves goods
132 | Deactivate MerchantWebServer
133 | '//Sequence end//'
134 | @enduml
135 | {{/plantuml}}
136 |
137 |
138 |
139 | == What you should do, step by step ==
140 |
141 | Below is an example implementation provided in C# 6, .NET 4.5.1+ and Newtonsoft.Json for the backend code. The frontend naturally uses HTML5 and JavaScript. To view backend examples of the raw HTTP request and response messages, please have a look at the [[Backend API documentation>>doc:Sandbox.payex-checkout-v1.Introduction.WebHome]].
142 |
143 | Note that the examples are written for a "happy path" implementation and thus contain no error handling of any kind. The examples are therefore not production ready code to be used in an actual application, they are just provided to help understanding the API and give the implementation a head start.
144 |
145 | Test data is located in the [[Test Data section>>doc:Sandbox.payex-checkout-v1.Testdata.WebHome]]. If you encounter any problem with the implementation, please visit the troubleshooting section or [[send us an e-mail>>mailto:support.ecom@payex.com]].
146 |
147 | === Step 1: Create payment session ===
148 |
149 | Create a payment session by doing a HTTP POST from your webserver with payment info and your merchant token. The response from the POST will contain a Payment Session URL that you will need later. Save this value for future use (frontend config and operations on the payment) related to the order/shoppingcart in your database.
150 |
151 | {{tabs idsToLabels="HTTP=HTTP, CS=C#"/}}
152 |
153 | (% id="HTTP" %)
154 | (((
155 | Retrieve the Home resource and locate the Payment Session base URL
156 |
157 | **Request**
158 |
159 | {{code language="JavaScript"}}
160 | GET https://api.payex.com/psp/checkout/ HTTP/1.1
161 | Accept: application/json
162 | Authorization: Bearer merchantToken==
163 | {{/code}}
164 |
165 | **Response**
166 |
167 | {{code language="JavaScript"}}
168 | HTTP/1.1 200 OK
169 | Content-Type: application/json
170 |
171 | {
172 | "paymentSession": "<payment_session_url>"
173 | }
174 | {{/code}}
175 |
176 | Perform the POST request to the Payment Session base URL to create a Payment Session
177 |
178 | **Request**
179 |
180 | {{code language="JavaScript"}}
181 | POST https://api.payex.com/psp/checkout/payment-sessions/ HTTP/1.1
182 | Content-Type: application/json
183 | Authorization: Bearer merchantToken==
184 |
185 | {
186 | "amount": 199.50,
187 | "vatAmount": 39.90,
188 | "currency": "NOK",
189 | "callbackUrl": "https://merchant.api/callback",
190 | "reference": "merchant-order-123",
191 | "acquire": ["email", "mobilePhoneNumber", "shippingAddress"],
192 | "culture": "nb-NO",
193 | "hosts": ["https://merchant.com/"],
194 | "payer": {
195 | "email": "payer@example.com",
196 | "mobilePhoneNumber": "+4712345678"
197 | },
198 | "fees" : {
199 | "invoice": {
200 | "amount": 19.50,
201 | "vatAmount": 3.90,
202 | "description": "Invoice fee"
203 | }
204 | }
205 | }
206 |
207 | {{/code}}
208 |
209 | **Response**
210 |
211 | {{code language="JavaScript"}}
212 | HTTP/1.1 201 Created
213 | Content-Type: application/json
214 | Location: https://api.payex.com/psp/checkout/payment-sessions/123-456-789
215 |
216 | {
217 | "id": "https://api.payex.com/psp/checkout/payment-sessions/123-456-789",
218 | "amount": 199.50,
219 | "vatAmount": 39.90,
220 | "currency": "NOK",
221 | "callbackUrl": "https://merchant.api/callback",
222 | "reference": "merchant-order-123",
223 | "acquire": ["email", "mobilePhoneNumber", "shippingAddress"],
224 | "culture": "nb-NO",
225 | "hosts": ["https://merchant.com/"],
226 | "payer": {
227 | "email": "payer@example.com",
228 | "mobilePhoneNumber": "+4712345678"
229 | },
230 | "fees" : {
231 | "invoice": {
232 | "amount": 19.50,
233 | "vatAmount": 3.90,
234 | "description": "Invoice fee"
235 | }
236 | }
237 | }
238 | {{/code}}
239 |
240 | Find the URL of the created Payment Session in the HTTP 'Location' header and store it alongside the order, shopping cart, or similar
241 | )))
242 |
243 | (% id="CS" %)
244 | (((
245 | {{code language="c#"}}
246 | var merchantToken = "<secret merchant token>";
247 | var httpClient = new HttpClient();
248 | httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + merchantToken);
249 |
250 | // 1. Retrieve the Home resource and locate the Payment Session base URL.
251 | var homeResponse = await httpClient.GetAsync("https://api.payex.com/psp/checkout");
252 | var homeContent = await homeResponse.Content.ReadAsStringAsync();
253 | var home = Newtonsoft.Json.Linq.JObject.Parse(homeContent);
254 | var paymentSessionBaseUrl = home["paymentSession"].ToString();
255 |
256 | // 2. Perform the POST request to the Payment Session base URL to create a Payment Session
257 | var json = Newtonsoft.Json.JsonConvert.SerializeObject(new
258 | {
259 | amount = 100.00,
260 | vatAmount = 20.00,
261 | currency = "NOK",
262 | callbackUrl = "https://merchant.api/callback",
263 | reference = "merchant-order-123",
264 | acquire = new[] { "shippingAddress" },
265 | culture = "nb-NO"
266 | });
267 | var paymentSessionContent = new StringContent(json, Encoding.UTF8, "application/json");
268 | var paymentSessionResponse = await httpClient.PostAsync(paymentSessionBaseUrl, paymentSessionContent);
269 |
270 | // 3. Find the URL of the created Payment Session in the HTTP 'Location' header and store it alongside the order, shopping cart, or similar.
271 | var paymentSessionUrl = paymentSessionResponse.Headers.Location;
272 | {{/code}}
273 |
274 | After the above code is executed, the {{code}}paymentSessionUrl{{/code}} variable will contain the URL to a Payment Session that contains the payment data used to guide the user through the PayEx Checkout user flow. **Remember to persist the {{code}}paymentSessionUrl{{/code}} to storage** related to the order, shopping cart or similar represented by the {{code}}reference{{/code}} above.
275 | )))
276 |
277 | ----
278 |
279 | Your can read more about the payment session object [[here>>Sandbox.payex-checkout-v1.Introduction.Payment-session.WebHome]].
280 |
281 | === Step 2: Configure your frontend ===
282 |
283 | PayEx Checkout uses a script that bootstraps the payment process when your purchase button is clicked. Add the PayEx Checkout script to your page:
284 |
285 | {{code language="html"}}
286 | <script src="https://checkout.externalintegration.payex.com/js/payex-checkout.min.js"></script>
287 | {{/code}}
288 |
289 | Please note that the above URL points to **PayEx Checkout's test environment**. For the URL to PayEx' production environment, [[please refer to the general API introduction>>doc:Main.ecommerce.technical-reference.card-payments.WebHome]].
290 |
291 | Choose the button that you want to start the checkout process with and add the attribute data-payex-checkout with the value returned from return in the initial POST. Then add the disable attribute - the PayEx Checkout JavaScript will enable it when it is properly loaded. The button should be wrapped inside a form that POST to your server.
292 |
293 | {{code language="html"}}
294 | <form action="<url_to_your_server>" method="post">
295 | <!-- ... -->
296 | <button data-payex-checkout="<payment_session_url>" disabled>Pay</button>
297 | </form>
298 | {{/code}}
299 |
300 | The PayEx Checkout script will post the form when the payment process is complete.
301 |
302 | You can read more about how to implement PayEx Checkout in your frontend [[here>>Sandbox.payex-checkout-v1.Frontend API.WebHome]].
303 |
304 | === Step 3: Payment window (facilitated by PayEx) ===
305 |
306 | When a consumer clicks on the Pay button the PayEx Checkout payment window appears in the web browser. This payment window includes the following steps.
307 |
308 | ==== Login ====
309 |
310 | PayEx holds all payer information for easier payment procedure. If the user submits an email address a lookup process begins.
311 | Otherwise an anonymous payment process is used where only credit card is available as payment method.
312 |
313 | ==== Authentication ====
314 |
315 | By specifying mobile phone number, a verification code is sent to your phone.
316 |
317 | ==== Delivery ====
318 |
319 | Depending on the parameters provided in the acquires property, various address information is required to continue to next step.
320 |
321 | ==== Payment ====
322 |
323 | Depending on merchant country, merchant contract and consumer country a list of payment options is displayed.
324 | Possible options are currently credit card and invoice.
325 | Credit card offers the option to add a new card or pick a previous card.
326 | Invoice is only available for consumers in same country as merchant.
327 |
328 | Once the payment is authorized at our end - the PayEx Checkout Javascript will post the form.
329 | From the payment window is opened until it closes, everything in the payment process is performed entirely by PayEx. After that we expect a receipt to be sent to the consumer.
330 |
331 | === Step 4: Get payment status ===
332 |
333 | After a successfully authorized payment, the purchase form will be submitted as earlier mentioned. It is assumed that the form contains the reference connecting the previously persisted {{code}}paymentSessionUrl{{/code}} to the order, shopping cart, or similar.
334 |
335 | When the form is submitted, look up the {{code}}paymentSesionUrl{{/code}} and perform a {{code}}GET{{/code}} request on it to retrieve the status of the payment. The returned JSON will also contain the necessary URLs to perform actions on the payment such as capture, cancel and reversal.
336 |
337 | {{tabs idsToLabels="HTTP_2=HTTP, C_2=C#"/}}
338 |
339 | (% id="HTTP_2" %)
340 | (((
341 | Retrieve the ##paymentSessionUrl## related to the submitted form from storage, and then retrieve the Payment Session and find the URL of the Payment.
342 |
343 | **Request**
344 |
345 | {{code language="JavaScript"}}
346 | GET https://api.payex.com/psp/checkout/payment-sessions/123-456-789 HTTP/1.1
347 | Accept: application/json
348 | Authorization: Bearer merchantToken==
349 | {{/code}}
350 |
351 | **Response**
352 |
353 | {{code language="JavaScript"}}
354 | HTTP/1.1 200 OK
355 | Content-Type: application/json
356 |
357 | {
358 | "amount": 199.50,
359 | "vatAmount": 39.90,
360 | "currency": "NOK",
361 | "callbackUrl": "https://merchant.api/callback",
362 | "reference": "merchant-order-123",
363 | "acquire": ["email", "mobilePhoneNumber", "shippingAddress"],
364 | "culture": "nb-NO",
365 | "addressee": {
366 | "name": "Olivia Nyhuus",
367 | "email": "olivia.nyhuus@example.com",
368 | "mobilePhoneNumber": "004791234567",
369 | "shippingAddress": {
370 | "city": "Oslo",
371 | "countryCode": "NO",
372 | "streetAddress": "Stålverkskroken, 4",
373 | "zipCode": "0661"
374 | }
375 | },
376 | "payment": "https://api.payex.com/psp/payment/credit-card/984-223-836",
377 | }
378 | {{/code}}
379 |
380 | Retrieve the Payment and inspect its state.
381 |
382 | **Request**
383 |
384 | {{code language="JavaScript"}}
385 | GET <payment_url> HTTP/1.1
386 | Content-Type: application/json
387 | Authorization: Bearer merchantToken==
388 | {{/code}}
389 |
390 | **Response**
391 |
392 | {{code language="JavaScript"}}
393 | {
394 | "payment": {
395 | "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c",
396 | "number": 1234567890,
397 | "created": "2016-09-14T13:21:29.3182115Z",
398 | "updated": "2016-09-14T13:21:57.6627579Z",
399 | "operation": "Purchase|Verify|Recur",
400 | "intent": "Authorization|AutoCapture",
401 | "state": "Ready|Pending|Failed|Aborted",
402 | "currency": "NOK|SEK|...",
403 | "amount": 1500,
404 | "remainingCaptureAmount": 1500,
405 | "remainingCancellationAmount": 1500,
406 | "remainingReversalAmount": 0,
407 | "description": "Test Purchase",
408 | "initiatingSystemUserAgent": "PostmanRuntime/3.0.1",
409 | "userAgent": "Mozilla/5.0...",
410 | "language": "nb-NO",
411 | "paymentToken": "5adc265f-f87f-4313-577e-08d3dca1a26c",
412 | "prices": {
413 | "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/prices"
414 | },
415 | "transactions": {
416 | "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/transactions"
417 | },
418 | "authorizations": {
419 | "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/authorizations"
420 | },
421 | "captures": {
422 | "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/captures"
423 | },
424 | "cancellations": {
425 | "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/cancellations"
426 | },
427 | "reversals": {
428 | "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/reversals"
429 | },
430 | "payeeInfo": {
431 | "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/payeeInfo"
432 | },
433 | "urls": {
434 | "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/urls"
435 | },
436 | "settings": {
437 | "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/settings"
438 | }
439 | },
440 | "operations": [
441 | {
442 | "href": "<capture_operation_url>",
443 | "rel": "create-checkout-capture",
444 | "method": "POST"
445 | },
446 | {
447 | "href": "<cancellation_operation_url>",
448 | "rel": "create-checkout-cancellation",
449 | "method": "POST"
450 | },
451 | {
452 | "href": "<reversal_operation_url>",
453 | "rel": "create-checkout-reversal",
454 | "method": "POST"
455 | }
456 | ]
457 | }
458 | {{/code}}
459 | )))
460 |
461 | (% id="C_2" %)
462 | (((
463 | ===== Implementation example =====
464 |
465 | {{code language="c#"}}
466 | var merchantToken = "<secret merchant token>";
467 | var httpClient = new HttpClient();
468 | httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + merchantToken);
469 |
470 | // 1. Retrieve the paymentSessionUrl related to the submitted form from storage.
471 | var paymentSessionUrl = "<retrieved from storage>";
472 |
473 | // 2. Retrieve the Payment Session and find the URL of the Payment.
474 | var paymentSessionResponse = await httpClient.GetAsync(paymentSessionUrl);
475 | var paymentSessionContent = await paymentSessionResponse.Content.ReadAsStringAsync();
476 | var paymentSession = Newtonsoft.Json.Linq.JObject.Parse(paymentSessionContent);
477 | var paymentUrl = paymentSession["payment"].ToString();
478 |
479 | // 3. Retrieve the Payment and inspect its state.
480 | var paymentResponse = await httpClient.GetAsync(paymentUrl);
481 | var paymentContent = await paymentResponse.Content.ReadAsStringAsync();
482 | var payment = Newtonsoft.Json.Linq.JObject.Parse(paymentContent);
483 | var paymentState = payment["state"].ToString();
484 | {{/code}}
485 |
486 | After the above code example is executed, the {{code}}paymentState{{/code}} variable will contain the value {{code}}Ready{{/code}}, {{code}}Pending{{/code}}, {{code}}Failed{{/code}} or {{code}}Aborted{{/code}}. Use it to provide a message to the user in the form of a receipt, an error message in the event of failure, etc.
487 | )))
488 |
489 | ----
490 |
491 | In a normal flow the paymentState will be {{code}}Ready{{/code}} and it is now expected that an order confirmation is presented to the consumer in your webshop and that you ship the confirmation per email.
492 |
493 | Read more about the payment session [[here>>Sandbox.payex-checkout-v1.Introduction.Payment-session.WebHome||anchor="HRetrievePaymentSession"]].
494 |
495 | == Step 5: Capture the payment ==
496 |
497 | {{tabs idsToLabels="HTTP_3=HTTP, C_3=C#"/}}
498 |
499 | Capture can be done at any time, depending on whether you want to physically send the purchased goods to the customer first, for instance. Just repeat the {{code}}GET{{/code}} request to the {{code}}paymentSessionUrl{{/code}}, find the {{code}}capture{{/code}} operation and execute it. We now expect an order confirmation to be sent to the consumer.
500 |
501 |
502 | (% id="HTTP_3" %)
503 | (((
504 | Retrieve the {{code}}paymentSessionUrl{{/code}} related to the submitted form from storage, and then retrieve the Payment Session and find the URL of the Payment.
505 |
506 | **Request**
507 |
508 | {{code language="JavaScript"}}
509 | GET https://api.payex.com/psp/checkout/payment-sessions/123-456-789 HTTP/1.1
510 | Accept: application/json
511 | Authorization: Bearer merchantToken==
512 | {{/code}}
513 |
514 | **Response**
515 |
516 | {{code language="JavaScript"}}
517 | HTTP/1.1 200 OK
518 | Content-Type: application/json
519 |
520 | {
521 | "amount": 199.50,
522 | "vatAmount": 39.90,
523 | "currency": "NOK",
524 | "callbackUrl": "https://merchant.api/callback",
525 | "reference": "merchant-order-123",
526 | "acquire": ["email", "mobilePhoneNumber", "shippingAddress"],
527 | "culture": "nb-NO",
528 | "addressee": {
529 | "name": "Olivia Nyhuus",
530 | "email": "olivia.nyhuus@example.com",
531 | "mobilePhoneNumber": "004791234567",
532 | "shippingAddress": {
533 | "city": "Oslo",
534 | "countryCode": "NO",
535 | "streetAddress": "Stålverkskroken, 4",
536 | "zipCode": "0661"
537 | }
538 | },
539 | "payment": "https://api.payex.com/psp/payment/credit-card/984-223-836"
540 | }
541 | {{/code}}
542 |
543 | Retrieve the Payment and find its {{code}}create-checkout-capture{{/code}} operation:
544 |
545 | **Request**
546 |
547 | {{code language="JavaScript"}}
548 | GET <payment_url> HTTP/1.1
549 | Content-Type: application/json
550 | Authorization: Bearer merchantToken==
551 | {{/code}}
552 |
553 | **Response**
554 |
555 | {{code language="JavaScript"}}
556 | {
557 | "payment": {
558 | "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c",
559 | "number": 1234567890,
560 | "created": "2016-09-14T13:21:29.3182115Z",
561 | "updated": "2016-09-14T13:21:57.6627579Z",
562 | "operation": "Purchase|Verify|Recur",
563 | "intent": "Authorization|AutoCapture",
564 | "state": "Ready|Pending|Failed|Aborted",
565 | "currency": "NOK|SEK|...",
566 | "amount": 1500,
567 | "remainingCaptureAmount": 1500,
568 | "remainingCancellationAmount": 1500,
569 | "remainingReversalAmount": 0,
570 | "description": "Test Purchase",
571 | "initiatingSystemUserAgent": "PostmanRuntime/3.0.1",
572 | "userAgent": "Mozilla/5.0...",
573 | "language": "nb-NO",
574 | "paymentToken": "5adc265f-f87f-4313-577e-08d3dca1a26c",
575 | "prices": {
576 | "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/prices"
577 | },
578 | "transactions": {
579 | "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/transactions"
580 | },
581 | "authorizations": {
582 | "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/authorizations"
583 | },
584 | "captures": {
585 | "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/captures"
586 | },
587 | "cancellations": {
588 | "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/cancellations"
589 | },
590 | "reversals": {
591 | "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/reversals"
592 | },
593 | "payeeInfo": {
594 | "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/payeeInfo"
595 | },
596 | "urls": {
597 | "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/urls"
598 | },
599 | "settings": {
600 | "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/settings"
601 | }
602 | },
603 | "operations": [
604 | {
605 | "href": "<capture_operation_url>",
606 | "rel": "create-checkout-capture",
607 | "method": "POST"
608 | },
609 | {
610 | "href": "<cancellation_operation_url>",
611 | "rel": "create-checkout-cancellation",
612 | "method": "POST"
613 | },
614 | {
615 | "href": "<reversal_operation_url>",
616 | "rel": "create-checkout-reversal",
617 | "method": "POST"
618 | }
619 | ]
620 | }
621 | {{/code}}
622 |
623 | Perform the capture request:
624 |
625 | **Request**
626 |
627 | {{code language="JavaScript"}}
628 | POST <capture_operation_href> HTTP/1.1
629 | Accept: application/json
630 | Content-Type: application/json
631 | Authorization: Bearer merchantToken==
632 |
633 | {
634 | "transaction": {
635 | "description": "description for the transaction"
636 | }
637 | }
638 | {{/code}}
639 |
640 | **Response**
641 |
642 | {{code language="JavaScript"}}
643 | {
644 | "payment": "<paymentUrl>",
645 | "capture": {
646 | "id": "<paymentCaptureUrl>",
647 | "transaction": {
648 | "id": "<transactionUrl>",
649 | "created": "2016-09-14T01:01:01.01Z",
650 | "updated": "2016-09-14T01:01:01.03Z",
651 | "type": "Capture",
652 | "state": "Initialized|Completed|Failed",
653 | "number": 1234567890,
654 | "amount": 1500,
655 | "vatAmount": 300,
656 | "description": "Test Capture",
657 | "payeeReference": "ABC123",
658 | "failedReason": "",
659 | "isOperational": "TRUE|FALSE",
660 | "operations": []
661 | }
662 | }
663 | }
664 | {{/code}}
665 |
666 | As the {{code}}state{{/code}} property in the response above will indicate, the capture operation should now be {{code}}Completed{{/code}}, indicating that the payment is captured.
667 | )))
668 |
669 | (% id="C_3" %)
670 | (((
671 | Implementation example
672 |
673 | {{code language="c#"}}
674 | var merchantToken = "<secret merchant token>";
675 | var httpClient = new HttpClient();
676 | httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + merchantToken);
677 |
678 | // 1. Retrieve the paymentSessionUrl related to the submitted form from storage.
679 | var paymentSessionUrl = "<retrieved from storage>";
680 |
681 | // 2. Retrieve the Payment Session and find the URL of the Payment.
682 | var paymentSessionResponse = await httpClient.GetAsync(paymentSessionUrl);
683 | var paymentSessionContent = await paymentSessionResponse.Content.ReadAsStringAsync();
684 | var paymentSession = Newtonsoft.Json.Linq.JObject.Parse(paymentSessionContent);
685 | var paymentUrl = paymentSession["payment"].ToString();
686 |
687 | // 3. Retrieve the Payment and find its 'create-checkout-capture' operation.
688 | var paymentResponse = await httpClient.GetAsync(paymentUrl);
689 | var paymentContent = await paymentResponse.Content.ReadAsStringAsync();
690 | var payment = Newtonsoft.Json.Linq.JObject.Parse(paymentContent);
691 | var captureUrl = payment["operations"]
692 | .Children()
693 | .First(x => x["rel"].ToString() == "create-checkout-capture")["href"]
694 | .ToString();
695 |
696 | // 4. Perform the capture request.
697 | var json = Newtonsoft.Json.JsonConvert.SerializeObject(new
698 | {
699 | transaction = new
700 | {
701 | description = "Captured the payment"
702 | }
703 | });
704 | var captureRequestContent = new StringContent(json, Encoding.UTF8, "application/json");
705 | var captureResponse = await httpClient.PostAsync(captureUrl, captureRequestContent);
706 | var captureResponseContent = await captureResponse.Content.ReadAsStringAsync();
707 | var capture = Newtonsoft.Json.Linq.JObject.Parse(captureResponseContent);
708 | {{/code}}
709 |
710 | When the above code example is executed, the {{code}}capture{{/code}} variable will be a JSON object containing the result of the capture operation. It is now excepted that an order receipt is sent per email to the consumer.
711 |
712 | The above example performs a complete capture of the authorized amount. If you want to perform a more detailed captured, read more about the capture operation [[here.>>Sandbox.payex-checkout-v1.Introduction.Payment.WebHome||anchor="HCapture"]]
713 | )))

# Applications

# Tips

If you're starting with XWiki, check out the Getting Started Guide.

# Need help?

If you need help with XWiki you can contact:

- Community Support
- Professional Support