woocommerce/classes/gateways/gateway-paypal.php

424 lines
14 KiB
PHP
Raw Normal View History

2011-08-09 15:16:18 +00:00
<?php
/**
2011-08-10 17:11:11 +00:00
* PayPal Standard Payment Gateway
*
* Provides a PayPal Standard Payment Gateway.
*
2011-11-04 10:35:02 +00:00
* @class woocommerce_paypal
2011-08-10 17:11:11 +00:00
* @package WooCommerce
* @category Payment Gateways
* @author WooThemes
*/
class woocommerce_paypal extends woocommerce_payment_gateway {
2011-08-09 15:16:18 +00:00
public function __construct() {
global $woocommerce;
2011-08-09 15:16:18 +00:00
$this->id = 'paypal';
2011-11-03 09:34:53 +00:00
$this->icon = apply_filters('woocommerce_paypal_icon', $woocommerce->plugin_url() . '/assets/images/icons/paypal.png');
2011-08-09 15:16:18 +00:00
$this->has_fields = false;
$this->liveurl = 'https://www.paypal.com/webscr';
2011-08-09 15:16:18 +00:00
$this->testurl = 'https://www.sandbox.paypal.com/webscr';
// Load the form fields.
$this->init_form_fields();
// Load the settings.
$this->init_settings();
2011-08-09 15:16:18 +00:00
// Define user set variables
$this->title = $this->settings['title'];
$this->description = $this->settings['description'];
$this->email = $this->settings['email'];
$this->testmode = $this->settings['testmode'];
$this->send_shipping = $this->settings['send_shipping'];
$this->debug = $this->settings['debug'];
2011-08-09 15:16:18 +00:00
// Actions
2011-08-09 15:16:18 +00:00
add_action( 'init', array(&$this, 'check_ipn_response') );
add_action('valid-paypal-standard-ipn-request', array(&$this, 'successful_request') );
add_action('woocommerce_receipt_paypal', array(&$this, 'receipt_page'));
add_action('woocommerce_update_options_payment_gateways', array(&$this, 'process_admin_options'));
2011-08-09 15:16:18 +00:00
}
/**
* Initialise Gateway Settings Form Fields
*/
function init_form_fields() {
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable/Disable', 'woothemes' ),
'type' => 'checkbox',
'label' => __( 'Enable PayPal standard', 'woothemes' ),
'default' => 'yes'
),
'title' => array(
'title' => __( 'Title', 'woothemes' ),
'type' => 'text',
'description' => __( 'This controls the title which the user sees during checkout.', 'woothemes' ),
'default' => __( 'PayPal', 'woothemes' )
),
'description' => array(
'title' => __( 'Description', 'woothemes' ),
'type' => 'textarea',
'description' => __( 'This controls the description which the user sees during checkout.', 'woothemes' ),
'default' => __("Pay via PayPal; you can pay with your credit card if you don't have a PayPal account", 'woothemes')
),
'email' => array(
'title' => __( 'PayPal Email', 'woothemes' ),
'type' => 'text',
'description' => __( 'Please enter your PayPal email address; this is needed in order to take payment.', 'woothemes' ),
'default' => ''
),
'send_shipping' => array(
'title' => __( 'Shipping details', 'woothemes' ),
'type' => 'checkbox',
'label' => __( 'Send shipping details to PayPal', 'woothemes' ),
'default' => 'no'
),
'testmode' => array(
'title' => __( 'PayPal sandbox', 'woothemes' ),
'type' => 'checkbox',
'label' => __( 'Enable PayPal sandbox', 'woothemes' ),
'default' => 'yes'
),
'debug' => array(
'title' => __( 'Debug', 'woothemes' ),
'type' => 'checkbox',
'label' => __( 'Enable logging (<code>woocommerce/logs/paypal.txt</code>)', 'woothemes' ),
'default' => 'no'
)
);
} // End init_form_fields()
/**
2011-08-09 15:16:18 +00:00
* Admin Panel Options
* - Options for bits like 'title' and availability on a country-by-country basis
*
* @since 1.0.0
*/
2011-08-09 15:16:18 +00:00
public function admin_options() {
2011-08-09 15:16:18 +00:00
?>
2011-08-13 16:07:10 +00:00
<h3><?php _e('PayPal standard', 'woothemes'); ?></h3>
<p><?php _e('PayPal standard works by sending the user to PayPal to enter their payment information.', 'woothemes'); ?></p>
2011-08-13 16:07:10 +00:00
<table class="form-table">
2011-08-09 15:16:18 +00:00
<?php
// Generate the HTML For the settings form.
$this->generate_settings_html();
?>
</table><!--/.form-table-->
<?php
} // End admin_options()
2011-08-09 15:16:18 +00:00
/**
* There are no payment fields for paypal, but we want to show the description if set.
**/
function payment_fields() {
if ($this->description) echo wpautop(wptexturize($this->description));
2011-08-09 15:16:18 +00:00
}
/**
* Generate the paypal button link
**/
public function generate_paypal_form( $order_id ) {
global $woocommerce;
2011-08-09 15:16:18 +00:00
2011-08-10 17:11:11 +00:00
$order = &new woocommerce_order( $order_id );
2011-08-09 15:16:18 +00:00
if ( $this->testmode == 'yes' ):
$paypal_adr = $this->testurl . '?test_ipn=1&';
else :
$paypal_adr = $this->liveurl . '?';
endif;
2011-11-18 12:36:02 +00:00
if ($this->debug=='yes') $woocommerce->log->add( 'paypal', 'Generating payment form for order #' . $order_id . '. Notify URL: ' . trailingslashit(home_url()).'?paypalListener=paypal_standard_IPN');
2011-11-18 12:32:59 +00:00
2011-08-09 15:16:18 +00:00
$shipping_name = explode(' ', $order->shipping_method);
if (in_array($order->billing_country, array('US','CA'))) :
2011-09-28 08:35:51 +00:00
$order->billing_phone = str_replace(array('(', '-', ' ', ')'), '', $order->billing_phone);
2011-08-09 15:16:18 +00:00
$phone_args = array(
'night_phone_a' => substr($order->billing_phone,0,3),
2011-09-28 08:35:51 +00:00
'night_phone_b' => substr($order->billing_phone,3,3),
'night_phone_c' => substr($order->billing_phone,6,4),
2011-08-09 15:16:18 +00:00
'day_phone_a' => substr($order->billing_phone,0,3),
2011-09-28 08:35:51 +00:00
'day_phone_b' => substr($order->billing_phone,3,3),
'day_phone_c' => substr($order->billing_phone,6,4)
2011-08-09 15:16:18 +00:00
);
else :
$phone_args = array(
'night_phone_b' => $order->billing_phone,
'day_phone_b' => $order->billing_phone
);
endif;
$paypal_args = array_merge(
array(
'cmd' => '_cart',
'business' => $this->email,
'no_note' => 1,
2011-08-10 17:11:11 +00:00
'currency_code' => get_option('woocommerce_currency'),
2011-08-09 15:16:18 +00:00
'charset' => 'UTF-8',
'rm' => 2,
'upload' => 1,
'return' => $this->get_return_url( $order ),
2011-08-09 15:16:18 +00:00
'cancel_return' => $order->get_cancel_order_url(),
// Order key
'custom' => $order_id,
// IPN
2011-11-18 12:36:02 +00:00
'notify_url' => trailingslashit(home_url()).'?paypalListener=paypal_standard_IPN',
2011-08-09 15:16:18 +00:00
// Address info
'first_name' => $order->billing_first_name,
'last_name' => $order->billing_last_name,
'company' => $order->billing_company,
'address1' => $order->billing_address_1,
'address2' => $order->billing_address_2,
'city' => $order->billing_city,
'state' => $order->billing_state,
'zip' => $order->billing_postcode,
'country' => $order->billing_country,
'email' => $order->billing_email,
// Payment Info
'invoice' => $order->order_key,
'tax_cart' => $order->get_total_tax(),
'discount_amount_cart' => $order->get_total_discount()
2011-08-09 15:16:18 +00:00
),
$phone_args
);
if ($this->send_shipping=='yes') :
$paypal_args['no_shipping'] = 0;
$paypal_args['address_override'] = 1;
else :
$paypal_args['no_shipping'] = 1;
endif;
// Cart Contents
$item_loop = 0;
if (sizeof($order->items)>0) : foreach ($order->items as $item) :
if ($item['qty']) :
2011-08-09 15:16:18 +00:00
$item_loop++;
2011-09-28 09:25:51 +00:00
$item_name = $item['name'];
2011-11-06 15:45:22 +00:00
$item_meta = &new order_item_meta( $item['item_meta'] );
if ($meta = $item_meta->display( true, true )) :
$item_name .= ' ('.$meta.')';
2011-09-28 09:25:51 +00:00
endif;
$paypal_args['item_name_'.$item_loop] = $item_name;
2011-08-09 15:16:18 +00:00
$paypal_args['quantity_'.$item_loop] = $item['qty'];
2011-09-02 14:58:34 +00:00
$paypal_args['amount_'.$item_loop] = $item['cost'];
2011-08-09 15:16:18 +00:00
endif;
endforeach; endif;
// Shipping Cost
$item_loop++;
2011-08-10 17:11:11 +00:00
$paypal_args['item_name_'.$item_loop] = __('Shipping cost', 'woothemes');
2011-08-09 15:16:18 +00:00
$paypal_args['quantity_'.$item_loop] = '1';
$paypal_args['amount_'.$item_loop] = number_format($order->order_shipping, 2);
$paypal_args_array = array();
foreach ($paypal_args as $key => $value) {
2011-09-30 18:22:17 +00:00
$paypal_args_array[] = '<input type="hidden" name="'.esc_attr( $key ).'" value="'.esc_attr( $value ).'" />';
2011-08-09 15:16:18 +00:00
}
2011-09-30 18:22:17 +00:00
return '<form action="'.esc_url( $paypal_adr ).'" method="post" id="paypal_payment_form">
2011-08-09 15:16:18 +00:00
' . implode('', $paypal_args_array) . '
2011-09-30 18:22:17 +00:00
<input type="submit" class="button-alt" id="submit_paypal_payment_form" value="'.__('Pay via PayPal', 'woothemes').'" /> <a class="button cancel" href="'.esc_url( $order->get_cancel_order_url() ).'">'.__('Cancel order &amp; restore cart', 'woothemes').'</a>
2011-08-09 15:16:18 +00:00
<script type="text/javascript">
jQuery(function(){
jQuery("body").block(
{
2011-09-30 18:22:17 +00:00
message: "<img src=\"'.esc_url( $woocommerce->plugin_url() ).'/assets/images/ajax-loader.gif\" alt=\"Redirecting...\" style=\"float:left; margin-right: 10px;\" />'.__('Thank you for your order. We are now redirecting you to PayPal to make payment.', 'woothemes').'",
2011-08-09 15:16:18 +00:00
overlayCSS:
{
background: "#fff",
opacity: 0.6
},
css: {
padding: 20,
textAlign: "center",
color: "#555",
border: "3px solid #aaa",
backgroundColor:"#fff",
2011-09-22 15:08:21 +00:00
cursor: "wait",
lineHeight: "32px"
2011-08-09 15:16:18 +00:00
}
});
jQuery("#submit_paypal_payment_form").click();
});
</script>
</form>';
}
/**
* Process the payment and return the result
**/
function process_payment( $order_id ) {
2011-08-10 17:11:11 +00:00
$order = &new woocommerce_order( $order_id );
2011-08-09 15:16:18 +00:00
return array(
'result' => 'success',
2011-08-10 17:11:11 +00:00
'redirect' => add_query_arg('order', $order->id, add_query_arg('key', $order->order_key, get_permalink(get_option('woocommerce_pay_page_id'))))
2011-08-09 15:16:18 +00:00
);
}
/**
* receipt_page
**/
function receipt_page( $order ) {
2011-08-10 17:11:11 +00:00
echo '<p>'.__('Thank you for your order, please click the button below to pay with PayPal.', 'woothemes').'</p>';
2011-08-09 15:16:18 +00:00
echo $this->generate_paypal_form( $order );
}
/**
* Check PayPal IPN validity
**/
function check_ipn_request_is_valid() {
global $woocommerce;
if ($this->debug=='yes') $woocommerce->log->add( 'paypal', 'Checking IPN response is valid...' );
2011-08-09 15:16:18 +00:00
// Add cmd to the post array
$_POST['cmd'] = '_notify-validate';
// Send back post vars to paypal
$params = array(
'body' => $_POST,
'sslverify' => false
);
2011-08-09 15:16:18 +00:00
// Get url
if ( $this->testmode == 'yes' ):
$paypal_adr = $this->testurl;
else :
$paypal_adr = $this->liveurl;
endif;
// Post back to get a response
$response = wp_remote_post( $paypal_adr, $params );
// Clean
unset($_POST['cmd']);
// check to see if the request was valid
if ( !is_wp_error($response) && $response['response']['code'] >= 200 && $response['response']['code'] < 300 && (strcmp( $response['body'], "VERIFIED") == 0)) {
if ($this->debug=='yes') $woocommerce->log->add( 'paypal', 'Received valid response from PayPal' );
2011-08-09 15:16:18 +00:00
return true;
}
if ($this->debug=='yes') :
$woocommerce->log->add( 'paypal', 'Received invalid response from PayPal' );
if (is_wp_error($response)) :
$woocommerce->log->add( 'paypal', 'Error response: ' . $result->get_error_message() );
endif;
endif;
2011-08-09 15:16:18 +00:00
return false;
}
/**
* Check for PayPal IPN Response
**/
function check_ipn_response() {
if (isset($_GET['paypalListener']) && $_GET['paypalListener'] == 'paypal_standard_IPN'):
$_POST = stripslashes_deep($_POST);
if ($this->check_ipn_request_is_valid()) :
2011-08-09 15:16:18 +00:00
do_action("valid-paypal-standard-ipn-request", $_POST);
endif;
endif;
}
/**
* Successful Payment!
**/
function successful_request( $posted ) {
// Custom holds post ID
if ( !empty($posted['txn_type']) && !empty($posted['invoice']) ) {
$accepted_types = array('cart', 'instant', 'express_checkout', 'web_accept', 'masspay', 'send_money');
if (!in_array(strtolower($posted['txn_type']), $accepted_types)) exit;
2011-08-10 17:11:11 +00:00
$order = new woocommerce_order( (int) $posted['custom'] );
2011-08-09 15:16:18 +00:00
if ($order->order_key!==$posted['invoice']) exit;
// Sandbox fix
if ($posted['test_ipn']==1 && $posted['payment_status']=='Pending') $posted['payment_status'] = 'completed';
2011-08-09 15:16:18 +00:00
if ($order->status !== 'completed') :
// We are here so lets check status and do actions
switch (strtolower($posted['payment_status'])) :
case 'completed' :
// Payment completed
2011-08-10 17:11:11 +00:00
$order->add_order_note( __('IPN payment completed', 'woothemes') );
2011-08-09 15:16:18 +00:00
$order->payment_complete();
2011-11-16 10:30:56 +00:00
2011-11-16 15:28:14 +00:00
// Store PP Details
2011-11-16 10:30:56 +00:00
update_post_meta( (int) $posted['custom'], 'Payer PayPal address', $posted['payer_email']);
2011-11-16 15:28:14 +00:00
update_post_meta( (int) $posted['custom'], 'Transaction ID', $posted['txn_id']);
update_post_meta( (int) $posted['custom'], 'Payer first name', $posted['first_name']);
update_post_meta( (int) $posted['custom'], 'Payer last name', $posted['last_name']);
update_post_meta( (int) $posted['custom'], 'Payment type', $posted['payment_type']);
2011-08-09 15:16:18 +00:00
break;
case 'denied' :
case 'expired' :
case 'failed' :
case 'voided' :
// Order failed
$order->update_status('failed', sprintf(__('Payment %s via IPN.', 'woothemes'), strtolower($posted['payment_status']) ) );
2011-08-09 15:16:18 +00:00
break;
case "refunded" :
case "reversed" :
// Mark order as refunded
$order->update_status('refunded', sprintf(__('Payment %s via IPN.', 'woothemes'), strtolower($posted['payment_status']) ) );
break;
2011-08-09 15:16:18 +00:00
default:
// No action
break;
endswitch;
endif;
exit;
}
}
}
/**
2011-08-10 17:11:11 +00:00
* Add the gateway to WooCommerce
2011-08-09 15:16:18 +00:00
**/
function add_paypal_gateway( $methods ) {
2011-08-10 17:11:11 +00:00
$methods[] = 'woocommerce_paypal'; return $methods;
2011-08-09 15:16:18 +00:00
}
2011-08-10 17:11:11 +00:00
add_filter('woocommerce_payment_gateways', 'add_paypal_gateway' );