Formidable PayPal

Knowledge BaseExtend Formidable ProAdd Ons → Formidable PayPal

This plugin allows you to collect PayPal payments using Formidable Pro. You can send users and a payment amount 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 Set Up

  1. Download latest version:
    Please log in to download

    Note: Versions 2.0rc2+ require Formidable v1.6+. View the change log to see a complete list of changes made in each version.

  2. In your WordPress admin, go to “Plugins” → “Add New” and click the “Upload” link at the top of the page.
  3. Click the “Browse” button and select the zip file you just downloaded. Once the plugin is installed, click “Activate Plugin” or go to the “Plugins” page, find “Formidable Payment” and click “Activate”.
  4. Now that the plugin is activated, go to “Formidable” → “Global Settings” and click the “Payment” tab.
  5. 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.
  6. Go into edit the form you would like to use with PayPal. Click “Settings” → “Payment”.
  7. Check the box to Send users to PayPal after submitting this form.
  8. 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.
  9. Select an Amount Field from your form. This field should contain the payment amount that will be sent to Paypal.
  10. If you would like to send users to Paypal after form submission depending on a selection in the form, you will need to add Conditional Logic as shown above.
  11. Don’t forget to hit “Update” so these settings will be saved.

Set up Instant Payment Notifications

In order for your payments to get correctly marked as paid, you must configure your PayPal account to send payment notifications.

  1. Log into your PayPal account.
  2. Go to your “Profile” page and then “My Selling Tools”.
  3. Click the “Update” link next to “Instant Payment Notifications”.
  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.

Additional Customizations

These code examples can be added to your theme functions.php file or a new plugin. If you want to insert code into your theme functions.php, add it at the very end of the file, before the last ?> if there is one. If you plan to update your theme, be sure to put it in a new plugin so the code won’t be lost on update.

Automatically publish a post after payment.

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){ if(!$args['pay_vars']['completed']) return; //don't publish if the payment was not completed
if(!$args['entry']->post_id) return; //don't publish if not linked to a post
wp_update_post(array('ID' => $args['entry']->post_id, 'post_status' => 'publish'));

Set payment status field to complete after payment

If you would like a field in your form to indicate the payment status, add a drop-down or radio field with two options: Yes, and No. Set the Visibility to “Administrator”, and select “No” as the default value. Then, add this code to your theme functions.php or a new plugin to change the value to “Yes” when the payment is completed:

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

  $formIDToFieldID = array(
    6 => 92, // change 6 to the id of your form and 92 to your field id
    7 => 115 // change 7 to the id of your form and 115 to your field id

  global $frmdb, $wpdb;

  $entry_id = $vars['payment']->item_id;
  $form_id = $vars['entry']->form_id;

  if ( ! isset($formIDToFieldID[$form_id]) ) {
    return; // don't continue if this form is not one listed above

  $wpdb->update( $frmdb->entry_metas, array('meta_value' => 'Yes'), array(
    'item_id' => $entry_id, 'field_id' => $formIDToFieldID[$form_id]
  ) );

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;

Change return URL

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;

Use a different PayPal email

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 .= '&business='. urlencode( '' ); //insert the email address here
  return $paypal_url;

Use different currencies

add_action('frm_after_create_entry', 'change_my_return_url', 40, 2);
function change_my_return_url($entry_id, $form_id){
    //check if sending to PayPal
    if ( !$_POST || !isset($_POST['frm_payment']) || (is_admin() && !defined('DOING_AJAX')) ) {

    if($form_id == 18){ //change 18 to the ID of the form to override the currency
        add_filter('frm_paypal_settings', 'change_my_GBP_currency');
    }else if($form == 19){
        add_filter('frm_paypal_settings', 'change_my_USD_currency');

function change_my_GBP_currency($settings){
  $settings->currency = 'GBP';
  return $settings;

function change_my_USD_currency($settings){
  $settings->currency = 'USD';
  return $settings;

If the 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].

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>';