Server to Server: Embedded Components

We recommend that you use our Client SDKs: Embedded Components to support Native Alternative Payment Methods. Our SDKs will handle the whole UI flow and make all the necessary backend calls that are described in this guide. In case you choose to support Native APMs with the server version, you’d have to implement the UI flow control yourselves.

Fetch a list of available Native APMs

The first step is to generate a list of available Native APMs for the user to choose from. The relevant information about the native APMs is kept in the GatewayConfiguration objects that represent them. You will probably find it useful to expand the gateway field of the GatewayConfiguration objects when you list them because the Gateway object contains the Native APM's name, logo and other details you might want to display. To achieve that add the expand_merchant_accounts=true to your query parameters or options.

There are gateway configurations for all payment methods, but you can filter the list to include only Native APMs, as shown in the example below.

curl https://api.processout.com/gateway-configurations?filter=native-alternative-payment-methods&expand_merchant_accounts=true \
      -u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB
confs = client.new_gateway_configuration().create({
    "filter":                   "native-alternative-payment-methods",
    "expand_merchant_accounts": True
})
# Iterate over the available configurations and display them.
confs = client.gateway_configuration.new().all(
    filter:                   "native-alternative-payment-methods",
    expand_merchant_accounts: true
)
# Iterate over the available configurations and display them.
$confs = $client->newGatewayConfiguration()->all(array(
    "filter":                   "native-alternative-payment-methods",
    "expand_merchant_accounts": true
));
// Iterate over the available configurations and display them.
confs, err := client.NewGatewayConfiguration().All(processout.GatewayConfigurationAllParameters{
    ExpandMerchantAccounts: true,
    Options: &processout.Options{
        Filter: "native-alternative-payment-methods",
    },
})
if err != nil {
    panic(err)
}
// Iterate over the available configurations and display them.
client.newGatewayConfiguration().all({
    filter:                   "native-alternative-payment-methods",
    expand_merchant_accounts: true
}).then(function(confs) {
    // Iterate over the available configurations and display them.

}, function(err) {
    // An error occured.
  
});

Once you have the list, you can iterate over it to present the options in any way you like. For example, on a web page, you might create a menu or a list of links for the Native APMs.

You should design your UI to send the gateway configuration id of the chosen Native APM back to your server. You will need these fields to process the Native APM payment. The gateway configuration id for APMs (including native ones) is composed of the <gateway_configuration_uid>.<native_apm_gateway_name>.

The native_apm_config field contains details about the information you need to collect from your customer before creating the payment request to ProcessOut. The field type is json and it would be in the following format:

{
  "parameters": [
    {
      "key": "example", // name of the field that needs to be collect for the request e.g. blik_code
      "type": "text", // type of the field e.g. email, phone, numeric, text etc.
      "length": 6, // expected length of the field (for validation purposes)
      "required": true // informs if it is an optional or a required field
    }
  ],
  "customer_action_message": "To complete the payment please confirm it from your banking app.", // message you can display to your customer on the customer action page
  "customer_action_image_url": "https://js.processout.com/images/native-apm-assets/blik_customer_action_image.png" // a default imagine you can use to display to your customer on the customer action page
}

The key will be used when creating the payment as it will map to the customer information the APM requires. You can also leverage this information to build your UI components and collect the details from your customers.

Currently we support the following parameter types:

ParameterContents
numericNumeric-only fields
textAlphanumeric fields
emailEmail fields
phonePhone number fields

📘

If the length field is null, that means there is no length requirement for that specific parameter and no length validation will be performed on our side.

Initiate the payment request

When you have collected the information from your customer you can make the following API call to create the Native APM payment request.

Endpoint: POST /invoices/{invoice_id}/native-payment

For example:

{
    "gateway_configuration_id": "<gateway_configuration_id>.<gateway_name>",
    "native_apm": {
        "parameter_values": {
          "<parameter_key>": "<value_you_collected>",
          ...
        }
    }
}

The gateway_configuration_id is constructed from the gateway configuration id and the gateway name you have fetched earlier.

Collecting additional information

Some Native APMs require further information to be collected back from the customer. In that case, our API will send back details of the information that needs to be collected. For example:

