This plugin allows you to collect PayPal payments using Formidable Forms. You can send users and a total directly to PayPal after submitting a Formidable form. Your users do NOT need to have a Paypal account in order to pay with Paypal.

Download and install

  1. Download latest version of the PayPal Standard plugin
  2. In your WordPress admin, go to "Plugins" > "Add New" and click the "Upload Plugin" button at the top of the page.
  3. Upload the zip file you just downloaded in step one. Once the plugin is installed, click "Activate Plugin" or go to the "Plugins" page, find "Formidable Payment" and click "Activate".

Set up the Paypal add-on

Now that the PayPal plugin is activated you’ll need to set up Formidable Forms to integrate with your PayPal account. To do this follow these steps below.

Global settings

  1. Now that the plugin is activated, go to "Formidable" > "Global Settings" and click the "Paypal" tab.
  2. Insert your PayPal email address and update any other settings. For live sites, make sure the "PayPal" environment is set to "Live"; otherwise, users will be prompted to set up new PayPal accounts.
    PayPal Global Settings

Instant payment notifications

In order for your payments to get correctly marked as paid, you must configure your PayPal account to send payment notifications. Follow the directions below to set this up.

  1. Log into your PayPal account.
  2. Go to your "Profile and settings" page and then "My Selling Tools".
  3. Click the "Update" link next to "Instant Payment Notifications".
    PayPal IPN
  4. Edit and enter a notification URL. It doesn’t matter what URL you insert since Formidable PayPal will override it.
  5. Enable IPN Messages.
  6. Click Save.
    PayPal IPN Email

Using the testing mode

Before you can use the test mode, you'll need to create both a personal and business PayPal account at Be sure to setup the IPN on your sandbox business account as well. Use your sandbox business email in your form settings, and pay using your personal sandbox email when you run through test transactions.

Form settings

  1. Go into edit the form you would like to use with PayPal. Click on "Settings" > "Form Actions" > "PayPal".
    PayPal Icon
  2. Give your Paypal action a Label for easy reference. This label will only be seen on the back-end.
    PayPal Label
  3. Choose an Item Name that will appear on the PayPal page and on the PayPal receipt. You can either type in the product name if it is not changing or select a field from your form if it will change depending on your user's selection.
    PayPal Item Name
  4. Set an Amount for the payment. You can either select a field from your form (this field should contain the payment amount) or select "Set Amount" and insert a value in the box.
    PayPal Amount
  5. If this form will be used to collect Donations, select "Payments made in this form are donations".
    Paypal Donations
  6. If you do not want the user to receive Notifications until after the payment is received, check "Hold email notifications until payment is received".
    PayPal Notifications
  7. If you would like to conditionally send users to Paypal after form submission, you will need to add Conditional Logic.
    PayPal Conditional Logic
  8. Don’t forget to hit "Update" so these settings will be saved.

Additional customizations

These code examples can be added to a child theme's functions.php file or the Code Snippets plugin.

Add a currency

If you need to take a payment in a currency that is not included in the Paypal action's currency options, you may add a currency using the code below.

