Skip to content

Commit

Permalink
Payment Gateway Framework Fixes and Updates
Browse files Browse the repository at this point in the history
* Direct payment gateway "paid upon release" pre-order support
* minor cleanups/refactors/comment updates
* Pay page pre-order support
* Order note for payment method tokenization closes #13
* Fixed parameter ordering of remove_tokenized_payment_method() call
* Fixed pay page guest transaction tokenization allowed handling in the
template files
  • Loading branch information
justinstern committed Nov 23, 2013
1 parent a968370 commit 4740453
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@
if ( ! interface_exists( 'SV_WC_Payment_Gateway_API_Authorization_Response' ) ) :

/**
* WooCommerce Direct Payment Gateway API Response
* WooCommerce Direct Payment Gateway API Authorization Response
*
* Represents a Payment Gateway Credit Card Authorization response. This should
* also be used as the parent class for credit card charge (authorization +
* capture) responses.
*/
interface SV_WC_Payment_Gateway_API_Authorization_Response extends SV_WC_Payment_Gateway_API_Response {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ protected function validate_check_fields( $is_valid ) {
* Handles payment processing
*
* @since 1.0
* @see WC_Payment_Gateway::process_payment()
*/
public function process_payment( $order_id ) {

Expand All @@ -341,6 +342,11 @@ public function process_payment( $order_id ) {
// note that customer id & payment token are saved to order when create_payment_token() is called
if ( 0 == $order->payment_total || $this->do_transaction( $order ) ) {

// add transaction data for zero-dollar "orders"
if ( 0 == $order->payment_total ) {
$this->add_transaction_data( $order );
}

if ( 'on-hold' == $order->status )
$order->reduce_order_stock(); // reduce stock for held orders, but don't complete payment
else
Expand Down Expand Up @@ -598,7 +604,7 @@ public function do_credit_card_capture( $order ) {
$message = sprintf(
__( '%s Capture of %s Approved', $this->text_domain ),
$this->get_method_title(),
get_woocommerce_currency_symbol() . woocommerce_format_total( $order->order_total )
get_woocommerce_currency_symbol() . woocommerce_format_total( $order->get_total() )
);

// adds the transaction id (if any) to the order note
Expand Down Expand Up @@ -681,17 +687,23 @@ protected function add_transaction_data( $order, $response = null ) {
if ( $this->is_credit_card_gateway() ) {

// credit card gateway data
if ( $response && $response->get_authorization_code() ) {
update_post_meta( $order->id, '_wc_' . $this->get_id() . '_authorization_code', $response->get_authorization_code() );
}
if ( $response && $response instanceof SV_WC_Payment_Gateway_API_Authorization_Response ) {

if ( $response->get_authorization_code() ) {
update_post_meta( $order->id, '_wc_' . $this->get_id() . '_authorization_code', $response->get_authorization_code() );
}

if ( $order->payment_total > 0 ) {
// mark as captured
if ( $this->perform_credit_card_charge() ) {
$captured = 'yes';
} else {
$captured = 'no';
}
update_post_meta( $order->id, '_wc_' . $this->get_id() . '_charge_captured', $captured );
}

// mark as captured
if ( $this->perform_credit_card_charge() ) {
$captured = 'yes';
} else {
$captured = 'no';
}
update_post_meta( $order->id, '_wc_' . $this->get_id() . '_charge_captured', $captured );

if ( isset( $order->payment->exp_year ) && $order->payment->exp_year && isset( $order->payment->exp_month ) && $order->payment->exp_month ) {
update_post_meta( $order->id, '_wc_' . $this->get_id() . '_card_expiry_date', $order->payment->exp_year . '-' . $order->payment->exp_month );
Expand Down Expand Up @@ -812,8 +824,9 @@ public function subscriptions_tokenization_forced( $force_tokenization ) {

if ( WC_Subscriptions_Cart::cart_contains_subscription() ||
WC_Subscriptions_Change_Payment_Gateway::$is_request_to_change_payment ||
$pay_page_subscription )
$pay_page_subscription ) {
$force_tokenization = true;
}

return $force_tokenization;
}
Expand Down Expand Up @@ -1118,8 +1131,20 @@ public function add_pre_orders_support() {
*/
public function pre_orders_tokenization_forced( $force_tokenization ) {

if ( class_exists( 'WC_Pre_Orders_Cart' ) && WC_Pre_Orders_Cart::cart_contains_pre_order() &&
class_exists( 'WC_Pre_Orders_Product' ) && WC_Pre_Orders_Product::product_is_charged_upon_release( WC_Pre_Orders_Cart::get_pre_order_product() ) ) {
// pay page with pre-order?
$pay_page_pre_order = false;
if ( $this->is_pay_page_gateway() ) {

$order_id = isset( $_GET['order'] ) ? absint( $_GET['order'] ) : 0;

if ( $order_id ) {
$pay_page_pre_order = WC_Pre_Orders_Order::order_contains_pre_order( $order_id ) && WC_Pre_Orders_Product::product_is_charged_upon_release( WC_Pre_Orders_Order::get_pre_order_product( $order_id ) );
}

}

if ( ( WC_Pre_Orders_Cart::cart_contains_pre_order() && WC_Pre_Orders_Product::product_is_charged_upon_release( WC_Pre_Orders_Cart::get_pre_order_product() ) ) ||
$pay_page_pre_order ) {

// always tokenize the card for pre-orders that are charged upon release
$force_tokenization = true;
Expand Down Expand Up @@ -1147,7 +1172,7 @@ public function pre_orders_get_order( $order ) {

if ( WC_Pre_Orders_Order::order_requires_payment_tokenization( $order ) ) {

// normally a guest user wouldn't be assigned a customer id, but for a pre-order requiring tokenization, it will be
// normally a guest user wouldn't be assigned a customer id, but for a pre-order requiring tokenization, it might be
if ( 0 == $order->user_id && false !== ( $customer_id = $this->get_guest_customer_id( $order ) ) )
$order->customer_id = $customer_id;

Expand All @@ -1158,7 +1183,7 @@ public function pre_orders_get_order( $order ) {
// retrieve the payment token
$order->payment->token = get_post_meta( $order->id, '_wc_' . $this->get_id() . '_payment_token', true );

// retrieve the customer id
// retrieve the customer id (might not be one)
$order->customer_id = get_post_meta( $order->id, '_wc_' . $this->get_id() . '_customer_id', true );

// verify that this customer still has the token tied to this order. Pass in customer_id to support tokenized guest orders
Expand All @@ -1171,7 +1196,7 @@ public function pre_orders_get_order( $order ) {
// or from the order object otherwise. The theory is that the token will have the
// most up-to-date data, while the meta attached to the order is a second best

// for a guest transaction with a gateway that doesn't support "tokenization get" this will return null
// for a guest transaction with a gateway that doesn't support "tokenization get" this will return null and the token data will be pulled from the order meta
$token = $this->get_payment_token( $order->user_id, $order->payment->token, $order->customer_id );

// account last four
Expand Down Expand Up @@ -1223,8 +1248,7 @@ public function process_pre_order_payment( $result, $order_id ) {

if ( ! $this->supports_pre_orders() ) throw new SV_WC_Payment_Gateway_Feature_Unsupported_Exception( __( 'Pre-Orders not supported by gateway', $this->text_domain ) );

if ( $this->get_plugin()->is_pre_orders_active() && class_exists( 'WC_Pre_Orders_Order' ) &&
WC_Pre_Orders_Order::order_contains_pre_order( $order_id ) &&
if ( WC_Pre_Orders_Order::order_contains_pre_order( $order_id ) &&
WC_Pre_Orders_Order::order_requires_payment_tokenization( $order_id ) ) {

$order = $this->get_order( $order_id );
Expand All @@ -1243,27 +1267,6 @@ public function process_pre_order_payment( $result, $order_id ) {
$order = $this->create_payment_token( $order );
}

$token = $this->get_payment_token( get_current_user_id(), $order->payment->token );

// order note based on gateway type
if ( $this->is_credit_card_gateway() ) {
$message = sprintf( __( '%s Pre-Order Payment Token Saved: %s ending in %s (expires %s)', $this->text_domain ),
$this->get_method_title(),
$token->get_type_full(),
$token->get_last_four(),
$token->get_exp_date()
);
} else {
// account type (checking/savings) may or may not be available, which is fine
$message = sprintf( __( '%s Pre-Order eCheck Payment Token Saved: %s account ending in %s', $this->text_domain ),
$this->get_method_title(),
$token->get_account_type(),
$token->get_last_four()
);
}

$order->add_order_note( $message );

// mark order as pre-ordered / reduce order stock
WC_Pre_Orders_Order::mark_order_as_pre_ordered( $order );

Expand Down Expand Up @@ -1456,6 +1459,25 @@ protected function create_payment_token( $order ) {
if ( $order->user_id )
$this->add_payment_token( $order->user_id, $token );

// order note based on gateway type
if ( $this->is_credit_card_gateway() ) {
$message = sprintf( __( '%s Payment Method Saved: %s ending in %s (expires %s)', $this->text_domain ),
$this->get_method_title(),
$token->get_type_full(),
$token->get_last_four(),
$token->get_exp_date()
);
} else {
// account type (checking/savings) may or may not be available, which is fine
$message = sprintf( __( '%s eCheck Payment Method Saved: %s account ending in %s', $this->text_domain ),
$this->get_method_title(),
$token->get_account_type(),
$token->get_last_four()
);
}

$order->add_order_note( $message );

// add the standard transaction data
$this->add_transaction_data( $order, $response );

Expand Down Expand Up @@ -1740,7 +1762,7 @@ public function remove_payment_token( $user_id, $token ) {

try {

$response = $this->get_api()->remove_tokenized_payment_method( $this->get_customer_id( $user_id ), $token->get_token() );
$response = $this->get_api()->remove_tokenized_payment_method( $token->get_token(), $this->get_customer_id( $user_id ) );

if ( ! $response->transaction_approved() ) {
return false;
Expand Down
15 changes: 13 additions & 2 deletions skyverge/woocommerce/payment-gateway/class-wc-payment-gateway.php
Original file line number Diff line number Diff line change
Expand Up @@ -383,15 +383,26 @@ public function enqueue_scripts() {
}


/**
* Returns true if on the pay page
*
* @since 1.0
* @return mixed true if on pay page
*/
public function is_pay_page() {
return is_page( woocommerce_get_page_id( 'pay' ) );
}


/**
* Returns true if on the pay page and this is the currently selected gateway
*
* @since 1.0
* @return mixed true if on pay page and is currently selected gateways, false if on pay page and not the selected gateway, null otherwise
*/
protected function is_pay_page_gateway() {
public function is_pay_page_gateway() {

if ( is_page( woocommerce_get_page_id( 'pay' ) ) ) {
if ( $this->is_pay_page() ) {

$order_id = isset( $_GET['order'] ) ? absint( $_GET['order'] ) : 0;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly

%%IF SUPPORTS TOKENIZATION%%
<?php
if ( $tokenization_allowed ) :
if ( $tokenization_allowed || $tokenization_forced ) :
if ( $tokenization_forced ) :
?>
<input name="wc-%%GATEWAY ID DASHERIZED CHECKS%%-tokenize-payment-method" id="wc-%%GATEWAY ID DASHERIZED CHECKS%%-tokenize-payment-method" type="hidden" value="true" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly

%%IF SUPPORTS TOKENIZATION%%
<?php
if ( $tokenization_allowed ) :
if ( $tokenization_allowed || $tokenization_forced ) :
if ( $tokenization_forced ) :
?>
<input name="wc-%%GATEWAY ID DASHERIZED%%-tokenize-payment-method" id="wc-%%GATEWAY ID DASHERIZED%%-tokenize-payment-method" type="hidden" value="true" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ if ( ! function_exists( 'woocommerce_%%GATEWAY ID%%_payment_fields' ) ) {
// tokenization is allowed if tokenization is enabled on the gateway
$tokenization_allowed = $gateway->tokenization_enabled();

// on the pay page there is no way of creating an account, so disallow tokenization for guest customers
if ( $tokenization_allowed && $gateway->is_pay_page() && ! is_user_logged_in() ) {
$tokenization_allowed = false;
}

$tokens = array();
$default_new_card = true;
if ( $tokenization_allowed && is_user_logged_in() ) {
Expand Down Expand Up @@ -211,6 +216,11 @@ if ( ! function_exists( 'woocommerce_%%GATEWAY ID CHECKS%%_payment_fields' ) ) {
// tokenization is allowed if tokenization is enabled on the gateway
$tokenization_allowed = $gateway->tokenization_enabled();

// on the pay page there is no way of creating an account, so disallow tokenization for guest customers
if ( $tokenization_allowed && $gateway->is_pay_page() && ! is_user_logged_in() ) {
$tokenization_allowed = false;
}

$tokens = array();
$default_new_account = true;
if ( $tokenization_allowed && is_user_logged_in() ) {
Expand Down

0 comments on commit 4740453

Please sign in to comment.