Native alternative payment methods (server version)

We recommend that you use our client API to support native Alternative Payment Methods (APMs) but you can also access the relevant information on your server (to generate a web page with static Native APM links). See the client API page for a description of the asynchronous payment flow that APMs use.

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 param 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
client.newGatewayConfiguration().all({
    filter:                   "native-alternative-payment-methods",
    expand_merchant_accounts: true
}).then(function(confs) {
    // Iterate over the available confs and display them

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

});
confs = client.new_gateway_configuration().create({
    "filter":                   "native-alternative-payment-methods",
    "expand_merchant_accounts": True
})
# Iterate over the available confs and display them
confs = client.gateway_configuration.new().all(
    filter:                   "native-alternative-payment-methods",
    expand_merchant_accounts: true
)
# Iterate over the available confs and display them
$confs = $client->newGatewayConfiguration()->all(array(
    "filter":                   "native-alternative-payment-methods",
    "expand_merchant_accounts": true
));
// Iterate over the available confs 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 confs and display them

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
    }
  ]
}

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:

  • numeric - for numeric only fields
  • text - for any alphanumeric fields
  • email - for email fields
  • phone - for phone fields

NOTE: 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.

Creating the invoice

curl https://api.processout.com/invoices \
    -u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB \
    -d name="Awesome invoice" \
    -d amount="9.99" \
    -d currency=USD \
    -d return_url="https://www.super-merchant.com/return" \
    -d metadata[skip_processoutjs]=true
client.newInvoice().create({
    name:       "Amazing item",
    amount:     "4.99",
    currency:   "USD",
    return_url: "https://www.super-merchant.com/return",
    metadata: {
      skip_processoutjs: "true"
    }
}).then(function(invoice) {
    //

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

});
invoice = client.new_invoice().create({
    "name":       "Amazing item",
    "amount":     "4.99",
    "currency":   "USD",
    "return_url": "https://www.super-merchant.com/return",
    "metadata": {
      "skip_processoutjs": "true"
    }
})
invoice = client.invoice.create(
    name:       "Amazing item",
    amount:     "4.99",
    currency:   "USD",
    return_url: "https://www.super-merchant.com/return",
    metadata: {
      skip_processoutjs: "true"
    }
)
$invoice = $client->newInvoice()->create(array(
    "name"       => "Amazing item",
    "amount"     => "4.99",
    "currency"   => "USD",
    "return_url" => "https://www.super-merchant.com/return",
    "metadata": array(
      "skip_processoutjs" => "true"
    )
));
iv, err := client.NewInvoice().Create(processout.InvoiceCreateParameters{
    Invoice: &processout.Invoice{
        Name:      processout.String("Amazing item"),
        Amount:    processout.String("4.99"),
        Currency:  processout.String("USD"),
        ReturnURL: processout.String("https://www.super-merchant.com/return"),
        Metadata:  &map[string]string{
          "skip_processoutjs": "true",
        },
    },
})
if err != nil {
    panic(err)
}

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"
    }
  }
}

NOTE: 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 to not wait for the webhook to confirm the status of the transaction, some Native APMs offer the ability to check the status of the capture earlier. To do that you can refer to the capture a payment page or alternatively call our /capture endpoint and using the gateway_configuration_id you obtained for the previous calls as a source.

NOTE: 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.

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 sanbox 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": "test@processout.com"
    }
  }
}

NOTE: 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 invoices/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.