Current File : /home/itiffy/www/blog/wp-content/plugins/wp-invoice/lib/gateways/class_wpi_stripe.php
<?php

/**
  Name: Stripe
  Class: wpi_stripe
  Internal Slug: wpi_stripe
  JS Slug: wpi_stripe
  Version: 1.0
  Description: Provides Stripe gateway
 */
class wpi_stripe extends wpi_gateway_base {

  /**
   * Construct
   */
  function __construct() {
    parent::__construct();

    //** Fields for front-end. */
    $this->front_end_fields = array(
        'customer_information' => array(
            'first_name' => array(
                'type' => 'text',
                'class' => 'text-input',
                'name' => 'first_name',
                'label' => __('First Name', ud_get_wp_invoice()->domain)
            ),
            'last_name' => array(
                'type' => 'text',
                'class' => 'text-input',
                'name' => 'last_name',
                'label' => __('Last Name', ud_get_wp_invoice()->domain)
            ),
            'user_email' => array(
                'type' => 'text',
                'class' => 'text-input',
                'name' => 'email_address',
                'label' => __('Email Address', ud_get_wp_invoice()->domain)
            ),
            'phonenumber' => array(
                'type' => 'text',
                'class' => 'text-input',
                'name' => 'phonenumber',
                'label' => __('Phone', ud_get_wp_invoice()->domain)
            ),
            'streetaddress' => array(
                'type' => 'text',
                'class' => 'text-input',
                'name' => 'address1',
                'label' => __('Address', ud_get_wp_invoice()->domain)
            ),
            'city' => array(
                'type' => 'text',
                'class' => 'text-input',
                'name' => 'city',
                'label' => __('City', ud_get_wp_invoice()->domain)
            ),
            'country' => array(
                'type' => 'text',
                'class' => 'text-input',
                'name' => 'country',
                'label' => __('Country', ud_get_wp_invoice()->domain)
            ),
            'state' => array(
                'type' => 'text',
                'class' => 'text-input',
                'name' => 'state',
                'label' => __('State/Province', ud_get_wp_invoice()->domain)
            ),
            'zip' => array(
                'type' => 'text',
                'class' => 'text-input',
                'name' => 'zip',
                'label' => __('Zip/Postal Code', ud_get_wp_invoice()->domain)
            )
        )
    );

    $this->options = array(
        'name' => 'Stripe',
        'allow' => '',
        'default_option' => '',
        'settings' => array(
            'test_secret_key' => array(
                'label' => __( "Test Secret Key", ud_get_wp_invoice()->domain ),
                'value' => ''
            ),
            'test_publishable_key' => array(
                'label' => __( "Test Publishable Key", ud_get_wp_invoice()->domain ),
                'value' => ''
            ),
            'live_secret_key' => array(
                'label' => __( "Live Secret Key", ud_get_wp_invoice()->domain ),
                'value' => ''
            ),
            'live_publishable_key' => array(
                'label' => __( "Live Publishable Key", ud_get_wp_invoice()->domain ),
                'value' => ''
            ),
            'mode' => array(
                'label' => __("Mode", ud_get_wp_invoice()->domain),
                'description' => "Stripe payment mode",
                'type' => 'select',
                'value' => 'test',
                'data' => array(
                    'test' => "Test",
                    'live' => "Live"
                )
            ),
            'webhook_url' => array(
                'label' => __( "Webhook URL", ud_get_wp_invoice()->domain ),
                'type' => "readonly",
                'value' => admin_url('admin-ajax.php?action=wpi_gateway_server_callback&type=wpi_stripe'),
                'description' => __( "Use webhooks to be notified about events that happen in your Stripe account.", ud_get_wp_invoice()->domain )
            )
        )
    );

  }

  /**
   * Settings for recurring billing
   * @param type $this_invoice
   */
  function recurring_settings($this_invoice) {
      ?>
      <h4><?php _e('Stripe Subscriptions', ud_get_wp_invoice()->domain); ?></h4>
      <table class="wpi_recurring_bill_settings">
          <tr>
              <th style="cursor:help;" title="<?php _e('Specifies billing frequency.', ud_get_wp_invoice()->domain); ?>"><?php _e('Interval', ud_get_wp_invoice()->domain); ?></th>
              <td>
                  <?php echo WPI_UI::select("name=wpi_invoice[recurring][".$this->type."][interval]&values=" . serialize(apply_filters('wpi_stripe_interval', array("week" => __("Week", ud_get_wp_invoice()->domain), "month" => __("Month", ud_get_wp_invoice()->domain), "year" => __("Year", ud_get_wp_invoice()->domain)))) . "&current_value=" . (!empty($this_invoice['recurring'][$this->type]) ? $this_invoice['recurring'][$this->type]['interval'] : '')); ?>
              </td>
          </tr>

          <tr>
              <th style="cursor:help;" title="<?php _e('The number of the unit specified in the interval parameter. For example, you could specify an interval_count of 3 and an interval of "month" for quarterly billing (every 3 months).', ud_get_wp_invoice()->domain); ?>"><?php _e('Interval Count', ud_get_wp_invoice()->domain); ?></th>
              <td>
                  <?php echo WPI_UI::input("id=stripe_interval_count&name=wpi_invoice[recurring][".$this->type."][interval_count]&value=" . (!empty($this_invoice['recurring'][$this->type]) ? $this_invoice['recurring'][$this->type]['interval_count'] : '') . "&special=size='2' maxlength='4' autocomplete='off'"); ?>
              </td>
          </tr>
      </table>
      <?php
  }

