Display a Payment Field that supports with Stripe & PayPal Express gateways, working on both front-end and back-end.
Setting name | Description |
Gateways | Choose the payment gateways to display and their order |
Amount | The default amount to charge |
Currency | The currency to use |
Description | A description attached to the payment. Useful for displaying to users |
Display Button | Whenever to display an inline “Pay Now” button or not |
Button Value | Set a default button value |
Button Attributes | Add class and id attributes to the button |
Before Button HTML | Add cutom HTML before the button render |
After Button HTML | Add custom HTML after the button render |
Stripe Hide Postal Code | Hide Stripe’s postal code field validation which can be displayed in specific cases |
Stripe Test API | Set the Stripe Secret & Public Keys. Available in your Stripe Test Dashboard |
Stripe Production API | Set the Stripe Secret & Public Keys. Available in your Stripe Production Dashboard |
PayPal Test API | Set the PayPal Sandbox Credentials. Available in your PayPal Sandbox Dashboard |
PayPal Production API | Set the PayPal Sandbox Credentials. Available in your PayPal Production Dashboard |
Mode | Switch API mode between Test & Production |
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 Name | Format |
Secret Key | sk_xxxxxxxxxxxxxxxxxxxxxx |
Public Key | pk_xxxxxxxxxxxxxxxxxxxxxx |
The “Test” keys are available in the same dashboard, when switching the mode to test on the top right corner.
The PayPal gateway requires a PayPal Business account. Four keys must be set: API Username, API Password, API Signature and PayPal Merchant ID.
Key Name | Format |
API Username | xxxxxxxxx.domain.com |
API Password | xxxxxxxxxxxxxxxxxxxx |
API Signature | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx |
Merchant ID | xxxxxxxxxxxxx |
To generate your API Username, API Password and API Signature, follow this instruction:
To retrieve your Merchant ID, follow this instruction:
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.
The payment flow of both gateways is pretty straight forward and have been unified for the sake of simplicity:
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;
}
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;
}
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'));
}
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;
});
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: