Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/Gateways/AbstractGateway.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ abstract class AbstractGateway extends WC_Payment_Gateway_Cc {
const TXN_TYPE_INITIATE_AUTHENTICATION = 'initiateAuthentication';

const TXN_TYPE_PAYPAL_INITIATE = 'initiatePayment';
// Subscription
const TXN_TYPE_SUBSCRIPTION_PAYMENT = 'subscriptionPayment';


/**
* Gateway provider. Should be overriden by individual gateway implementations
Expand Down Expand Up @@ -956,6 +959,11 @@ public function process_payment( $order_id ) {
$this->payment_action,
$order->get_transaction_id()
);
// If the order contains a subscription, add the muti-use token to the order meta for repeat payments.
if ( function_exists( "wcs_order_contains_subscription" ) && wcs_order_contains_subscription( $order ) && $is_successful ) {
$order->add_meta_data( "_GP_multi_use_token", $response->token, true );
$order->save_meta_data();
}

$order->add_order_note( $note_text );
}
Expand Down Expand Up @@ -1167,6 +1175,7 @@ public function prepare_request( $txn_type, WC_Order $order = null, $configData
self::TXN_TYPE_BNPL_AUTHORIZE => Requests\BuyNowPayLater\InitiatePaymentRequest::class,
self::TXN_TYPE_OB_AUTHORIZATION => Requests\OpenBanking\InitiatePaymentRequest::class,
self::TXN_TYPE_PAYPAL_INITIATE => Requests\Apm\InitiatePaymentRequest::class,
self::TXN_TYPE_SUBSCRIPTION_PAYMENT => Requests\Subscriptions\SubscriptionRequest::class
);

if ( ! isset( $map[ $txn_type ] ) ) {
Expand Down
6 changes: 6 additions & 0 deletions src/Gateways/Clients/SdkClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,12 @@ protected function prepare_request_objects() {
$this->builder_args['requestMultiUseToken'] = array( true );
}
}
// Checks if order contains a subscription and requests a muti-use token.
if( function_exists( "wcs_order_contains_subscription" ) ){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add a space after the 'if' keyword too. This applies to the other files too.

if( isset( $this->builder_args['orderId'] ) && wcs_order_contains_subscription( wc_get_order( $this->builder_args['orderId'][0] ) ) ) {
$this->builder_args['requestMultiUseToken'] = array( true );
}
}

if ( $this->has_arg( RequestArg::DIGITAL_WALLET_TOKEN ) ) {
$this->card_data = new CreditCardData();
Expand Down
55 changes: 55 additions & 0 deletions src/Gateways/GpApiGateway.php
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,25 @@ protected function add_hooks() {
'process_threeDSecure_challengeNotification'
) );
add_action( 'woocommerce_order_actions', array( $this, 'handle_adding_capture_order_action' ) );

add_action( 'woocommerce_scheduled_subscription_payment_' . $this->id, array(
$this,
'renew_subscription'
), 10, 3 );
// When subscription is canceled remove the meta data
add_action( 'woocommerce_subscription_status_pending-cancel_to_cancelled', function( $subscription ){
if( $subscription->get_payment_method() === $this->id ) {
$original_order = wc_get_order( $subscription->get_parent_id() );
if( $original_order->get_meta( "_GP_multi_use_token" ) ) {
$original_order->delete_meta_data( '_GP_multi_use_token' );
$original_order->save();
} else {
return;
}
} else {
return;
}
} );
}

public function woocommerce_globalpayments_gpapi_settings( $settings ) {
Expand Down Expand Up @@ -550,6 +569,42 @@ public function handle_adding_capture_order_action( $actions ) {
return $actions;
}

/**
* Handles subscription renewals, gets the muti-use token from the order meta and charges it.
* @return bool
*/
public function renew_subscription( $amount_to_charge, $renewal_order ) {
$renewal_order_subscriptions = wcs_get_subscriptions_for_renewal_order( $renewal_order->get_id(),array( "order_type"=>"parent") );
$parent_order = false;
foreach( $renewal_order_subscriptions as $renewal_order_subscription ) {
if( $renewal_order_subscription->get_parent_id() ) {
$parent_order = wc_get_order( $renewal_order_subscription->get_parent_id() );
}
}

if( !$parent_order || !$parent_order->get_meta( "_GP_multi_use_token" ) ) {

return;
}
$request = $this->prepare_request( parent::TXN_TYPE_SUBSCRIPTION_PAYMENT, $renewal_order, array( "multi_use_token"=> $parent_order->get_meta( "_GP_multi_use_token" ) ) );
$response = $this->client->submit_request( $request );
$client_trans_ref = $response->transactionReference->clientTransactionId;

if( parent::handle_response( $request, $response ) ) {
$renewal_order->add_order_note( sprintf( __( "Subscription Renewal Successful \r\n Transaction Reference: %s", "globalpayments-gateway-provider-for-woocommerce" ), $client_trans_ref ) );
$renewal_order->payment_complete();
$renewal_order->save();

return true;
}else{
$renewal_order->add_order_note( sprintf( __( "Subscription Renewal Payment Failed \r\nTransaction Reference: %s", "globalpayments-gateway-provider-for-woocommerce" ), $client_trans_ref ) );
$renewal_order->save();

return false;
}

return false;
}
/**
* Returns gateway supported payment methods.
*
Expand Down
79 changes: 79 additions & 0 deletions src/Gateways/Requests/Subscriptions/SubscriptionRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code in this file seems to be indented using spaces and not tabs. This needs to be fixed.


namespace GlobalPayments\WooCommercePaymentGatewayProvider\Gateways\Requests\Subscriptions;

use GlobalPayments\WooCommercePaymentGatewayProvider\Gateways\Requests\AbstractRequest;
use GlobalPayments\WooCommercePaymentGatewayProvider\Gateways\AbstractGateway;
use GlobalPayments\Api\PaymentMethods\CreditCardData;
use GlobalPayments\Api\Entities\Enums\AddressType;
use GlobalPayments\Api\Entities\Customer;
use GlobalPayments\Api\Entities\Address;
use GlobalPayments\Api\Utils\CountryUtils;
use GlobalPayments\Api\Entities\Enums\PhoneNumberType;
use GlobalPayments\Api\Entities\PhoneNumber;
use GlobalPayments\WooCommercePaymentGatewayProvider\Utils\Utils;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Three of the four empty lines can be removed.

defined('ABSPATH') || exit;

class SubscriptionRequest extends AbstractRequest {

public function get_transaction_type() {
return AbstractGateway::TXN_TYPE_SUBSCRIPTION_PAYMENT;
}
public function get_args() {
return array();
}
public function do_request() {
$muti_use_token = $this->get_muti_use_token();
$tokenizedCard = new CreditCardData();
$tokenizedCard->token = $muti_use_token;
$customer_details = $this->get_customer_data();
$tokenizedCard->cardHolderName = $customer_details->firstName . " " . $customer_details->lastName;
$response = $tokenizedCard->charge( $this->order->get_total() )
->withCurrency( $this->order->get_currency() )
->withOrderId( (string) $this->order->get_id() )
->withAddress( $this->get_shipping_details(), AddressType::SHIPPING )
->withAddress( $this->get_billing_address(), AddressType::BILLING )
->withCustomerData( $customer_details )
->withDynamicDescriptor( sprintf( __( "Subscription payment for order: %s", "globalpayments-gateway-provider-for-woocommerce" ), $this->order->get_id() ) )
->execute();

return $response;
}
private function get_muti_use_token(){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add a space before the brace for this method and the below ones, for consistency.

return $this->order->get_meta( "_GP_multi_use_token" ) ? $this->order->get_meta( "_GP_multi_use_token" ) : $this->config['multi_use_token'];
}
private function get_shipping_details(){
$shipping_details = new Address();
$shipping_details->streetAddress1 = $this->order->get_billing_address_1();
$shipping_details->streetAddress2 = $this->order->get_billing_address_2();
$shipping_details->city = $this->order->get_billing_city();
$shipping_details->state = $this->order->get_billing_state();
$shipping_details->postalCode = $this->order->get_billing_postcode();
$shipping_details->country = $this->order->get_billing_country();

return $shipping_details;
}
protected function get_billing_address(){
$billing_address = new Address();
$billing_address->streetAddress1 = $this->order->get_billing_address_1();
$billing_address->streetAddress2 = $this->order->get_billing_address_2();
$billing_address->city = $this->order->get_billing_city();
$billing_address->state = $this->order->get_billing_state();
$billing_address->postalCode = $this->order->get_billing_postcode();
$billing_address->country = $this->order->get_billing_country();

return $billing_address;
}
private function get_customer_data(){
$customer = new Customer();
$customer->id = $this->order->get_customer_id();
$customer->firstName = Utils::sanitize_string( $this->order->get_billing_first_name() );
$customer->lastName = Utils::sanitize_string( $this->order->get_billing_last_name() );
$customer->email = $this->order->get_billing_email();
$phone_code = CountryUtils::getPhoneCodesByCountry( $this->order->get_billing_country() );
$customer->phone = new PhoneNumber( $phone_code[0], $this->order->get_billing_phone(), PhoneNumberType::HOME );

return $customer;
}
}