Changes for page PayEx Checkout v1
Last modified by Trieu Tran on 2019/12/04 14:11
From version 13.1
edited by Helge Dahl
on 2018/01/23 15:12
on 2018/01/23 15:12
To version 14.1
edited by HÄkon Mosvoll
on 2018/01/25 10:44
on 2018/01/25 10:44
Change comment: There is no comment for this version
Summary
-
Page properties (2 modified, 0 added, 0 removed)
Details
- Page properties
-
- Author
-
... ... @@ -1,1 +1,1 @@ 1 -xwiki:XWiki.h de1 +xwiki:XWiki.hnm - Content
-
... ... @@ -1,8 +1,683 @@ 1 -(% style="background-color:#A0A3A1;color:#ffffff;align=center" %) 2 -|This tencnical documentation targets technical system integrators and developers implementing PayEx Checkout.((( 3 -For technical questions, please contact [[(% style="color:#ffffff" %)PayEx Technical Support>>mailto:support.ecom@payex,com]] 1 += Introduction = 4 4 3 +PayEx Checkout 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. 5 5 5 += What you need before you get started = 6 6 7 -=== (% style="color:#ffffff" %)**Get started by jumping to the [[Introduction>>doc:Main.ECommerce.PayEx Checkout.Introduction.WebHome||title="Introduction to PayEx Checkout"]] >>**(%%) === 8 -)))|[[image:segment_checkout_w300.png]] 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://developer.payex.com/xwiki/wiki/external/view/ecommerce/PayEx%20Checkout/Implementation/#HStep1:createpaymentsession step 1: create payment session ]]== 59 +MerchantWebServer->PayEx: GET [[https://wiki.payex.com/xwiki/wiki/external/view/ecommerce/PayEx%20Checkout/Home/ <checkout baseUrl>]] 60 +Activate PayEx 61 +note left: First API request 62 +MerchantWebServer<--PayEx: Response: {paymentSessionUrl} 63 +MerchantWebServer->PayEx: POST [[https://developer.payex.com/xwiki/wiki/external/view/ecommerce/PayEx%20Checkout/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://developer.payex.com/xwiki/wiki/external/view/ecommerce/PayEx%20Checkout/Implementation/#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://developer.payex.com/xwiki/wiki/external/view/ecommerce/PayEx%20Checkout/Implementation/#HStep3:paymentwindow28facilitatedbyPayEx29 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://developer.payex.com/xwiki/wiki/external/view/ecommerce/PayEx%20Checkout/Implementation/#HStep4:getpaymentstatus step 4: get payment status]]== 100 +MerchantWebServer<-MerchantWebServer: Get {paymentSessionUrl} from storage 101 + 102 +MerchantWebServer->PayEx: GET [[https://developer.payex.com/xwiki/wiki/external/view/ecommerce/PayEx%20Checkout/Payment-session/#HRetrievePaymentSession <paymentSessionUrl> $merchantToken]] 103 +note left: Third API request 104 +Activate PayEx 105 +PayEx-->MerchantWebServer: Respons paymentSession Object 106 + 107 +MerchantWebServer->PayEx: GET [[https://developer.payex.com/xwiki/wiki/external/view/ecommerce/PayEx%20Checkout/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://developer.payex.com/xwiki/wiki/external/view/ecommerce/PayEx%20Checkout/Implementation/#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/external/view/ecommerce/PayEx%20Checkout/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 +=== Implementation example === 142 + 143 +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:Main.ECommerce.PayEx Checkout.Introduction.WebHome]]. 144 + 145 +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. 146 + 147 +Testdata is located in the [[Test Data section>>doc:Main.ECommerce.PayEx Checkout.Testdata.WebHome]]. If you encounter any problem with the implementation, please visit the troubleshooting section or ask us on [[Gitter>>https://gitter.im/PayEx/PayEx.Checkout.Documentation]]. 148 + 149 +== Step 1: Create payment session == 150 + 151 +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. 152 + 153 +{{tabs idsToLabels="HTTP=HTTP, CS=C#"/}} 154 + 155 +(% id="HTTP" %) 156 +((( 157 +Retrieve the Home resource and locate the Payment Session base URL 158 + 159 +**Request** 160 + 161 +{{code language="JavaScript"}} 162 +GET https://api.payex.com/psp/checkout/ HTTP/1.1 163 +Accept: application/json 164 +Authorization: Bearer merchantToken== 165 +{{/code}} 166 + 167 +**Response** 168 + 169 +{{code language="JavaScript"}} 170 +HTTP/1.1 200 OK 171 +Content-Type: application/json 172 + 173 +{ 174 + "paymentSession": "<payment_session_url>" 175 +} 176 +{{/code}} 177 + 178 +Perform the POST request to the Payment Session base URL to create a Payment Session 179 + 180 +**Request** 181 + 182 +{{code language="JavaScript"}} 183 +POST https://api.payex.com/psp/checkout/payment-sessions/ HTTP/1.1 184 +Content-Type: application/json 185 +Authorization: Bearer merchantToken== 186 + 187 +{ 188 + "amount": 199.50, 189 + "vatAmount": 39.90, 190 + "currency": "NOK", 191 + "callbackUrl": "https://merchant.api/callback", 192 + "reference": "merchant-order-123", 193 + "acquire": ["email", "mobilePhoneNumber", "shippingAddress"], 194 + "culture": "nb-NO", 195 + "payer": { 196 + "email": "payer@example.com", 197 + "mobilePhoneNumber": "+4712345678" 198 + }, 199 + "fees" : { 200 + "invoice": { 201 + "amount": 19.50, 202 + "vatAmount": 3.90, 203 + "description": "Invoice fee" 204 + } 205 + } 206 +} 207 + 208 +{{/code}} 209 + 210 +**Response** 211 + 212 +{{code language="JavaScript"}} 213 +HTTP/1.1 201 Created 214 +Content-Type: application/json 215 +Location: https://api.payex.com/psp/checkout/payment-sessions/123-456-789 216 + 217 +{ 218 + "id": "https://api.payex.com/psp/checkout/payment-sessions/123-456-789", 219 + "payment": "<payment_url>" 220 +} 221 +{{/code}} 222 + 223 +Find the URL of the created Payment Session in the HTTP 'Location' header and store it alongside the order, shopping cart, or similar 224 +))) 225 + 226 +(% id="CS" %) 227 +((( 228 +==== Implementation example ==== 229 + 230 +{{code language="c#"}} 231 +var merchantToken = "<secret merchant token>"; 232 +var httpClient = new HttpClient(); 233 +httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + merchantToken); 234 + 235 +// 1. Retrieve the Home resource and locate the Payment Session base URL. 236 +var homeResponse = await httpClient.GetAsync("https://api.payex.com/psp/checkout"); 237 +var homeContent = await homeResponse.Content.ReadAsStringAsync(); 238 +var home = Newtonsoft.Json.Linq.JObject.Parse(homeContent); 239 +var paymentSessionBaseUrl = home["paymentSession"].ToString(); 240 + 241 +// 2. Perform the POST request to the Payment Session base URL to create a Payment Session 242 +var json = Newtonsoft.Json.JsonConvert.SerializeObject(new 243 +{ 244 + amount = 100.00, 245 + vatAmount = 20.00, 246 + currency = "NOK", 247 + callbackUrl = "https://merchant.api/callback", 248 + reference = "merchant-order-123", 249 + acquire = new[] { "shippingAddress" }, 250 + culture = "nb-NO" 251 +}); 252 +var paymentSessionContent = new StringContent(json, Encoding.UTF8, "application/json"); 253 +var paymentSessionResponse = await httpClient.PostAsync(paymentSessionBaseUrl, paymentSessionContent); 254 + 255 +// 3. Find the URL of the created Payment Session in the HTTP 'Location' header and store it alongside the order, shopping cart, or similar. 256 +var paymentSessionUrl = paymentSessionResponse.Headers.Location; 257 +{{/code}} 258 + 259 +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. 260 +))) 261 + 262 +---- 263 + 264 +Your can read more about the payment session object [[here>>Main.ECommerce.PayEx Checkout.Introduction.Payment-session.WebHome]]. 265 + 266 +== Step 2: Configure your frontend == 267 + 268 +PayEx Checkout uses a script that bootstraps the payment process when your purchase button is clicked. Add the PayEx Checkout script to your page: 269 + 270 +{{code language="html"}} 271 +<script src="https://checkout.payex.com/js/payex-checkout.min.js"></script> 272 +{{/code}} 273 + 274 +Please note that the above URL points to **PayEx Checkout's production environment**. If you want to integrate with PayEx' test environment, [[please refer to the FAQ for the correct URLs>>doc:Main.ECommerce.PayEx Checkout.FAQ.WebHome]]. 275 + 276 +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. 277 + 278 +{{code language="html"}} 279 +<form action="<url_to_your_server>" method="post"> 280 + <!-- ... --> 281 + <button data-payex-checkout="<payment_session_url>" disabled>Pay</button> 282 +</form> 283 +{{/code}} 284 + 285 +The PayEx Checkout script will post the form when the payment process is complete. 286 + 287 +You can read more about how to implement PayEx Checkout in your frontend [[here>>Main.ECommerce.PayEx Checkout.Frontend API.WebHome]]. 288 + 289 +== Step 3: Payment window (facilitated by PayEx) == 290 + 291 +When consumer clicks on the Pay button the PayEx Checkout payment window appears in the web browser. 292 +Once the payment is authorized at our end - the PayEx Checkout Javascript will post the form. 293 + 294 +From the payment window opens until it closes is performed entirely by PayEx. We now expect a receipt to be sent to the consumer. 295 + 296 +== Step 4: Get payment status == 297 + 298 +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. 299 + 300 +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. 301 + 302 +{{tabs idsToLabels="HTTP_2=HTTP, C_2=C#"/}} 303 + 304 +(% id="HTTP_2" %) 305 +((( 306 +Retrieve the paymentSessionUrl related to the submitted form from storage, and then retrieve the Payment Session and find the URL of the Payment. 307 + 308 +**Request** 309 + 310 +{{code language="JavaScript"}} 311 +GET https://api.payex.com/psp/checkout/payment-sessions/123-456-789 HTTP/1.1 312 +Accept: application/json 313 +Authorization: Bearer merchantToken== 314 +{{/code}} 315 + 316 +**Response** 317 + 318 +{{code language="JavaScript"}} 319 +HTTP/1.1 200 OK 320 +Content-Type: application/json 321 + 322 +{ 323 + "amount": 199.50, 324 + "vatAmount": 39.90, 325 + "currency": "NOK", 326 + "callbackUrl": "https://merchant.api/callback", 327 + "reference": "merchant-order-123", 328 + "acquire": ["email", "mobilePhoneNumber", "shippingAddress"], 329 + "culture": "nb-NO", 330 + "addressee": { 331 + "name": "Olivia Nyhuus", 332 + "email": "olivia.nyhuus@example.com", 333 + "mobilePhoneNumber": "004791234567", 334 + "shippingAddress": { 335 + "city": "Oslo", 336 + "countryCode": "NO", 337 + "streetAddress": "StÄlverkskroken, 4", 338 + "zipCode": "0661" 339 + } 340 + }, 341 + "payment": "https://api.payex.com/psp/payment/credit-card/984-223-836", 342 +} 343 +{{/code}} 344 + 345 +Retrieve the Payment and inspect its state. 346 + 347 +**Request** 348 + 349 +{{code language="JavaScript"}} 350 +GET <payment_url> HTTP/1.1 351 +Content-Type: application/json 352 +Authorization: Bearer merchantToken== 353 +{{/code}} 354 + 355 +**Response** 356 + 357 +{{code language="JavaScript"}} 358 +{ 359 + "payment": { 360 + "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c", 361 + "number": 1234567890, 362 + "created": "2016-09-14T13:21:29.3182115Z", 363 + "updated": "2016-09-14T13:21:57.6627579Z", 364 + "operation": "Purchase|Verify|Recur", 365 + "intent": "PreAuthorization|Authorization|AutoCapture", 366 + "state": "Ready|Pending|Failed|Aborted", 367 + "currency": "NOK|SEK|...", 368 + "amount": 1500, 369 + "remainingCaptureAmount": 1500, 370 + "remainingCancellationAmount": 1500, 371 + "remainingReversalAmount": 0, 372 + "description": "Test Purchase", 373 + "initiatingSystemUserAgent": "PostmanRuntime/3.0.1", 374 + "userAgent": "Mozilla/5.0...", 375 + "language": "nb-NO", 376 + "paymentToken": "5adc265f-f87f-4313-577e-08d3dca1a26c", 377 + "prices": { 378 + "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/prices" 379 + }, 380 + "transactions": { 381 + "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/transactions" 382 + }, 383 + "authorizations": { 384 + "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/authorizations" 385 + }, 386 + "captures": { 387 + "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/captures" 388 + }, 389 + "cancellations": { 390 + "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/cancellations" 391 + }, 392 + "reversals": { 393 + "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/reversals" 394 + }, 395 + "payeeInfo": { 396 + "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/payeeInfo" 397 + }, 398 + "urls": { 399 + "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/urls" 400 + }, 401 + "settings": { 402 + "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/settings" 403 + } 404 + }, 405 + "operations": [ 406 + { 407 + "href": "<capture_operation_url>", 408 + "rel": "create-checkout-capture", 409 + "method": "POST" 410 + }, 411 + { 412 + "href": "<cancellation_operation_url>", 413 + "rel": "create-checkout-cancellation", 414 + "method": "POST" 415 + }, 416 + { 417 + "href": "<reversal_operation_url>", 418 + "rel": "create-checkout-reversal", 419 + "method": "POST" 420 + } 421 + ] 422 +} 423 +{{/code}} 424 +))) 425 + 426 +(% id="C_2" %) 427 +((( 428 +==== Implementation example ==== 429 + 430 +{{code language="c#"}} 431 +var merchantToken = "<secret merchant token>"; 432 +var httpClient = new HttpClient(); 433 +httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + merchantToken); 434 + 435 +// 1. Retrieve the paymentSessionUrl related to the submitted form from storage. 436 +var paymentSessionUrl = "<retrieved from storage>"; 437 + 438 +// 2. Retrieve the Payment Session and find the URL of the Payment. 439 +var paymentSessionResponse = await httpClient.GetAsync(paymentSessionUrl); 440 +var paymentSessionContent = await paymentSessionResponse.Content.ReadAsStringAsync(); 441 +var paymentSession = Newtonsoft.Json.Linq.JObject.Parse(paymentSessionContent); 442 +var paymentUrl = paymentSession["payment"].ToString(); 443 + 444 +// 3. Retrieve the Payment and inspect its state. 445 +var paymentResponse = await httpClient.GetAsync(paymentUrl); 446 +var paymentContent = await paymentResponse.Content.ReadAsStringAsync(); 447 +var payment = Newtonsoft.Json.Linq.JObject.Parse(paymentContent); 448 +var paymentState = payment["state"].ToString(); 449 +{{/code}} 450 + 451 +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. 452 +))) 453 + 454 +---- 455 + 456 +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. 457 + 458 +Read more about the payment session [[here>>Main.ECommerce.PayEx Checkout.Introduction.Payment-session.WebHome||anchor="HRetrievePaymentSession"]]. 459 + 460 +== Step 5: Capture the payment == 461 + 462 +{{tabs idsToLabels="HTTP_3=HTTP, C_3=C#"/}} 463 + 464 +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. 465 + 466 + 467 +(% id="HTTP_3" %) 468 +((( 469 +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. 470 + 471 +**Request** 472 + 473 +{{code language="JavaScript"}} 474 +GET https://api.payex.com/psp/checkout/payment-sessions/123-456-789 HTTP/1.1 475 +Accept: application/json 476 +Authorization: Bearer merchantToken== 477 +{{/code}} 478 + 479 +**Response** 480 + 481 +{{code language="JavaScript"}} 482 +HTTP/1.1 200 OK 483 +Content-Type: application/json 484 + 485 +{ 486 + "amount": 199.50, 487 + "vatAmount": 39.90, 488 + "currency": "NOK", 489 + "callbackUrl": "https://merchant.api/callback", 490 + "reference": "merchant-order-123", 491 + "acquire": ["email", "mobilePhoneNumber", "shippingAddress"], 492 + "culture": "nb-NO", 493 + "addressee": { 494 + "name": "Olivia Nyhuus", 495 + "email": "olivia.nyhuus@example.com", 496 + "mobilePhoneNumber": "004791234567", 497 + "shippingAddress": { 498 + "city": "Oslo", 499 + "countryCode": "NO", 500 + "streetAddress": "StÄlverkskroken, 4", 501 + "zipCode": "0661" 502 + } 503 + }, 504 + "payment": "https://api.payex.com/psp/payment/credit-card/984-223-836" 505 +} 506 +{{/code}} 507 + 508 +Retrieve the Payment and find its {{code}}create-checkout-capture{{/code}} operation: 509 + 510 +**Request** 511 + 512 +{{code language="JavaScript"}} 513 +GET <payment_url> HTTP/1.1 514 +Content-Type: application/json 515 +Authorization: Bearer merchantToken== 516 +{{/code}} 517 + 518 +**Response** 519 + 520 +{{code language="JavaScript"}} 521 +{ 522 + "payment": { 523 + "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c", 524 + "number": 1234567890, 525 + "created": "2016-09-14T13:21:29.3182115Z", 526 + "updated": "2016-09-14T13:21:57.6627579Z", 527 + "operation": "Purchase|Verify|Recur", 528 + "intent": "PreAuthorization|Authorization|AutoCapture", 529 + "state": "Ready|Pending|Failed|Aborted", 530 + "currency": "NOK|SEK|...", 531 + "amount": 1500, 532 + "remainingCaptureAmount": 1500, 533 + "remainingCancellationAmount": 1500, 534 + "remainingReversalAmount": 0, 535 + "description": "Test Purchase", 536 + "initiatingSystemUserAgent": "PostmanRuntime/3.0.1", 537 + "userAgent": "Mozilla/5.0...", 538 + "language": "nb-NO", 539 + "paymentToken": "5adc265f-f87f-4313-577e-08d3dca1a26c", 540 + "prices": { 541 + "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/prices" 542 + }, 543 + "transactions": { 544 + "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/transactions" 545 + }, 546 + "authorizations": { 547 + "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/authorizations" 548 + }, 549 + "captures": { 550 + "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/captures" 551 + }, 552 + "cancellations": { 553 + "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/cancellations" 554 + }, 555 + "reversals": { 556 + "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/reversals" 557 + }, 558 + "payeeInfo": { 559 + "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/payeeInfo" 560 + }, 561 + "urls": { 562 + "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/urls" 563 + }, 564 + "settings": { 565 + "id": "/psp/creditcard/payments/5adc265f-f87f-4313-577e-08d3dca1a26c/settings" 566 + } 567 + }, 568 + "operations": [ 569 + { 570 + "href": "<capture_operation_url>", 571 + "rel": "create-checkout-capture", 572 + "method": "POST" 573 + }, 574 + { 575 + "href": "<cancellation_operation_url>", 576 + "rel": "create-checkout-cancellation", 577 + "method": "POST" 578 + }, 579 + { 580 + "href": "<reversal_operation_url>", 581 + "rel": "create-checkout-reversal", 582 + "method": "POST" 583 + } 584 + ] 585 +} 586 +{{/code}} 587 + 588 +Perform the capture request: 589 + 590 +**Request** 591 + 592 +{{code language="JavaScript"}} 593 +POST <capture_operation_href> HTTP/1.1 594 +Accept: application/json 595 +Content-Type: application/json 596 +Authorization: Bearer merchantToken== 597 + 598 +{ 599 + "transaction": { 600 + "description": "description for the transaction" 601 + } 602 +} 603 +{{/code}} 604 + 605 +**Response** 606 + 607 +{{code language="JavaScript"}} 608 +{ 609 + "payment": "<paymentUrl>", 610 + "capture": { 611 + "id": "<paymentCaptureUrl>", 612 + "transaction": { 613 + "id": "<transactionUrl>", 614 + "created": "2016-09-14T01:01:01.01Z", 615 + "updated": "2016-09-14T01:01:01.03Z", 616 + "type": "Capture", 617 + "state": "Initialized|Completed|Failed", 618 + "number": 1234567890, 619 + "amount": 1500, 620 + "vatAmount": 300, 621 + "description": "Test Capture", 622 + "payeeReference": "ABC123", 623 + "failedReason": "", 624 + "isOperational": "TRUE|FALSE", 625 + "operations": [] 626 + } 627 + } 628 +} 629 +{{/code}} 630 + 631 +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. 632 +))) 633 + 634 +(% id="C_3" %) 635 +((( 636 +Implementation example 637 + 638 +{{code language="c#"}} 639 +var merchantToken = "<secret merchant token>"; 640 +var httpClient = new HttpClient(); 641 +httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + merchantToken); 642 + 643 +// 1. Retrieve the paymentSessionUrl related to the submitted form from storage. 644 +var paymentSessionUrl = "<retrieved from storage>"; 645 + 646 +// 2. Retrieve the Payment Session and find the URL of the Payment. 647 +var paymentSessionResponse = await httpClient.GetAsync(paymentSessionUrl); 648 +var paymentSessionContent = await paymentSessionResponse.Content.ReadAsStringAsync(); 649 +var paymentSession = Newtonsoft.Json.Linq.JObject.Parse(paymentSessionContent); 650 +var paymentUrl = paymentSession["payment"].ToString(); 651 + 652 +// 3. Retrieve the Payment and find its 'create-checkout-capture' operation. 653 +var paymentResponse = await httpClient.GetAsync(paymentUrl); 654 +var paymentContent = await paymentResponse.Content.ReadAsStringAsync(); 655 +var payment = Newtonsoft.Json.Linq.JObject.Parse(paymentContent); 656 +var captureUrl = payment["operations"] 657 + .Children() 658 + .First(x => x["rel"].ToString() == "create-checkout-capture")["href"] 659 + .ToString(); 660 + 661 +// 4. Perform the capture request. 662 +var json = Newtonsoft.Json.JsonConvert.SerializeObject(new 663 +{ 664 + transaction = new 665 + { 666 + description = "Captured the payment" 667 + } 668 +}); 669 +var captureRequestContent = new StringContent(json, Encoding.UTF8, "application/json"); 670 +var captureResponse = await httpClient.PostAsync(captureUrl, captureRequestContent); 671 +var captureResponseContent = await captureResponse.Content.ReadAsStringAsync(); 672 +var capture = Newtonsoft.Json.Linq.JObject.Parse(captureResponseContent); 673 +{{/code}} 674 + 675 +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. 676 + 677 +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.>>Main.ECommerce.PayEx Checkout.Introduction.Payment.WebHome||anchor="HCapture"]] 678 +))) 679 + 680 +---- 681 + 682 +~{~{/completed}} 683 +~)~)~)