When requesting checkout with 3d_verification payment ends out as "status": "CLO" but not captured?

I’m making requests in sandbox like this:

web request url: https://sandboxapi.rapyd.net/v1/checkout
web request body: {
"amount":###amount here###,
"country":"DK",
"currency":"DKK",
"merchant_reference_id":"1011",
"capture":false,
}

When calling with an amount that needs 3d_verification

I’ll get two webhook callback, the first one:

  {
   ...
  "type": "PAYMENT_SUCCEEDED",
  "data": {
	"paid": false,
    "amount": 0,
    "status": "ACT",
    "paid_at": 0,
    "captured": false,  
	"next_action": "3d_verification",
    ...

After 3d_verification has been done, I’ll get another call.

{
  ...
  "type": "PAYMENT_COMPLETED",
  "data": {
    "paid": true,
    "amount": 1500,
    "status": "CLO",
    "paid_at": 1622051363,
    "captured": false,
	"next_action": "not_applicable",

If I call with a payment that don’t need 3d_verification I’ll only get one webhook call:

{
  ...
  "type": "PAYMENT_SUCCEEDED",
  "data": {
    "paid": false,
    "amount": 0,
    "status": "ACT",
    "paid_at": 0,
    "captured": false,
    "next_action": "pending_capture",

How come that the 3d_verification is reported as CLOSED, paid: true and captured:false while the one without 3d_verification is reported as paid: false, status:ACT and next_action pending_capture

Why isn’t the payment with 3d_verification returned as ACT with “next_action”: “pending_capture” as that payment surely also need to be captured.

How can I decide when I need to capture or not to capture - is that only by reading “captured”: false?
And what is the true meaning of status CLO if it doesn’t mean that the payment is closed?

I would expect the status for the payment after 3d_verification to equal the one without 3d_verification => status: ACT as the payment hasn’t been captured yet - how come that it isn’t?

Please post the complete API requests.

If the payment method requires 3DS, it can’t move to completion until after the 3DS succeeds.

The only time you should set ‘capture’ to ‘false’ is when you are doing a card verification with amount=zero, or you intend to capture the payment with a later API call. Even if it is set to ‘true’, the payment won’t complete until the 3DS succeeds.

It’s confusing, but PAYMENT_SUCCEEDED means that the payment was created in the system, not that the entire process has completed. The ‘next_action’ field indicates what the next step in the process is. If the payment is completed, there is no next step, so the field says ‘not_applicable’.

Hi @CharlesDorsett

Please notice that this is in the sandbox

Full request
web request method: POST
web request url: https://sandboxapi.rapyd.net/v1/checkout
web request body: {“amount”:1500,“complete_checkout_url”:“http://oneshop.local/da-DK/gateway/Retur/Ok/fdb53816-9f36-4811-9935-00d731d90d8a",“complete_auto_redirect”:true,“cancel_checkout_url”:“http://oneshop.local/da-DK/Checkout/Status/fdb53816-9f36-4811-9935-00d731d90d8a”,“country”:“DK”,“currency”:“DKK”,“merchant_reference_id”:“2001”,“capture”:false,“metadata”:{“track_ident”:"fdb53816-9f36-4811-9935-00d731d90d8a”}}
web request contentType: application/json
web request salt: d0a68225020f6a87
web request timestamp: 1622051339
web request signature: YjJkODg1NjU2NjIxNDFlZDQ4NWQzODhlNGVlNDUxM2VkN2NkZGE5NzUwOTM2MjlkZjlmNTkxMDlkZGY2YmY3OA==
web request access_key: ####

Rapyd response {“status”:
{“error_code”:"",“status”:“SUCCESS”,“message”:"",“response_code”:"",“operation_id”:“ecc78cfb-273d-479a-91d3-64d45ef69cff”},“data”:{“id”:“checkout_28ab6d73b2ae3acd2836864e0803051c”,“country”:“DK”,“currency”:“DKK”,“amount”:1500,“status”:“NEW”,“payment”:{“id”:"",“amount”:1500,“original_amount”:0,“is_partial”:false,“currency_code”:“DKK”,“country_code”:“DK”,“status”:"",“description”:“Payment via Checkout”,“merchant_reference_id”:“2001”,“customer_token”:"",“expiration”:0,“captured”:false,“refunded”:false,“refunded_amount”:0,“receipt_email”:"",“redirect_url”:"",“complete_payment_url”:"",“error_payment_url”:"",“receipt_number”:"",“flow_type”:"",“address”:null,“statement_descriptor”:"",“transaction_id”:"",“created_at”:0,“updated_at”:0,“metadata”:{“track_ident”:“fdb53816-9f36-4811-9935-00d731d90d8a”},“failure_code”:"",“failure_message”:"",“paid”:false,“paid_at”:0,“dispute”:null,“refunds”:null,“order”:null,“outcome”:null,“visual_codes”:{},“textual_codes”:{},“instructions”:{},“ewallet_id”:null,“ewallets”:,“payment_method_options”:{},“payment_method_type”:"",“payment_method_type_category”:"",“fx_rate”:"",“merchant_requested_currency”:null,“merchant_requested_amount”:null,“payment_fees”:null,“invoice”:"",“escrow”:null},“payment_method_type”:"",“payment_method_type_categories”:null,“payment_method_types_include”:null,“payment_method_types_exclude”:null,“customer”:"",“customer_data”:null,“country_name”:“Denmark”,“merchant_color”:“323fff”,“merchant_website”:“https://www.rapyd.net”,“merchant_logo”:"",“merchant_alias”:“N/A”,“merchant_customer_support”:{},“custom_elements”:{“save_card_default”:false,“display_description”:false,“payment_fees_display”:true,“merchant_currency_only”:false,“billing_address_collect”:false,“cardholder_preferred_currency”:false,“merchant_color”:null},“language”:"",“complete_checkout_url”:“http://oneshop.local/da-DK/gateway/Retur/Ok/fdb53816-9f36-4811-9935-00d731d90d8a",“cancel_checkout_url”:“http://oneshop.local/da-DK/Checkout/Status/fdb53816-9f36-4811-9935-00d731d90d8a”,“redirect_url”:“https://sandboxcheckout.rapyd.net?token=checkout_28ab6d73b2ae3acd2836864e0803051c”,“timestamp”:1622051338,“payment_expiration”:null,“page_expiration”:1623260938,“cart_items”:[],“complete_checkout_auto_redirect”:false,“region”:"”}}

First webhook callback
{
“id”: “wh_5eeb4eeb9c4b2d81617e3b6119e08b7c”,
“type”: “PAYMENT_SUCCEEDED”,
“data”: {
“id”: “payment_5a05b64199704a5c238172e2b5d99804”,
“mid”: “”,
“paid”: false,
“order”: null,
“amount”: 0,
“escrow”: null,
“status”: “ACT”,
“address”: null,
“dispute”: null,
“fx_rate”: 1,
“invoice”: “”,
“outcome”: null,
“paid_at”: 0,
“refunds”: null,
“captured”: false,
“ewallets”: [
{
“amount”: 1500,
“percent”: 100,
“ewallet_id”: “ewallet_3b81035f1baa0075adf49c038916c28b”,
“refunded_amount”: 0
}
],
“metadata”: {
“track_ident”: “fdb53816-9f36-4811-9935-00d731d90d8a”
},
“refunded”: false,
“flow_type”: “”,
“created_at”: 1622051353,
“ewallet_id”: “ewallet_3b81035f1baa0075adf49c038916c28b”,
“expiration”: 1622656153,
“fixed_side”: “”,
“is_partial”: false,
“description”: “Payment via Checkout”,
“next_action”: “3d_verification”,
“country_code”: “dk”,
“failure_code”: “”,
“instructions”: {},
“payment_fees”: null,
“redirect_url”: “Rapyd Client Portal”,
“visual_codes”: {},
“cancel_reason”: null,
“currency_code”: “DKK”,
“group_payment”: “”,
“receipt_email”: “”,
“textual_codes”: {},
“customer_token”: “cus_85bafde57909056fb067a2da3f7fde4b”,
“payment_method”: “card_bc69c7d011127e701e7551e7372a68d1”,
“receipt_number”: “”,
“transaction_id”: “”,
“failure_message”: “”,
“initiation_type”: “customer_present”,
“original_amount”: 1500,
“refunded_amount”: 0,
“error_payment_url”: “Checkout”,
“payment_method_data”: {
“id”: “card_bc69c7d011127e701e7551e7372a68d1”,
“name”: “joe me”,
“type”: “dk_mastercard_card”,
“image”: “”,
“last4”: “1111”,
“category”: “card”,
“metadata”: {},
“acs_check”: “unchecked”,
“cvv_check”: “unchecked”,
“bin_details”: {
“brand”: null,
“bin_number”: “411111”
},
“webhook_url”: “”,
“expiration_year”: “23”,
“expiration_month”: “01”,
“fingerprint_token”: “ocfp_04b6c9d64396cb3078efe4e5e8deff89”,
“authentication_url”: “”,
“supporting_documentation”: “”
},
“payment_method_type”: “dk_mastercard_card”,
“complete_payment_url”: “Checkout”,
“statement_descriptor”: “N/A”,
“merchant_reference_id”: “2001”,
“payment_method_options”: {},
“merchant_requested_amount”: null,
“merchant_requested_currency”: null,
“payment_method_type_category”: “card”
},
“trigger_operation_id”: “f40f52d6-4b55-4c67-867a-34fdc6018d8d”,
“status”: “NEW”,
“created_at”: 1622051353
}

Next webhook callback

{
“id”: “wh_5cb8f9a6c328872d1d8ff2e80f0fe42d”,
“type”: “PAYMENT_COMPLETED”,
“data”: {
“id”: “payment_5a05b64199704a5c238172e2b5d99804”,
“mid”: “”,
“paid”: true,
“order”: null,
“amount”: 1500,
“escrow”: null,
“status”: “CLO”,
“address”: null,
“dispute”: null,
“fx_rate”: 1,
“invoice”: “”,
“outcome”: null,
“paid_at”: 1622051363,
“refunds”: null,
“captured”: false,
“ewallets”: [
{
“amount”: 1500,
“percent”: 100,
“ewallet_id”: “ewallet_3b81035f1baa0075adf49c038916c28b”,
“refunded_amount”: 0
}
],
“metadata”: {
“track_ident”: “fdb53816-9f36-4811-9935-00d731d90d8a”
},
“refunded”: false,
“flow_type”: “”,
“created_at”: 1622051353,
“ewallet_id”: “ewallet_3b81035f1baa0075adf49c038916c28b”,
“expiration”: 1622656153,
“fixed_side”: “”,
“is_partial”: false,
“description”: “Payment via Checkout”,
“next_action”: “not_applicable”,
“country_code”: “dk”,
“failure_code”: “”,
“instructions”: {},
“payment_fees”: null,
“redirect_url”: “Rapyd Client Portal”,
“visual_codes”: {},
“cancel_reason”: null,
“currency_code”: “DKK”,
“group_payment”: “”,
“receipt_email”: “”,
“textual_codes”: {},
“customer_token”: “cus_85bafde57909056fb067a2da3f7fde4b”,
“payment_method”: “card_bc69c7d011127e701e7551e7372a68d1”,
“receipt_number”: “”,
“transaction_id”: “”,
“failure_message”: “”,
“initiation_type”: “customer_present”,
“original_amount”: 1500,
“refunded_amount”: 0,
“error_payment_url”: “Checkout”,
“payment_method_data”: {
“id”: “card_bc69c7d011127e701e7551e7372a68d1”,
“name”: “joe me”,
“type”: “dk_mastercard_card”,
“image”: “”,
“last4”: “1111”,
“category”: “card”,
“metadata”: {},
“acs_check”: “unchecked”,
“cvv_check”: “unchecked”,
“bin_details”: {
“brand”: null,
“bin_number”: “411111”
},
“webhook_url”: “”,
“expiration_year”: “23”,
“expiration_month”: “01”,
“fingerprint_token”: “ocfp_04b6c9d64396cb3078efe4e5e8deff89”,
“authentication_url”: “”,
“supporting_documentation”: “”
},
“payment_method_type”: “dk_mastercard_card”,
“complete_payment_url”: “Checkout”,
“statement_descriptor”: “N/A”,
“merchant_reference_id”: “2001”,
“payment_method_options”: {},
“merchant_requested_amount”: null,
“merchant_requested_currency”: null,
“payment_method_type_category”: “card”
},
“trigger_operation_id”: “2433b7d6-92dd-40b5-aff2-5efc74b3b754”,
“status”: “NEW”,
“created_at”: 1622051363
}

Hi @CharlesDorsett

I trying to use Repyd as something as simple as a payment gateway for credit cards.

For this, I wanted to use the hosted payment window. When the customer process the payment on the gateway we first receive a webhook call with:

"status": "ACT",
"next_action": "3d_verification",

fine with me, I don’t need to do anything here.
Next webhook call yields

    "paid": true,
    "amount": 1500,
    "status": "CLO",
    "paid_at": 1622051363,
    "captured": false,
	"next_action": "not_applicable",

And I have several problems with this - my main problem is that a non 3d_verification yields:

    "paid": false,
    "amount": 0,
    "status": "ACT",
    "paid_at": 0,
    "captured": false,
    "next_action": "pending_capture",

Can’t you see the different? From my perspective - as the shop - the two payments should be in the same state

     paid": false,
    "amount": 0,
    "status": "ACT",
    "paid_at": 0,
    "captured": false,
    "next_action": "pending_capture",

My next problem is that I can’t capture the 3d_verification payment from the portal as IT IS CLOSED!

Compared with the non 3DS payment

Just for the record, I’m still able to capture the CLOSED payment throught the API

{
   "status":{
      "error_code":"",
      "status":"SUCCESS",
      "message":"",
      "response_code":"",
      "operation_id":"f9edbda9-e1d4-407e-8633-e9fde0691cf0"
   },
   "data":{
      "id":"payment_5a05b64199704a5c238172e2b5d99804",
      "amount":1500,
      "original_amount":1500,
      "is_partial":false,
      "currency_code":"DKK",
      "country_code":"dk",
      "status":"CLO",
      "description":"Payment via Checkout",
      "merchant_reference_id":"2001",
      "customer_token":"cus_85bafde57909056fb067a2da3f7fde4b",
      "payment_method":"card_bc69c7d011127e701e7551e7372a68d1",
      "payment_method_data":{
         "id":"card_bc69c7d011127e701e7551e7372a68d1",
         "type":"dk_mastercard_card",
         "category":"card",
         "metadata":{
            
         },
         "image":"",
         "authentication_url":"",
         "webhook_url":"",
         "supporting_documentation":"",
         "name":"joe me",
         "last4":"1111",
         "acs_check":"unchecked",
         "cvv_check":"unchecked",
         "bin_details":{
            "brand":null,
            "bin_number":"411111"
         },
         "expiration_year":"23",
         "expiration_month":"01",
         "fingerprint_token":"ocfp_04b6c9d64396cb3078efe4e5e8deff89"
      },
      "expiration":1622656153,
      "captured":true,
      "refunded":false,
      "refunded_amount":0,
      "receipt_email":"",
      "redirect_url":"https://dashboard.rapyd.net/3ds-payment?token=payment_5a05b64199704a5c238172e2b5d99804",
      "complete_payment_url":"https://sandboxcheckout.rapyd.net/thank-you-success/checkout_28ab6d73b2ae3acd2836864e0803051c",
      "error_payment_url":"https://sandboxcheckout.rapyd.net/thank-you-failed/checkout_28ab6d73b2ae3acd2836864e0803051c",
      "receipt_number":"",
      "flow_type":"",
      "address":null,
      "statement_descriptor":"N/A",
      "transaction_id":"",
      "created_at":1622051353,
  "metadata":{
     "track_ident":"fdb53816-9f36-4811-9935-00d731d90d8a"
  },
  "failure_code":"",
  "failure_message":"",
  "paid":true,
  "paid_at":1622051363,
  "dispute":null,
  "refunds":null,
  "order":null,
  "outcome":null,
  "visual_codes":{
     
  },
  "textual_codes":{
     
  },
  "instructions":{
     
  },
  "ewallet_id":"ewallet_3b81035f1baa0075adf49c038916c28b",
  "ewallets":[
     {
        "ewallet_id":"ewallet_3b81035f1baa0075adf49c038916c28b",
        "amount":1500,
        "percent":100,
        "refunded_amount":0
     }
  ],
  "payment_method_options":{
     
  },
  "payment_method_type":"dk_mastercard_card",
  "payment_method_type_category":"card",
  "fx_rate":1,
  "merchant_requested_currency":null,
  "merchant_requested_amount":null,
  "fixed_side":"",
  "payment_fees":null,
  "invoice":"",
  "escrow":null,
  "group_payment":"",
  "cancel_reason":null,
  "initiation_type":"customer_present",
  "mid":"",
  "next_action":"not_applicable"

}
}

If it’s closed, then it was already captured. I will look more closely at your examples on Sunday.

It’s closed but not captured

Okay, second and final update.

‘capture’ is not officially supported for hosted checkout pages yet, so it’s not documented in the API Reference, but it does work. If you need to run an authorization only, then you create the hosted page and set ‘capture’=false in the root of the body of the request. For the later capture (‘capture’=true), you use the ‘Capture Payment’ API method.

What was confusing both you and me was that we were using ‘Complete Payment’ instead of ‘Capture Payment’. ‘Complete Payment’ is just for the sandbox, and just for simulating the completion of the 3DS process (or other third-party action).

Here’s the sequence of events you need to design for:

  1. Create Checkout Page, using the API.

The response contains the following information:

  • ‘status’ of the checkout page is NEW.
  • ‘status’ of the payment is null (undefined, because it doesn’t exist yet)
  • ‘next_action’ is not part of the checkout page object, so it is not returned here.
  • ‘capture’ in the payment object is not relevant yet because we don’t yet know whether the customer will choose a card (as opposed to other category of payment method, which capture is not relevant for).

At this stage, there is no webhook, and nothing shows up in the Client Portal yet.

You can use the API to retrieve the checkout page to verify this information - it is all the same as what appears in the API response.

  1. The customer (end user) accesses the URL. There is no change to anything in the system yet.

  2. The customer provides the details required for the payment method, then clicks ‘Place your order’ (or whatever it reads in the language selected). The following changes occur, which is reflected in the PAYMENT_SUCCEEDED webhook (there is no API response):

  • ‘status’ of the checkout page changes to ACT (=active).
  • ‘status’ of the payment object changes to ACT.
  • ‘captured’ in the payment object is false (which matches the setting in the hosted page).
  • ‘next_action’ changes to ‘3d_verification’ if the amount is larger than the threshold for the selected card. If the amount is lower, then it changes to ‘pending_capture’.
  1. If 3DS is required, the customer is redirected to a 3DS page - in the sandbox, this is a simulator. The customer clicks ‘Pay’ and the following changes occur:
  • ‘status’ of the checkout page is still ACT.
  • ‘status’ of the payment is still ACT.
  • ‘captured’ in the payment object is still false.
  • ‘next_action’ in the payment object changes to ‘pending_capture’
  • No webhook is sent, but you can see the changes by querying the API with the payment ID.
  1. If 3DS is not required, the customer clicks ‘Pay’ and is redirected to the URL specified in ‘complete_checkout_url’. There is no webhook, and no change in either the checkout page object or the payment object.

  2. The merchant uses the ‘Capture Payment’ API method.
    The API returns a response, the PAYMENT_CAPTURED webhook and the PAYMENT_COMPLETED webhook, all of which show the following changes:

  • ‘status’ of the payment changes to CLO.
  • ‘next_action’ in the payment object changes to ‘not_applicable’.
  • ‘captured’ in the payment object changes to ‘true’.
    These changes are visible in the Client Portal, but you might need to refresh your browser or wait a few minutes. You can also see them with the ‘Retrieve Payment’ API call. You can also check the balance in the client wallet, both in the Client Portal and in the response to the ‘Retrieve Wallet’ API call.

‘status’ of the checkout page also changes to CLO. You can see this by retrieving the original checkout page object in the API.

1 Like

That’s not my experience - when playing around with the sandbox the hosted checkout page will default to capture=true, but I can override it by setting capture=false. If it’s not supported:

  1. why is it available in the request?
  2. why ain’t I’m getting an error when setting it to false?

Not really :slight_smile:

That’s what I’m doing

I know - I have seen it several times - and I expect that there’s a “bug” in this as it CLO the payment instead of leaving it with ACT → capture.

For several reasons (mostly law regulations in my country) I need to use the hosted window and I need to be able to not capture the payment until I ship the goods. It’s illegal by law to do an instant capture when a customer process payment for non-downloadable items in Denmark.

I think I need to skip using the sandbox for development and instead do development directly in production and just cross my fingers that production isn’t as error-prone as the sandbox.

I have worked as an e-commerce developer since 2001 and I have seen my fair share of payments gateways - Rapyd is by far the most difficult I have ever worked with. I have already spent around 40 hours and are still unable to process the payment of an invoice.

Thanks for your patience. I talked with the product manager about this. It turns out the feature works, but there are a few things that need to be worked out before we publish it. The team is currently evaluating it and there is no projected date yet.

I revised my earlier list of events to reflect the procedure - I tested it and it does work. Basically, what you do is this:

  1. Create the checkout page with capture=false.

  2. The customer fills in the details.

  3. The merchant (that’s you) then uses the ‘Capture Payment’ API method to capture the payment.

1 Like