{
  "native_apm": {
    "state": "CUSTOMER_INPUT",
    "parameters": [
      {
        "key": "token",
        "type": "numeric",
        "required": true,
        "length": 6
      },
      {
        "key": "name",
        "type": "string",
        "required": false,
        "length": null
      }
    ],
    "parameterValues": {
      "message": "Dear John Doe, your transaction has succeeded"
    }
  },...

You can use that information to render further UI components in order to collect the necessary information or if you already have it you can create another POST request to the same endpoint as before. Example payload:

{
  "gateway_configuration_id": "<gateway_configuration_id>.<gateway_name>",
  "native_apm": {
    "parameter_values": {
      "token": "123456",
      "name": "John Doe"
    }
  }
}

Once a payment is completed you will get a confirmation that the payment has been processed and is awaiting the webhook to confirm it was settled. For example:

{
  "native_apm": {
    "state": "PENDING_CAPTURE",
    "parameters": null,
    "parameterValues": {
      "message": "Dear John Doe, your transaction has succeeded"
    }
  }
}

📘

If you lost the context of which additional parameters you needed to supply, you could revisit the response you would have gotten by fetching the transaction and inspecting the native_apm_response field.

Manually updating (capturing) a transaction

If you wish not to wait for the webhook to confirm the transaction's status, some Native APMs offer the ability to check the status of the capture earlier. To do that, you can refer to the Capturing a payment page or call our Capture an invoice endpoint.

You must use the gateway_configuration_id you obtained for the previous calls as the source parameter in the request. If the transaction was successfully captured, you will get a native APM status of Captured.

📘

The Native APMs that do not offer this functionality will just add a Pending Capture operation, and you will still need to wait for the webhook to update the status of the transaction.

Error Handling

Errors will not differ from the normal errors that our API sends back with the only exception of our ability to provide details about invalid fields for some APM providers (given the PSP also provides that granularity). An example response from our sandbox gateway when you enter an invalid email address will look like this:

{
    "error_type": "gateway.invalid-customer-input",
    "invalid_fields": [
        {
            "name": "email",
            "message": "Customer's Email address is not recognized by our system."
        }
    ],
    "message": "Customer's Email address is not recognized by our system.",
    "success": false
}

Retrieving the current native APM transaction state

We provide an API endpoint that allows you to retrieve the current state of the native APM transaction.

Endpoint: GET /invoices/{invoice_id}/native-payment/{gateway_configuration_id}

An example response will contain the following:

    "native_apm": {
        "gateway": {
            "customer_action_image_url": "https://js.processout.com/images/native-apm-assets/blik_customer_action_image.png",
            "customer_action_message": "To complete the payment please confirm it from your banking app.",
            "display_name": "ProcessOut test gateway",
            "logo_url": "https://www.processout.com/images/logo.png"
        }, // Information about the gateway and customer action assets
        "invoice": {
            "amount": "13",
            "currency_code": "PLN"
        }, // information about the invoice
        "parameters": [
            {
                "key": "email",
                "type": "email",
                "required": true,
                "length": null,
                "display_name": "Email"
            }
        ]
    }, // fields that need to be collected at this stage (if applicable)

Testing using our Sandbox Gateway

You can leverage our Sandbox mode and our Sandbox gateway to perform your testing. To read more about testing in sandbox please refer our sandbox testing guide.

The Sandbox gateway can simulate a scenario where you will have to initially provide the information described in the Native APM configuration and will also ask for additional information after the initial call.

Creating the payment request

You can follow the initial steps of this guide to receive the sandbox gateway configuration that you will need for the initial call. In the native_apm_config for that gateway you should see the following:

{
  "parameters": [
    {
      "key": "email",
      "type": "email",
      "length": null,
      "required": true
    }
  ]
}

This tells you to collect the email and send it in the initial call to the gateway. Make the following call to the POST /invoices/{{invoice_id}}/native-payment endpoint using the following payload

{
  "gateway_configuration_id": "<gateway_configuration_uid>.sandbox",
  "native_apm": {
    "parameter_values": {
      "email": "[email protected]"
    }
  }
}

📘

If you want to simulate a failure scenario on this step of the flow, use any valid email apart from the one above. You can also supply any other unexpected parameter and you will receive an error from the API that will let you know which parameters are invalid or missing.

The response (in the success scenario) should be:

{
    "native_apm": {
        "state": "CUSTOMER_INPUT",
        "parameterDefinitions": [
            {
                "key": "token",
                "type": "numeric",
                "required": true,
                "length": 6
            },
            {
                "key": "name",
                "type": "string",
                "required": false,
                "length": null
            }
        ],
        "parameterValues": {
          "message": "Please provide the token value and your name"
        }
    },

This tells you which parameters to collect and supply in the next call. In case of the failure scenario you can redo the call with the valid email and it should produce the same success response.

Make the follow-up call to supply additional details

You can now make a call to the same endpoint with the following payload:

{
    "gateway_configuration_id": "<gateway_configuration_uid>.sandbox",
    "native_apm": {
      "parameter_values": {
        "token": "123456",
        "name": "John Doe"
      }
    }
}

Here the only required parameter is the token and it needs to be 6 digits long. You can simulate a failure call when you provide an invalid token or not supply it at all (the latter will produce an API error).

{
  "native_apm": {
    "state": "PENDING_CAPTURE",
    "parameterDefinitions": null,
    "parameterValues": {
      "message": "Dear John Doe, your transaction has succeeded"
    }
  },
  ...
}

Normally at this point you will have two choices:

  • Wait for the webhook to update the transaction
  • Call our capture endpoint.

Since our sandbox gateway currently doesn't simulate webhooks for this flow, you can call the /invoices/capture endpoint to complete the payment using the gateway_configuration_id as a source.