Split up line item methods in paypal

This commit is contained in:
Mike Jolley 2014-11-18 13:46:49 +00:00
parent e68353da63
commit a39353fc73
1 changed files with 133 additions and 131 deletions

View File

@ -170,12 +170,8 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
* *
* @return bool * @return bool
*/ */
function is_valid_for_use() { public function is_valid_for_use() {
if ( ! in_array( get_woocommerce_currency(), apply_filters( 'woocommerce_paypal_supported_currencies', array( 'AUD', 'BRL', 'CAD', 'MXN', 'NZD', 'HKD', 'SGD', 'USD', 'EUR', 'JPY', 'TRY', 'NOK', 'CZK', 'DKK', 'HUF', 'ILS', 'MYR', 'PHP', 'PLN', 'SEK', 'CHF', 'TWD', 'THB', 'GBP', 'RMB', 'RUB' ) ) ) ) { return in_array( get_woocommerce_currency(), apply_filters( 'woocommerce_paypal_supported_currencies', array( 'AUD', 'BRL', 'CAD', 'MXN', 'NZD', 'HKD', 'SGD', 'USD', 'EUR', 'JPY', 'TRY', 'NOK', 'CZK', 'DKK', 'HUF', 'ILS', 'MYR', 'PHP', 'PLN', 'SEK', 'CHF', 'TWD', 'THB', 'GBP', 'RMB', 'RUB' ) ) );
return false;
}
return true;
} }
/** /**
@ -219,31 +215,10 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
* @param WC_Order $order * @param WC_Order $order
* @return array * @return array
*/ */
function get_paypal_args( $order ) { public function get_paypal_args( $order ) {
$order_id = $order->id;
$this->log( 'Generating payment form for order #' . $order->get_order_number() . '. Notify URL: ' . $this->notify_url ); $this->log( 'Generating payment form for order #' . $order->get_order_number() . '. Notify URL: ' . $this->notify_url );
if ( in_array( $order->billing_country, array( 'US','CA' ) ) ) { return apply_filters( 'woocommerce_paypal_args', array_merge(
$order->billing_phone = str_replace( array( '(', '-', ' ', ')', '.' ), '', $order->billing_phone );
$phone_args = array(
'night_phone_a' => substr( $order->billing_phone, 0, 3 ),
'night_phone_b' => substr( $order->billing_phone, 3, 3 ),
'night_phone_c' => substr( $order->billing_phone, 6, 4 ),
'day_phone_a' => substr( $order->billing_phone, 0, 3 ),
'day_phone_b' => substr( $order->billing_phone, 3, 3 ),
'day_phone_c' => substr( $order->billing_phone, 6, 4 )
);
} else {
$phone_args = array(
'night_phone_b' => $order->billing_phone,
'day_phone_b' => $order->billing_phone
);
}
// PayPal Args
$paypal_args = array_merge(
array( array(
'cmd' => '_cart', 'cmd' => '_cart',
'business' => $this->email, 'business' => $this->email,
@ -257,15 +232,9 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
'page_style' => $this->page_style, 'page_style' => $this->page_style,
'paymentaction' => $this->paymentaction, 'paymentaction' => $this->paymentaction,
'bn' => 'WooThemes_Cart', 'bn' => 'WooThemes_Cart',
// Order key + ID
'invoice' => $this->invoice_prefix . $order->get_order_number(), 'invoice' => $this->invoice_prefix . $order->get_order_number(),
'custom' => serialize( array( $order_id, $order->order_key ) ), 'custom' => serialize( array( $order->id, $order->order_key ) ),
// IPN
'notify_url' => $this->notify_url, 'notify_url' => $this->notify_url,
// Billing Address info
'first_name' => $order->billing_first_name, 'first_name' => $order->billing_first_name,
'last_name' => $order->billing_last_name, 'last_name' => $order->billing_last_name,
'company' => $order->billing_company, 'company' => $order->billing_company,
@ -277,153 +246,167 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
'country' => $order->billing_country, 'country' => $order->billing_country,
'email' => $order->billing_email 'email' => $order->billing_email
), ),
$phone_args $this->get_phone_number_args( $order ),
); $this->get_shipping_args( $order ),
$this->get_line_item_args( $order )
), $order );
}
// Shipping /**
* Get phone number args for paypal request
* @param WC_Order $order
* @return array
*/
private function get_phone_number_args( $order ) {
if ( in_array( $order->billing_country, array( 'US','CA' ) ) ) {
$phone_number = str_replace( array( '(', '-', ' ', ')', '.' ), '', $order->billing_phone );
$phone_args = array(
'night_phone_a' => substr( $phone_number, 0, 3 ),
'night_phone_b' => substr( $phone_number, 3, 3 ),
'night_phone_c' => substr( $phone_number, 6, 4 ),
'day_phone_a' => substr( $phone_number, 0, 3 ),
'day_phone_b' => substr( $phone_number, 3, 3 ),
'day_phone_c' => substr( $phone_number, 6, 4 )
);
} else {
$phone_args = array(
'night_phone_b' => $order->billing_phone,
'day_phone_b' => $order->billing_phone
);
}
return $phone_args;
}
/**
* Get shipping args for paypal request
* @param WC_Order $order
* @return array
*/
private function get_shipping_args( $order ) {
if ( 'yes' == $this->send_shipping ) { if ( 'yes' == $this->send_shipping ) {
$paypal_args['address_override'] = ( $this->address_override == 'yes' ) ? 1 : 0; $shipping_args['address_override'] = ( $this->address_override == 'yes' ) ? 1 : 0;
$shipping_args['no_shipping'] = 0;
$paypal_args['no_shipping'] = 0;
// If we are sending shipping, send shipping address instead of billing // If we are sending shipping, send shipping address instead of billing
$paypal_args['first_name'] = $order->shipping_first_name; $shipping_args['first_name'] = $order->shipping_first_name;
$paypal_args['last_name'] = $order->shipping_last_name; $shipping_args['last_name'] = $order->shipping_last_name;
$paypal_args['company'] = $order->shipping_company; $shipping_args['company'] = $order->shipping_company;
$paypal_args['address1'] = $order->shipping_address_1; $shipping_args['address1'] = $order->shipping_address_1;
$paypal_args['address2'] = $order->shipping_address_2; $shipping_args['address2'] = $order->shipping_address_2;
$paypal_args['city'] = $order->shipping_city; $shipping_args['city'] = $order->shipping_city;
$paypal_args['state'] = $this->get_paypal_state( $order->shipping_country, $order->shipping_state ); $shipping_args['state'] = $this->get_paypal_state( $order->shipping_country, $order->shipping_state );
$paypal_args['country'] = $order->shipping_country; $shipping_args['country'] = $order->shipping_country;
$paypal_args['zip'] = $order->shipping_postcode; $shipping_args['zip'] = $order->shipping_postcode;
} else { } else {
$paypal_args['no_shipping'] = 1; $shipping_args['no_shipping'] = 1;
} }
return $shipping_args;
}
// Try to send line items, or default to sending the order as a whole /**
if ( $line_items = $this->get_line_items( $order ) ) { * Get line item args for paypal request
$paypal_args = array_merge( $paypal_args, $line_items ); * @param WC_Order $order
} else { * @return array
// Don't pass items - paypal borks tax due to prices including tax. PayPal has no option for tax inclusive pricing sadly. Pass 1 item for the order items overall */
$item_names = array(); private function get_line_item_args( $order ) {
$line_item_args = array();
try {
// Try passing a line item per product
if ( ! $this->prepare_line_items( $order ) ) {
throw new Exception;
}
$line_item_args = $this->line_items;
$line_item_args['tax_cart'] = $order->get_total_tax();
if ( $order->get_cart_discount() > 0 ) {
$line_item_args['discount_amount_cart'] = round( $order->get_cart_discount(), 2 );
}
} catch ( Exception $e ) {
// Pass 1 item for the order items overall
$this->line_items = array();
$item_names = array();
if ( sizeof( $order->get_items() ) > 0 ) { if ( sizeof( $order->get_items() ) > 0 ) {
foreach ( $order->get_items() as $item ) { foreach ( $order->get_items() as $item ) {
if ( $item['qty'] ) { $item_names[] = $item['name'] . ' x ' . $item['qty'];
$item_names[] = $item['name'] . ' x ' . $item['qty'];
}
} }
} }
$paypal_args['item_name_1'] = $this->paypal_item_name( sprintf( __( 'Order #%s' , 'woocommerce'), $order->get_order_number() ) . " - " . implode( ', ', $item_names ) ); $this->add_line_item( implode( ', ', $item_names ), 1, number_format( $order->get_total() - round( $order->get_total_shipping() + $order->get_shipping_tax(), 2 ) + $order->get_order_discount(), 2, '.', '' ), $order->get_order_number() );
$paypal_args['quantity_1'] = '1';
$paypal_args['amount_1'] = number_format( $order->get_total() - round( $order->get_total_shipping() + $order->get_shipping_tax(), 2 ) + $order->get_order_discount(), 2, '.', '' );
// Shipping Cost // Shipping Cost
// No longer using shipping_1 because // No longer using shipping_1 because
// a) paypal ignore it if *any* shipping rules are within paypal // a) paypal ignore it if *any* shipping rules are within paypal
// b) paypal ignore anything over 5 digits, so 999.99 is the max // b) paypal ignore anything over 5 digits, so 999.99 is the max
if ( ( $order->get_total_shipping() + $order->get_shipping_tax() ) > 0 ) { if ( ( $order->get_total_shipping() + $order->get_shipping_tax() ) > 0 ) {
$paypal_args['item_name_2'] = $this->paypal_item_name( __( 'Shipping via', 'woocommerce' ) . ' ' . ucwords( $order->get_shipping_method() ) ); $this->add_line_item( sprintf( __( 'Shipping via %s', 'woocommerce' ), ucwords( $order->get_shipping_method() ) ), 1, number_format( $order->get_total_shipping() + $order->get_shipping_tax(), 2, '.', '' ) );
$paypal_args['quantity_2'] = '1';
$paypal_args['amount_2'] = number_format( $order->get_total_shipping() + $order->get_shipping_tax(), 2, '.', '' );
} }
$line_item_args = $this->line_items;
// Discount // Discount
if ( $order->get_order_discount() ) { if ( $order->get_order_discount() ) {
$paypal_args['discount_amount_cart'] = $order->get_order_discount(); $line_item_args['discount_amount_cart'] = $order->get_order_discount();
} }
} }
$paypal_args = apply_filters( 'woocommerce_paypal_args', $paypal_args ); return $line_item_args;
return $paypal_args;
} }
/** /**
* Get line items to send to paypal * Get line items to send to paypal
* *
* @param WC_Order $order * @param WC_Order $order
* @return array on success, or false when it is not possible to send line items * @return bool
*/ */
private function get_line_items( $order ) { private function prepare_line_items( $order ) {
// Do not send lines for tax inclusive prices // Do not send lines for tax inclusive prices and do not send lines when order discount is present
if ( 'yes' === get_option( 'woocommerce_calc_taxes' ) && 'yes' === get_option( 'woocommerce_prices_include_tax' ) ) { if ( ( 'yes' === get_option( 'woocommerce_calc_taxes' ) && 'yes' === get_option( 'woocommerce_prices_include_tax' ) ) || $order->get_order_discount() > 0 ) {
return false; return false;
} }
// Do not send lines when order discount is present, or too many line items in the order. $this->line_items = array();
if ( $order->get_order_discount() > 0 || ( sizeof( $order->get_items() ) + sizeof( $order->get_fees() ) ) >= 9 ) { $calculated_total = $order->get_total_tax() - round( $order->get_cart_discount(), 2 );
return false;
}
$item_loop = 0;
$args = array();
$args['tax_cart'] = $order->get_total_tax();
$calculated_total = $order->get_total_tax();
// Products // Products
if ( sizeof( $order->get_items() ) > 0 ) { if ( sizeof( $order->get_items() ) > 0 ) {
foreach ( $order->get_items() as $item ) { foreach ( $order->get_items() as $item ) {
if ( ! $item['qty'] ) { $product = $order->get_product_from_item( $item );
continue; $item_name = $item['name'];
} $item_meta = new WC_Order_Item_Meta( $item['item_meta'] );
$item_loop ++; $calculated_total += $order->get_item_subtotal( $item, false ) * $item['qty'];
$product = $order->get_product_from_item( $item );
$item_name = $item['name'];
$item_meta = new WC_Order_Item_Meta( $item['item_meta'] );
if ( $meta = $item_meta->display( true, true ) ) { if ( $meta = $item_meta->display( true, true ) ) {
$item_name .= ' ( ' . $meta . ' )'; $item_name .= ' ( ' . $meta . ' )';
} }
$args[ 'item_name_' . $item_loop ] = $this->paypal_item_name( $item_name ); if ( ! $this->add_line_item( $item_name, $item['qty'], $order->get_item_subtotal( $item, false ), $product->get_sku() ) ) {
$args[ 'quantity_' . $item_loop ] = $item['qty']; return false;
$args[ 'amount_' . $item_loop ] = $order->get_item_subtotal( $item, false );
if ( $args[ 'amount_' . $item_loop ] < 0 ) {
return false; // Abort - negative line
} }
if ( $product->get_sku() ) {
$args[ 'item_number_' . $item_loop ] = $product->get_sku();
}
$calculated_total += $order->get_item_subtotal( $item, false ) * $item['qty'];
} }
} }
// Discount
if ( $order->get_cart_discount() > 0 ) {
$args['discount_amount_cart'] = round( $order->get_cart_discount(), 2 );
$calculated_total = $calculated_total - round( $order->get_cart_discount(), 2 );
}
// Fees // Fees
if ( sizeof( $order->get_fees() ) > 0 ) { if ( sizeof( $order->get_fees() ) > 0 ) {
foreach ( $order->get_fees() as $item ) { foreach ( $order->get_fees() as $item ) {
$item_loop ++;
$args[ 'item_name_' . $item_loop ] = $this->paypal_item_name( $item['name'] );
$args[ 'quantity_' . $item_loop ] = 1;
$args[ 'amount_' . $item_loop ] = $item['line_total'];
if ( $args[ 'amount_' . $item_loop ] < 0 ) {
return false; // Abort - negative line
}
$calculated_total += $item['line_total']; $calculated_total += $item['line_total'];
if ( ! $this->add_line_item( $item['name'], 1, $item['line_total'] ) ) {
return false;
}
} }
} }
// Shipping Cost item - paypal only allows shipping per item, we want to send shipping for the order // Shipping Cost item - paypal only allows shipping per item, we want to send shipping for the order
if ( $order->get_total_shipping() > 0 ) { if ( $order->get_total_shipping() > 0 ) {
$item_loop ++;
$args[ 'item_name_' . $item_loop ] = $this->paypal_item_name( sprintf( __( 'Shipping via %s', 'woocommerce' ), $order->get_shipping_method() ) );
$args[ 'quantity_' . $item_loop ] = '1';
$args[ 'amount_' . $item_loop ] = number_format( $order->get_total_shipping(), 2, '.', '' );
$calculated_total += number_format( $order->get_total_shipping(), 2, '.', '' ); $calculated_total += number_format( $order->get_total_shipping(), 2, '.', '' );
if ( ! $this->add_line_item( sprintf( __( 'Shipping via %s', 'woocommerce' ), $order->get_shipping_method(), 1, number_format( $order->get_total_shipping(), 2, '.', '' ) ) ) ) {
return false;
}
} }
// Check for mismatch // Check for mismatch
@ -431,7 +414,30 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
return false; return false;
} }
return $args; return true;
}
/**
* Add PayPal Line Item
* @param string $item_name
* @param integer $quantity
* @param integer $amount
* @param string $item_number
* @return bool successfully added or not
*/
public function add_line_item( $item_name, $quantity = 1, $amount = 0, $item_number = '' ) {
$index = ( sizeof( $this->line_items ) / 4 ) + 1;
if ( ! $item_name || $amount < 0 || $index > 9 ) {
return false;
}
$this->line_items[ 'item_name_' . $index ] = $this->paypal_item_name( $item_name );
$this->line_items[ 'quantity_' . $index ] = $quantity;
$this->line_items[ 'amount_' . $index ] = $amount;
$this->line_items[ 'item_number_' . $index ] = $item_number;
return true;
} }
/** /**
@ -489,7 +495,6 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
if ( 255 < strlen( $reason ) ) { if ( 255 < strlen( $reason ) ) {
$reason = substr( $reason, 0, 252 ) . '...'; $reason = substr( $reason, 0, 252 ) . '...';
} }
$post_data['NOTE'] = html_entity_decode( $reason, ENT_NOQUOTES, 'UTF-8' ); $post_data['NOTE'] = html_entity_decode( $reason, ENT_NOQUOTES, 'UTF-8' );
} }
@ -503,14 +508,11 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
) )
); );
if ( is_wp_error( $response ) ) { if ( is_wp_error( $response ) || empty( $response['body'] ) ) {
$this->log( 'Refund Failed: ' . print_r( $response['body'], true ) );
return $response; return $response;
} }
if ( empty( $response['body'] ) ) {
return new WP_Error( 'paypal-error', __( 'Empty Paypal response.', 'woocommerce' ) );
}
parse_str( $response['body'], $parsed_response ); parse_str( $response['body'], $parsed_response );
switch ( strtolower( $parsed_response['ACK'] ) ) { switch ( strtolower( $parsed_response['ACK'] ) ) {