PayPal PDT handler Closes #3414

This commit is contained in:
Mike Jolley 2013-08-19 12:28:29 +01:00
parent 759e49a60b
commit 0b8dd0476c
2 changed files with 184 additions and 113 deletions

View File

@ -51,6 +51,7 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
$this->page_style = $this->get_option( 'page_style' ); $this->page_style = $this->get_option( 'page_style' );
$this->invoice_prefix = $this->get_option( 'invoice_prefix', 'WC-' ); $this->invoice_prefix = $this->get_option( 'invoice_prefix', 'WC-' );
$this->paymentaction = $this->get_option( 'paymentaction', 'sale' ); $this->paymentaction = $this->get_option( 'paymentaction', 'sale' );
$this->identity_token = $this->get_option( 'identity_token', '' );
// Logs // Logs
if ( 'yes' == $this->debug ) if ( 'yes' == $this->debug )
@ -60,6 +61,7 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
add_action( 'valid-paypal-standard-ipn-request', array( $this, 'successful_request' ) ); add_action( 'valid-paypal-standard-ipn-request', array( $this, 'successful_request' ) );
add_action( 'woocommerce_receipt_paypal', array( $this, 'receipt_page' ) ); add_action( 'woocommerce_receipt_paypal', array( $this, 'receipt_page' ) );
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) ); add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
add_action( 'woocommerce_thankyou_paypal', array( $this, 'pdt_return_handler' ) );
// Payment listener/API hook // Payment listener/API hook
add_action( 'woocommerce_api_wc_gateway_paypal', array( $this, 'check_ipn_response' ) ); add_action( 'woocommerce_api_wc_gateway_paypal', array( $this, 'check_ipn_response' ) );
@ -67,7 +69,6 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
if ( !$this->is_valid_for_use() ) $this->enabled = false; if ( !$this->is_valid_for_use() ) $this->enabled = false;
} }
/** /**
* Check if this gateway is enabled and available in the user's country * Check if this gateway is enabled and available in the user's country
* *
@ -107,7 +108,6 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
endif; endif;
} }
/** /**
* Initialise Gateway Settings Form Fields * Initialise Gateway Settings Form Fields
* *
@ -152,6 +152,14 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
'desc_tip' => true, 'desc_tip' => true,
'placeholder' => 'you@youremail.com' 'placeholder' => 'you@youremail.com'
), ),
'identity_token' => array(
'title' => __( 'PayPal Identity Token', 'woocommerce' ),
'type' => 'text',
'description' => __( 'Optionally enable "Payment Data Transfer" (Profile > Website Payment Preferences) and then copy your identity token here. This will allow payments to be verified without the need for PayPal IPN.', 'woocommerce' ),
'default' => '',
'desc_tip' => true,
'placeholder' => __( 'Optional', 'woocommerce' )
),
'invoice_prefix' => array( 'invoice_prefix' => array(
'title' => __( 'Invoice Prefix', 'woocommerce' ), 'title' => __( 'Invoice Prefix', 'woocommerce' ),
'type' => 'text', 'type' => 'text',
@ -225,10 +233,8 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
'description' => sprintf( __( 'Log PayPal events, such as IPN requests, inside <code>woocommerce/logs/paypal-%s.txt</code>', 'woocommerce' ), sanitize_file_name( wp_hash( 'paypal' ) ) ), 'description' => sprintf( __( 'Log PayPal events, such as IPN requests, inside <code>woocommerce/logs/paypal-%s.txt</code>', 'woocommerce' ), sanitize_file_name( wp_hash( 'paypal' ) ) ),
) )
); );
} }
/** /**
* Get PayPal Args for passing to PP * Get PayPal Args for passing to PP
* *
@ -409,7 +415,6 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
return $paypal_args; return $paypal_args;
} }
/** /**
* Generate the paypal button link * Generate the paypal button link
* *
@ -472,7 +477,6 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
} }
/** /**
* Process the payment and return the result * Process the payment and return the result
* *
@ -512,7 +516,6 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
} }
/** /**
* Output for the order received page. * Output for the order received page.
* *
@ -524,7 +527,6 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
echo '<p>'.__( 'Thank you - your order is now pending payment. You should be automatically redirected to PayPal to make payment.', 'woocommerce' ).'</p>'; echo '<p>'.__( 'Thank you - your order is now pending payment. You should be automatically redirected to PayPal to make payment.', 'woocommerce' ).'</p>';
echo $this->generate_paypal_form( $order ); echo $this->generate_paypal_form( $order );
} }
/** /**
@ -581,7 +583,6 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
return false; return false;
} }
/** /**
* Check for PayPal IPN Response * Check for PayPal IPN Response
* *
@ -606,7 +607,6 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
} }
/** /**
* Successful Payment! * Successful Payment!
* *
@ -622,7 +622,7 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
// Custom holds post ID // Custom holds post ID
if ( ! empty( $posted['invoice'] ) && ! empty( $posted['custom'] ) ) { if ( ! empty( $posted['invoice'] ) && ! empty( $posted['custom'] ) ) {
$order = $this->get_paypal_order( $posted ); $order = $this->get_paypal_order( $posted['custom'], $posted['invoice'] );
if ( 'yes' == $this->debug ) if ( 'yes' == $this->debug )
$this->log->add( 'paypal', 'Found order #' . $order->id ); $this->log->add( 'paypal', 'Found order #' . $order->id );
@ -768,21 +768,91 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
} }
/**
* Return handler
*
* Alternative to IPN
*/
public function pdt_return_handler() {
$posted = stripslashes_deep( $_REQUEST );
if ( ! empty( $this->identity_token ) && ! empty( $posted['cm'] ) ) {
$order = $this->get_paypal_order( $posted['cm'] );
if ( $order->status != 'pending' )
return;
$posted['st'] = strtolower( $posted['st'] );
switch ( $posted['st'] ) {
case 'completed' :
// Validate transaction
if ( $this->testmode == 'yes' )
$paypal_adr = $this->testurl;
else
$paypal_adr = $this->liveurl;
$pdt = array(
'body' => array(
'cmd' => '_notify-synch',
'tx' => $posted['tx'],
'at' => $this->identity_token
),
'sslverify' => false,
'timeout' => 60,
'httpversion' => '1.1',
'user-agent' => 'WooCommerce/' . WOOCOMMERCE_VERSION
);
// Post back to get a response
$response = wp_remote_post( $paypal_adr, $pdt );
if ( is_wp_error( $response ) )
return false;
if ( ! strpos( $response['body'], "SUCCESS" ) === 0 )
return false;
// Validate Amount
if ( $order->get_total() != $posted['amt'] ) {
if ( 'yes' == $this->debug )
$this->log->add( 'paypal', 'Payment error: Amounts do not match (amt ' . $posted['amt'] . ')' );
// Put this order on-hold for manual checking
$order->update_status( 'on-hold', sprintf( __( 'Validation error: PayPal amounts do not match (amt %s).', 'woocommerce' ), $posted['amt'] ) );
} else {
// Store PP Details
update_post_meta( $order->id, 'Transaction ID', $posted['tx'] );
$order->add_order_note( __( 'PDT payment completed', 'woocommerce' ) );
$order->payment_complete();
}
break;
}
}
}
/** /**
* get_paypal_order function. * get_paypal_order function.
* *
* @access public * @param string $custom
* @param mixed $posted * @param string $invoice
* @return void * @return WC_Order object
*/ */
function get_paypal_order( $posted ) { private function get_paypal_order( $custom, $invoice = '' ) {
$custom = maybe_unserialize( $posted['custom'] ); $custom = maybe_unserialize( $custom );
// Backwards comp for IPN requests // Backwards comp for IPN requests
if ( is_numeric( $custom ) ) { if ( is_numeric( $custom ) ) {
$order_id = (int) $custom; $order_id = (int) $custom;
$order_key = $posted['invoice']; $order_key = $invoice;
} elseif( is_string( $custom ) ) { } elseif( is_string( $custom ) ) {
$order_id = (int) str_replace( $this->invoice_prefix, '', $custom ); $order_id = (int) str_replace( $this->invoice_prefix, '', $custom );
$order_key = $custom; $order_key = $custom;

View File

@ -177,6 +177,7 @@ Yes you can! Join in on our [GitHub repository](http://github.com/woothemes/wooc
* Feature - Authorize option for paypal standard. * Feature - Authorize option for paypal standard.
* Feature - Separate options for countries you can ship to and sell to. * Feature - Separate options for countries you can ship to and sell to.
* Feature - BACS supports multiple account details. * Feature - BACS supports multiple account details.
* Feature - PayPal PDT support (as alternative to IPN).
* Tweak - Added pagination to tax rate screens. * Tweak - Added pagination to tax rate screens.
* Tweak - Added filter to check the 'Create account' checkbox on checkout by default. * Tweak - Added filter to check the 'Create account' checkbox on checkout by default.
* Tweak - Update CPT parameters for 'product_variation' and 'shop_coupon' to be no longer public. * Tweak - Update CPT parameters for 'product_variation' and 'shop_coupon' to be no longer public.