Field Render

Display a Payment Field that supports with Stripe & PayPal Express gateways, working on both front-end and back-end.

Field Group

Field Settings

Setting nameDescription
GatewaysChoose the payment gateways to display and their order
AmountThe default amount to charge
CurrencyThe currency to use
DescriptionA description attached to the payment. Useful for displaying to users
Display ButtonWhenever to display an inline “Pay Now” button or not
Button ValueSet a default button value
Button AttributesAdd class and id attributes to the button
Before Button HTMLAdd cutom HTML before the button render
After Button HTMLAdd custom HTML after the button render
Stripe Hide Postal CodeHide Stripe’s postal code field validation which can be displayed in specific cases
Stripe Test APISet the Stripe Secret & Public Keys. Available in your Stripe Test Dashboard
Stripe Production APISet the Stripe Secret & Public Keys. Available in your Stripe Production Dashboard
PayPal Test APISet the PayPal Sandbox Credentials. Available in your PayPal Sandbox Dashboard
PayPal Production APISet the PayPal Sandbox Credentials. Available in your PayPal Production Dashboard
ModeSwitch API mode between Test & Production

Stripe Setup

The Stripe gateway requires a Stripe account. Two API keys must be set: the Secret Key and the Public Key, both are available in your Stripe Dashboard.

Key NameFormat
Secret Keysk_xxxxxxxxxxxxxxxxxxxxxx
Public Keypk_xxxxxxxxxxxxxxxxxxxxxx

The “Test” keys are available in the same dashboard, when switching the mode to test on the top right corner.

PayPal Setup

The PayPal gateway requires a PayPal Business account. Four keys must be set: API Username, API Password, API Signature and PayPal Merchant ID.

Key NameFormat
API Usernamexxxxxxxxx.domain.com
API Passwordxxxxxxxxxxxxxxxxxxxx
API Signaturexxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Merchant IDxxxxxxxxxxxxx

Retrieve API Credentials

To generate your API Username, API Password and API Signature, follow this instruction:

  1. Log in to your PayPal business account at www.paypal.com
  2. Click the settings icon at the top of your PayPal account page and then click “Account Settings”
  3. On the “Account access” page, click “Update” for the API access item
  4. Click “Manage API Credentials” in the “NVP/SOAP API Integration (Classic)” section
  5. Select “Request API signature”. Then, click “Agree and Submit”

Retrieve the Merchant ID

To retrieve your Merchant ID, follow this instruction:

  1. Log in to your PayPal business account at www.paypal.com
  2. Click the settings icon at the top of your PayPal account page and then click “Account Settings”
  3. On the left column, under “Business Profile” click “Business Information”
  4. The PayPal Merchant ID will be displayed here

Sandbox Credentials

The “Test” credentials are available using the PayPal Sandbox UI. This interface will let you create a “Test” Business Account, which automatically generate Test API Username, Test API Password, Test API Signature and Test Merchant ID under the “API Credential” tab of the account information.

Payment Flow

The payment flow of both gateways is pretty straight forward and have been unified for the sake of simplicity:

  1. Create: A Stripe Payment Intent or PayPal Express Checkout is created
  2. Confirm: The Stripe Payment Intent or PayPal Express Checkout is confirmed
  3. Object: The Payment Object is generated and saved
  4. Success: Payment Success is triggered

Create Payment

The Create Payment step will generate the initial payment data. By default, the Payment Field will use the settings in the field configuration (Amount, Currency and Description). It is possible to change that initial payment data programmatically and use others fields values in order to calculate a custom amount, or add custom data to the payment using the acfe/fields/payment/create hook.

As in the Form module, developers have access to others fields input values within the submitted form, using native ACF functions get_field(), have_rows(), get_sub_field() etc…

Three arguments are mandatory and unified across Stripe and PayPal gateways: amount, currency and description. Other keys in the $args array are relative to each gateway. Stripe keys use the Payment Intent format, and PayPal keys use the Express Checkout format.

Note that when using the Payment Cart field, this step is fully automated. Payment data can still be customized using the very same hook if needed.

/*
 * Create Payment
 * 
 * @array   $args     Stripe Payment Intent or PayPal Express Checkout array
 * @array   $field    Field settings
 * @string  $gateway  Selected gateway 'stripe' or 'paypal'
 * @string  $post_id  Current Post ID
 */