  /**
   * Fields renderer for STRIPE
   * @param type $invoice
   */
  function wpi_payment_fields($invoice) {

    $this->front_end_fields = apply_filters('wpi_crm_custom_fields', $this->front_end_fields, 'crm_data');

    if (!empty($this->front_end_fields)) {
      //** For each section */
      foreach ($this->front_end_fields as $key => $value) {
        //** If section is not empty */
        if (!empty($this->front_end_fields[$key])) {
          $html = '';
          ob_start();
          ?>
          <ul class="wpi_checkout_block">
            <li class="section_title"><?php _e(ucwords(str_replace('_', ' ', $key)), ud_get_wp_invoice()->domain); ?></li>
            <?php
            $html = ob_get_clean();
            echo $html;
            //** For each field */
            foreach ($value as $field_slug => $field_data) {
              //** Change field properties if we need */
              $field_data = apply_filters('wpi_payment_form_styles', $field_data, $field_slug, 'wpi_stripe');
              $html = '';

              ob_start();

              switch ($field_data['type']) {
                case self::TEXT_INPUT_TYPE:
                  ?>

                  <li class="wpi_checkout_row">
                    <div class="control-group">
                      <label class="control-label" for="<?php echo esc_attr($field_slug); ?>"><?php _e($field_data['label'], ud_get_wp_invoice()->domain); ?></label>
                      <div class="controls">
                        <input type="<?php echo esc_attr($field_data['type']); ?>" class="<?php echo esc_attr($field_data['class']); ?>"  name="<?php echo esc_attr($field_data['name']); ?>" value="<?php echo isset($field_data['value'])?$field_data['value']:(!empty($invoice['user_data'][$field_slug])?$invoice['user_data'][$field_slug]:'');?>" />
                      </div>
                    </div>
                  </li>

                  <?php
                  $html = ob_get_clean();

                  break;

                case self::SELECT_INPUT_TYPE:
                  ?>

                  <li class="wpi_checkout_row">
                    <label for="<?php echo esc_attr($field_slug); ?>"><?php _e($field_data['label'], ud_get_wp_invoice()->domain); ?></label>
                    <?php echo WPI_UI::select("name={$field_data['name']}&values={$field_data['values']}&id={$field_slug}&class={$field_data['class']}"); ?>
                  </li>

                  <?php
                  $html = ob_get_clean();

                  break;

                case self::RECAPTCHA_INPUT_TYPE:
                  $this->display_recaptcha($field_data);
                  
                  break;

                default:
                  break;
              }

              echo $html;
            }
            echo '</ul>';
          }
        }
      }
    }