add_filter('frm_currencies', 'add_custom_currency');
function add_custom_currency( $currencies ) {
    $currencies['USD'] = array(
        'name' => __('U.S. Dollar', 'frmpp'),
        'symbol_left' => '$', 'symbol_right' => '', 'symbol_padding' =>  '',
        'thousand_separator' => ',', 'decimal_separator' => '.', 'decimals' => 2,

    return $currencies;

Automatically publish a post after payment.

Please Note: This feature is built into the PayPal Standard plugin. If you have a post status field in your form, you can set it to change after payment using the "After payment" settings section inside your form action.
If your entry is set up to create WordPress posts, you can prevent the post from being created until payment is successful:

add_action('frm_payment_paypal_ipn', 'publish_paid_post');
function publish_paid_post($args){
   return; //don't publish if the payment was not completed
   return; //don't publish if not linked to a post
wp_update_post(array('ID' => $args['entry']->post_id, 'post_status' => 'publish'));

Change the user role after payment

The only change needed in the example is the user role the user should have: $new_role = 'contributor';

add_action('frm_payment_paypal_ipn', 'change_paid_user_role');

function change_paid_user_role($args){
    $new_role = 'contributor'; //change this to the role paid users should have
       return; //don't continue if the payment was not completed

    if(!$args['entry']->user_id or !is_numeric($args['entry']->user_id))
       return; //don't continue if not linked to a user

    $user = get_userdata($args['entry']->user_id);
        return; //don't continue if user doesn't exist

    $updated_user = (array)$user;

    // Get the highest/primary role for this user  
    $user_roles = $user->roles;
    $user_role = array_shift($user_roles);
    if ( $user_role == 'administrator' ) 
        return; //make sure we don't downgrade any admins

    $updated_user['role'] = $new_role;

Save transaction ID in field

If you would like to save the transaction ID in a field after the payment is complete, you may use the code below. You can add it to a child theme's functions.php file or the Code Snippets plugin. Replace 10 with the ID of your form and replace 123 with the ID of the field that will store the transaction ID. Make sure the field is blank by default or you will get extra data added to your database when this code is triggered.

add_action('frm_payment_paypal_ipn', 'save_frmpaypal_transaction_id');
function save_frmpaypal_transaction_id( $vars ){

    if ( ! $vars['pay_vars']['completed'] ) {
        return; //don't change value if the payment was not completed

    if ( $vars['entry']->form_id == 10 ) {
        $field_id = 123;
        $transaction_id = $vars['pay_vars']['receipt_id'];
        if ( $transaction_id ) {
            FrmEntryMeta::add_entry_meta( $vars['entry']->id, $field_id, null, $transaction_id );

Change return URL

Please Note: The Return URL option has been added to the PayPal action since version 3.0.

add_filter('formidable_paypal_url', 'formidable_paypal_url', 10, 3);
function formidable_paypal_url($paypal_url, $entry_id, $form_id){
  if($form_id == 5) //change 5 to the ID of your form
    $paypal_url .= '&return='. urlencode('');
  return $paypal_url;

If the one-time payment fails the first time, you can generate a link to allow users to pay again without filling out the form a second time. This shortcode can be used in a number of different ways, but the most likely would be in a view where you can add filters like "User ID is equal to current user", and the shortcode would be [pay_again id=[id]]. You can also set a specific entry id here if you would like [pay_again id=60].

Note: This isn't setup to work with recurring payments.

add_shortcode('pay_again', 'pay_frm_again');
function pay_frm_again($atts) {
    if ( ! class_exists('FrmPaymentsController') ) {
    $atts = shortcode_atts(array('id' => '', 'form_id' => ''), $atts);
    $entry_id = $atts['id'];
    $entry = FrmEntry::getOne($entry_id, true);
    if ( empty($atts['form_id']) ) {
      $atts['form_id'] = $entry->form_id;

    $form = FrmForm::getOne($atts['form_id']);
    global $frm_pay_form_settings;
    if ( empty($frm_pay_form_settings) ) {
        $frm_pay_form_settings = $form->options;
        if ( ( ! isset($form->options['paypal']) || empty($form->options['paypal']) ) && class_exists('FrmFormActionsHelper') ) {
            // get the 2.0 form action settings
            $action_control = FrmFormActionsHelper::get_action_for_form($form->id, 'paypal', 1);
            if ( ! $action_control ) {
            $frm_pay_form_settings = $action_control->post_content;
            $frm_pay_form_settings['paypal'] = 1;

    $amount_field = isset($frm_pay_form_settings['paypal_amount_field']) ? $frm_pay_form_settings['paypal_amount_field'] : '';
    $_POST['item_meta'][$amount_field] = $entry->metas[$amount_field]; // set the POST for the amount
    $amount = FrmPaymentsController::get_amount($form, $frm_pay_form_settings);
    if ( empty($amount) ) {

    global $wpdb;
    $invoice = $wpdb->get_var($wpdb->prepare('SELECT id FROM '. $wpdb->prefix .'frm_payments WHERE item_id=%d AND amount=%s AND paysys=%s', $entry_id, (float) $amount, 'paypal'));
    if ( ! $invoice ) {

    $frm_payment_settings = new FrmPaymentSettings();

    $paypal_url = '';
    $paypal_url .= '?cmd='. (( isset($frm_pay_form_settings['paypal_type']) && ! empty($frm_pay_form_settings['paypal_type']) ) ? $frm_pay_form_settings['paypal_type'] : '_xclick');
    $paypal_url .= '&notify_url='. FrmPaymentsHelper::format_for_url(admin_url('admin-ajax.php') . "?action=frm_payments_paypal_ipn");
    $paypal_url .= '&business='. FrmPaymentsHelper::format_for_url($frm_payment_settings->settings->business_email);
    $paypal_url .= '&currency_code='. FrmPaymentsHelper::format_for_url($frm_payment_settings->settings->currency);
    $paypal_url .= '&return='. FrmPaymentsHelper::format_for_url($frm_payment_settings->settings->return_url); 
    $paypal_url .= '&cancel_return='. FrmPaymentsHelper::format_for_url($frm_payment_settings->settings->cancel_url); 
    $paypal_url .= '&invoice='. FrmPaymentsHelper::format_for_url($invoice .'-'. FrmPaymentsHelper::get_rand(3));
    $paypal_url .= '&custom='. $entry_id.'|'. wp_hash($entry_id);
    $paypal_url .= '&amount='. urlencode($amount);
    if ( defined('ICL_LANGUAGE_CODE') ) {
      $paypal_url .= '&lc='. FrmPaymentsHelper::format_for_url(ICL_LANGUAGE_CODE);
    $item_name = apply_filters('frm_content', $frm_pay_form_settings['paypal_item_name'], $form, $entry_id);
    $paypal_url .= "&item_name=". urlencode($item_name);

    return '<a href="'. $paypal_url .'">Pay Now</a>';