filter('acfe/fields/payment/create',                         $args, $field, $gateway, $post_id);
filter('acfe/fields/payment/create/gateway=stripe',          $args, $field, $gateway, $post_id);
filter('acfe/fields/payment/create/name=my_field',           $args, $field, $gateway, $post_id);
filter('acfe/fields/payment/create/key=field_61395f18412c2', $args, $field, $gateway, $post_id);
add_filter('acfe/fields/payment/create/name=my_payment', 'my_create_payment', 10, 4);
function my_create_payment($args, $field, $gateway, $post_id){

    // retrieve field input value 'my_email'
    $email = get_field('my_email');
    
    // retrieve field input value 'my_checkbox'
    $checkbox = acf_get_array(get_field('my_checkbox'));
    
    // reset initial amount
    $amount = 0.00;
    
    // calculate amount based on 'my_checkbox' values
    if(in_array('item-1', $checkbox)){
        $amount += 9.99;
    }
    
    // calculate amount based on 'my_checkbox' values
    if(in_array('item-2', $checkbox)){
        $amount += 19.99;
    }
    
    // set calculated amount
    $args['amount'] = $amount;
    
    // set specific currency
    $args['currency'] = 'EUR';
    
    // add 'my_checkbox' values into the payment description
    $args['description'] = implode(', ', $checkbox);
    
    // stripe specific arguments
    if($gateway === 'stripe'){
        
        // add email into the Payment Intent metadata
        $args['metadata']['email'] = $email;
    
    // paypal specific arguments
    }elseif($gateway === 'paypal'){
        
        // add email into the PayPal payment description
        $args['description'] .= " Email:{$email}";
        
    }
    
    // return
    return $args;

}

Payment Object

When the payment has been confirmed by the server, a Payment Object is generated with additional information about the payment:

$object = array(
    'id'        => 'pi_1J9rNVDonAcsMN7hFbYu3j1S', // or PayPal ID: 54961843EX003522E
    'gateway'   => 'stripe', // stripe|paypal
    'amount'    => 19.99,
    'currency'  => 'USD',
    'items'     => array(),
    'date'      => 1631155804,
    'ip'        => '127.0.0.1',
    'mode'      => 'test', // test|prod
    'object'    => array(
        
        // Stripe Payment Intent:
        'id'                => 'pi_1J9rNVDonAcsMN7hFbYu3j1S',
        'object'            => 'payment_intent',
        'amount'            => 1999,
        'amount_capturable' => 0,
        'amount_received'   => 0,
        // ...
        
        // or PayPal Checkout Transaction:
        'TOKEN'         => 'EC-2WM09811G2700973X',
        'TIMESTAMP'     => '2021-09-09T02:59:16Z',
        'CORRELATIONID' => '443bb54f42c47',
        'ACK'           => 'Success',
        'VERSION'       => '121',
        // ...
        
    ),
);

It is possible to filter this object to add custom data if needed:

/*
 * Payment Object
 * 
 * @array   $object   Payment object array
 * @array   $field    Field settings
 * @string  $gateway  Selected gateway 'stripe' or 'paypal'
 * @string  $post_id  Current Post ID
 */
filter('acfe/fields/payment/object',                         $object, $field, $gateway, $post_id);
filter('acfe/fields/payment/object/gateway=stripe',          $object, $field, $gateway, $post_id);
filter('acfe/fields/payment/object/name=my_field',           $object, $field, $gateway, $post_id);
filter('acfe/fields/payment/object/key=field_61395f18412c2', $object, $field, $gateway, $post_id);
add_filter('acfe/fields/payment/object/name=my_payment', 'my_payment_object', 10, 4);
function my_payment_object($object, $field, $gateway, $post_id){
    
    // add items to payment object
    $object['items'] = array(
        array(
            'item' => 'Item 1',
            'amount' => 20.00
        ),
    );
    
    // add custom data
    $object['user_id'] = get_current_user_id();
    
    // return
    return $object;
    
}

Payment Success

Once the Payment Object is generated, the Payment Success action is triggered, allowing developers to add a custom action if needed:

/*
 * Payment Success
 * 
 * @array   $object   Payment object array
 * @array   $field    Field settings
 * @string  $gateway  Selected gateway 'stripe' or 'paypal'
 * @string  $post_id  Current Post ID
 */
action('acfe/fields/payment/success',                         $object, $field, $gateway, $post_id);
action('acfe/fields/payment/success/gateway=stripe',          $object, $field, $gateway, $post_id);
action('acfe/fields/payment/success/name=my_field',           $object, $field, $gateway, $post_id);
action('acfe/fields/payment/success/key=field_61395f18412c2', $object, $field, $gateway, $post_id);
<?php

add_action('acfe/fields/payment/success/name=my_payment', 'my_payment_success', 10, 4);
function my_payment_success($object, $field, $gateway, $post_id){
    
    // start buffer
    ob_start();
    ?>
    
    <p>Payment information:</p>
    <ul>
        <li>Amount: <?php echo $object['amount']; ?><?php echo $object['currency']; ?></li>
        <li>Date: <?php echo date_i18n('d/m/Y H:i:s', $object['date']); ?></li>
        <li>IP: <?php echo $object['ip']; ?></li>
    </ul>
    <p>Regards.</p>
    
    <?php
    
    // retrieve buffer
    $content = ob_get_clean();
    
    // send an e-mail on payment success
    wp_mail('[email protected]', 'New Payment', $content, array('Content-Type: text/html; charset=UTF-8'));

}

Stripe Javascript Hook

It is possible to change the arguments sent to the Stripe Card Element using the following Javascript filter:

/**
 * acfe/fields/payment/stripe_args
 * 
 * @object  args   Stripe arguments
 * @object  field  ACF Field instance
 */
filter('acfe/fields/payment/stripe_args',                         args, field);
filter('acfe/fields/payment/stripe_args/name=my_payment',         args, field);
filter('acfe/fields/payment/stripe_args/key=field_608abfa17fa7f', args, field);
acf.addFilter('acfe/fields/payment/stripe_args/name=my_payment', function(args, field){

    // hide the postal code field
    args.hidePostalCode = true;
    
    return args;

});

Field Value

If the field has been saved as a meta, then it can then be retrieved using the common get_field() function. Usage example:

$payment = get_field('payment');
 
/**
 * array(
 *     'id'        => 'pi_1J9rNVDonAcsMN7hFbYu3j1S',
 *     'gateway'   => 'stripe',
 *     'amount'    => 19.99,
 *     'currency'  => 'USD',
 *     'items'     => array(),
 *     'date'      => 1631155804,
 *     'ip'        => '127.0.0.1',
 *     'mode'      => 'test',
 *     'object'    => array(
 *         'id'                => 'pi_1J9rNVDonAcsMN7hFbYu3j1S',
 *         'object'            => 'payment_intent',
 *         'amount'            => 1999,
 *         'amount_capturable' => 0,
 *         'amount_received'   => 0,
 *         // ...
 *     ),
 * )
 */
$payment_id = get_field('payment_id');
 
// pi_1J9rNVDonAcsMN7hFbYu3j1S
$payment_amount = get_field('payment_amount');
 
// 19.99
$payment_ip = get_field('payment_ip');
 
// 127.0.0.1

If there is a Payment Object meta saved on the current post, the Payment Field will change its render and display the Payment Object as a readable summary instead of the Payment Form:

Field Group
Gateway: Stripe
Mode: Test
Amount: $19.99
Items: Product A
Date: 02/09/2021 05:21:32
IP Address: 127.0.0.1
Payment Object: View
Array
(
    [id] => pi_3JV6UXDonAcsMN7h1LhKXJy0
    [object] => payment_intent
    [amount] => 1999
    [amount_capturable] => 0
    [amount_received] => 1999
    [application] =>
    [application_fee_amount] =>
    [canceled_at] =>
    [cancellation_reason] =>
    [capture_method] => automatic
    [charges] => Array
        (
            [object] => list
            [data] => Array
                (
                    [0] => Array
                        (
                            [id] => ch_3JV6UXDonAcsMN7h1jzh2Awk
                            [object] => charge
                            [amount] => 1999
                            [amount_captured] => 1999
                            [amount_refunded] => 0
                            [application] =>
                            [application_fee] =>
                            [application_fee_amount] =>
                            [balance_transaction] => txn_3JV6UXDonAcsMN7h1XWuPbRX
                            [billing_details] => Array
                                (
                                    [address] => Array
                                        (
                                            [city] =>
                                            [country] =>
                                            [line1] =>
                                            [line2] =>
                                            [postal_code] => 22222
                                            [state] =>
                                        )

                                    [email] =>
                                    [name] =>
                                    [phone] =>
                                )

                            [calculated_statement_descriptor] => ACF EXTENDED
                            [captured] => 1
                            [created] => 1630552890
                            [currency] => usd
                            [customer] =>
                            [description] =>
                            [destination] =>
                            [dispute] =>
                            [disputed] =>
                            [failure_code] =>
                            [failure_message] =>
                            [fraud_details] => Array
                                (
                                )

                            [invoice] =>
                            [livemode] =>
                            [metadata] => Array
                                (
                                    [items] => Product A
                                )

                            [on_behalf_of] =>
                            [order] =>
                            [outcome] => Array
                                (
                                    [network_status] => approved_by_network
                                    [reason] =>
                                    [risk_level] => normal
                                    [risk_score] => 26
                                    [seller_message] => Payment complete.
                                    [type] => authorized
                                )

                            [paid] => 1
                            [payment_intent] => pi_3JV6UXDonAcsMN7h1LhKXJy0
                            [payment_method] => pm_1JV6UYDonAcsMN7hx2WJkClp
                            [payment_method_details] => Array
                                (
                                    [card] => Array
                                        (
                                            [brand] => visa
                                            [checks] => Array
                                                (
                                                    [address_line1_check] =>
                                                    [address_postal_code_check] => pass
                                                    [cvc_check] => pass
                                                )

                                            [country] => US
                                            [exp_month] => 2
                                            [exp_year] => 2022
                                            [fingerprint] => TYjcR0t9rkM8ipxZ
                                            [funding] => credit
                                            [installments] =>
                                            [last4] => 4242
                                            [network] => visa
                                            [three_d_secure] =>
                                            [wallet] =>
                                        )

                                    [type] => card
                                )

                            [receipt_email] =>
                            [receipt_number] =>
                            [receipt_url] => https://pay.stripe.com/receipts/acct_1HcYlfDonAcsMN7h/ch_3JV6UXDonAcsMN7h1jzh2Awk/rcpt_K9PJUPfJRWhKISfgl9GNsugJ6bk7NzV
                            [refunded] =>
                            [refunds] => Array
                                (
                                    [object] => list
                                    [data] => Array
                                        (
                                        )

                                    [has_more] =>
                                    [total_count] => 0
                                    [url] => /v1/charges/ch_3JV6UXDonAcsMN7h1jzh2Awk/refunds
                                )

                            [review] =>
                            [shipping] =>
                            [source] =>
                            [source_transfer] =>
                            [statement_descriptor] =>
                            [statement_descriptor_suffix] =>
                            [status] => succeeded
                            [transfer_data] =>
                            [transfer_group] =>
                        )

                )

            [has_more] =>
            [total_count] => 1
            [url] => /v1/charges?payment_intent=pi_3JV6UXDonAcsMN7h1LhKXJy0
        )

    [client_secret] => pi_3JV6UXDonAcsMN7h1LhKXJy0_secret_9WGn628gctZyog9ZaTx1fgOor
    [confirmation_method] => automatic
    [created] => 1630552889
    [currency] => usd
    [customer] =>
    [description] =>
    [invoice] =>
    [last_payment_error] =>
    [livemode] =>
    [metadata] => Array
        (
            [items] => Product A
        )

    [next_action] =>
    [on_behalf_of] =>
    [payment_method] => pm_1JV6UYDonAcsMN7hx2WJkClp
    [payment_method_options] => Array
        (
            [card] => Array
                (
                    [installments] =>
                    [network] =>
                    [request_three_d_secure] => automatic
                )

        )

    [payment_method_types] => Array
        (
            [0] => card
        )

    [receipt_email] =>
    [review] =>
    [setup_future_usage] =>
    [shipping] =>
    [source] =>
    [statement_descriptor] =>
    [statement_descriptor_suffix] =>
    [status] => succeeded
    [transfer_data] =>
    [transfer_group] =>
)