    /**
     * Process STRIPE payment
     * @global type $invoice
     */
    static function process_payment() {
      global $invoice;

      //** Response */
      $response = array(
        'success' => false,
        'error' => false,
        'data' => null
      );
      
      $data = array();

      if (isset($_POST['stripeToken'])) {
        $token = $_POST['stripeToken'];
      } else {
        $response['error'] = true;
        $data['messages'][] = __('The order cannot be processed. You have not been charged. Please confirm that you have JavaScript enabled and try again.', ud_get_wp_invoice()->domain);

        $response['data'] = $data;
        die(json_encode($response));
      }

      try {

        if ( !class_exists('Stripe') ) {
          require_once( ud_get_wp_invoice()->path( "lib/third-party/stripe/lib/Stripe.php", 'dir' ) );
        }
        $pk = trim($invoice['billing']['wpi_stripe']['settings'][$invoice['billing']['wpi_stripe']['settings']['mode']['value'].'_secret_key']['value']);

        Stripe::setApiKey($pk);

        switch( $invoice['type'] == 'recurring' ) {

          //** If recurring */
          case true:

            $plan = Stripe_Plan::create(array(
              "amount" => (float)$invoice['net']*100,
              "interval" => $invoice['recurring']['wpi_stripe']['interval'],
              "interval_count" => $invoice['recurring']['wpi_stripe']['interval_count'],
              "name" => $invoice['post_title'],
              "currency" => strtolower($invoice['default_currency_code']),
              "id" => $invoice['invoice_id'])
            );

            $customer = Stripe_Customer::create(array(
              "card" => $token,
              "plan" => $invoice['invoice_id'],
              "email" => $invoice['user_email'])
            );

            if ( !empty( $plan->id ) && !empty( $plan->amount ) && !empty( $customer->id ) ) {

              $invoice_obj = new WPI_Invoice();
              $invoice_obj->load_invoice("id={$invoice['invoice_id']}");
              $log = sprintf( __( "Subscription has been initiated. Plan: %s, Customer: %s", ud_get_wp_invoice()->domain ), $plan->id, $customer->id );
              $invoice_obj->add_entry("attribute=invoice&note=$log&type=update");
              $invoice_obj->save_invoice();

              send_notification( $invoice );
              update_post_meta( wpi_invoice_id_to_post_id( $invoice['invoice_id'] ), '_stripe_customer_id', $customer->id );

              $data['messages'][] = __( 'Stripe Subscription has been initiated. Do not pay this invoice again. Thank you.', ud_get_wp_invoice()->domain );
              $response['success'] = true;
              $response['error'] = false;
            } else {

              $data['messages'][] = __( 'Could not initiate Stripe Subscription. Contact site Administrator please.', ud_get_wp_invoice()->domain );
              $response['success'] = false;
              $response['error'] = true;
            }

            break;

          //** If regular payment */
          case false:

            //** Support partial payments */
            if ($invoice['deposit_amount'] > 0) {
              $amount = (float) $_REQUEST['amount'];
              if (((float) $_REQUEST['amount']) > $invoice['net']) {
                $amount = $invoice['net'];
              }
              if (((float) $_REQUEST['amount']) < $invoice['deposit_amount']) {
                $amount = $invoice['deposit_amount'];
              }
            } else {
              $amount = $invoice['net'];
            }

            $charge = Stripe_Charge::create(array(
              "amount" => (float)$amount*100,
              "currency" => strtolower( $invoice['default_currency_code'] ),
              "card" => $token,
              "description" => $invoice['invoice_id'].' ['.$invoice['post_title'].' / '.get_bloginfo('url').' / '.$invoice['user_email'].']'
            ));

            if ( $charge->paid ) {

              $invoice_id  = $invoice['invoice_id'];
              $wp_users_id = $invoice['user_data']['ID'];

              //** update user data */
              update_user_meta($wp_users_id, 'last_name', !empty($_REQUEST['last_name'])?$_REQUEST['last_name']:'' );
              update_user_meta($wp_users_id, 'first_name', !empty($_REQUEST['first_name'])?$_REQUEST['first_name']:'' );
              update_user_meta($wp_users_id, 'city', !empty($_REQUEST['city'])?$_REQUEST['city']:'' );
              update_user_meta($wp_users_id, 'state', !empty($_REQUEST['state'])?$_REQUEST['state']:'' );
              update_user_meta($wp_users_id, 'zip', !empty($_REQUEST['zip'])?$_REQUEST['zip']:'' );
              update_user_meta($wp_users_id, 'streetaddress', !empty($_REQUEST['address1'])?$_REQUEST['address1']:'' );
              update_user_meta($wp_users_id, 'phonenumber', !empty($_REQUEST['phonenumber'])?$_REQUEST['phonenumber']:'' );
              update_user_meta($wp_users_id, 'country', !empty($_REQUEST['country'])?$_REQUEST['country']:'' );

              if ( !empty( $_REQUEST['crm_data'] ) ) {
                self::user_meta_updated( $_REQUEST['crm_data'] );
              }

              $invoice_obj = new WPI_Invoice();
              $invoice_obj->load_invoice("id={$invoice['invoice_id']}");

              $amount = (float)($charge->amount/100);
              //** Add payment amount */
              $event_note = WPI_Functions::currency_format((float)$amount, $invoice['invoice_id']) . __(" paid via STRIPE", ud_get_wp_invoice()->domain);
              $event_amount = $amount;
              $event_type = 'add_payment';

              $event_note = urlencode($event_note);
              //** Log balance changes */
              $invoice_obj->add_entry("attribute=balance&note=$event_note&amount=$event_amount&type=$event_type");
              //** Log client IP */
              $success = __("Successfully processed by ", ud_get_wp_invoice()->domain).$_SERVER['REMOTE_ADDR'];
              $invoice_obj->add_entry("attribute=invoice&note=$success&type=update");
              //** Log payer */
              $payer_card = __("STRIPE Card ID: ", ud_get_wp_invoice()->domain).$charge->source->id;
              $invoice_obj->add_entry("attribute=invoice&note=$payer_card&type=update");

              $invoice_obj->save_invoice();
              //** Mark invoice as paid */
              wp_invoice_mark_as_paid($invoice_id, $check = true);
              parent::successful_payment( $invoice_obj );
              parent::successful_payment_webhook( $invoice_obj );
              send_notification( $invoice );

              $data['messages'][] = __( 'Successfully paid. Thank you.', ud_get_wp_invoice()->domain );
              $response['success'] = true;
              $response['error'] = false;
            } else {
              $data['messages'][] = $charge->failure_message;
              $response['success'] = false;
              $response['error'] = true;
            }

            break;

          //** Other cases */
          default: break;
        }

        $response['data'] = $data;
        die(json_encode($response));

      } catch (Stripe_CardError $e) {

        $e_json = $e->getJsonBody();
        $err = $e_json['error'];
        $response['error'] = true;
        $data['messages'][] = $err['message'];
      } catch (Stripe_ApiConnectionError $e) {

        $response['error'] = true;
        $data['messages'][] = __( 'Service is currently unavailable. Please try again later.', ud_get_wp_invoice()->domain );
      } catch (Stripe_InvalidRequestError $e) {

        $response['error'] = true;
        $data['messages'][] = $e->getMessage();
      } catch (Stripe_ApiError $e) {

        $response['error'] = true;
        $data['messages'][] = __( 'Stripe server is down! Try again later.', ud_get_wp_invoice()->domain );
      } catch (Exception $e) {

        $response['error'] = true;
        $data['messages'][] = $e->getMessage();
      }

      $response['data'] = $data;
      die(json_encode($response));
    }

    /**
     *
     */
    static function server_callback() {
      global $wpdb;

      //** Get request body */
      $body = @file_get_contents('php://input');
      $event_object = json_decode($body);

      switch ($event_object->type) {

        //** Used only for subscriptions since single payments processed without Webhook */
        case 'charge.succeeded':

          $post_id = $wpdb->get_col("SELECT post_id
          FROM {$wpdb->postmeta}
          WHERE meta_key = '_stripe_customer_id'
            AND meta_value = '{$event_object->data->object->customer}'");

          $invoice_object = new WPI_Invoice();
          $invoice_object->load_invoice("id=" . $post_id[0]);

          if (empty($invoice_object->data['ID'])) {
            die("Can't load invoice");
          }

          if ( !class_exists('Stripe') ) {
            require_once( ud_get_wp_invoice()->path( "lib/third-party/stripe/lib/Stripe.php", 'dir' ) );
          }
          $pk = trim($invoice_object->data['billing']['wpi_stripe']['settings'][$invoice_object->data['billing']['wpi_stripe']['settings']['mode']['value'] . '_secret_key']['value']);

          Stripe::setApiKey($pk);

          $event = Stripe_Event::retrieve($event_object->id);


          if ($event->data->object->paid == 1) {
            $event_amount = (float) ($event->data->object->amount / 100);
            $event_note = WPI_Functions::currency_format(abs($event_amount), $invoice_object->data['invoice_id']) . ' ' . __('Stripe Subscription Payment', ud_get_wp_invoice()->domain);
            $event_type = 'add_payment';

            $invoice_object->add_entry("attribute=balance&note=$event_note&amount=$event_amount&type=$event_type");
            $invoice_object->save_invoice();
          }
          break;

        case 'customer.subscription.deleted':

          $post_id = $wpdb->get_col("SELECT post_id
          FROM {$wpdb->postmeta}
          WHERE meta_key = '_stripe_customer_id'
            AND meta_value = '{$event_object->data->object->customer}'");

          $invoice_object = new WPI_Invoice();
          $invoice_object->load_invoice("id=" . $post_id[0]);

          if (empty($invoice_object->data['ID'])) {
            die("Can't load invoice");
          }

          if ( !class_exists('Stripe') ) {
            require_once( ud_get_wp_invoice()->path( "lib/third-party/stripe/lib/Stripe.php", 'dir' ) );
          }
          $pk = trim($invoice_object->data['billing']['wpi_stripe']['settings'][$invoice_object->data['billing']['wpi_stripe']['settings']['mode']['value'] . '_secret_key']['value']);

          Stripe::setApiKey($pk);

          $event = Stripe_Event::retrieve($event_object->id);

          if ( $event->data->object->status == 'canceled' ) {
            $invoice_object->add_entry("attribute=invoice&note=".__('Stripe Subscription has been canceled', ud_get_wp_invoice()->domain)."&type=update");
            $invoice_object->save_invoice();
            wp_invoice_mark_as_paid($invoice_object->data['invoice_id']);
          }

          break;

        default: break;
      }

    }

  }