Last active
December 11, 2022 08:26
-
-
Save digitalchild/00565df0939e7fde14eb to your computer and use it in GitHub Desktop.
[WC Vendors] Paypal Adaptive Payments - Chained
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
if ( !class_exists( 'WC_Payment_Gateway' ) ) return false; | |
/** | |
* Add the gateway to WooCommerce | |
* | |
* @access public | |
* @param array $methods | |
* @return array | |
*/ | |
function add_paypal_ap_gateway( $methods ) | |
{ | |
$methods[] = 'WC_PaypalAP'; | |
return $methods; | |
} | |
add_filter( 'woocommerce_payment_gateways', 'add_paypal_ap_gateway' ); | |
class WC_PaypalAP extends WC_Payment_Gateway { | |
public static $pluginDir; | |
/** | |
* | |
*/ | |
public function __construct() | |
{ | |
global $woocommerce; | |
self::$pluginDir = trailingslashit( dirname( __FILE__ ) ) . 'PayPal_AP/'; | |
/* Standard WooCommerce Configuration */ | |
$this->id = 'paypalap'; | |
$this->icon = plugin_dir_url( __FILE__ ) . 'PayPal_AP/assets/icons/paypalap.png'; | |
$this->method_title = __( 'PayPal Adaptive Payments', 'wcvendors' ); | |
$this->has_fields = false; | |
// Load the settings | |
$this->init_form_fields(); | |
$this->init_settings(); | |
$this->enabled = $this->settings['enabled']; | |
$this->title = $this->settings['title']; | |
$this->description = $this->settings['description']; | |
$this->currency = get_option( 'woocommerce_currency' ); | |
/* PayPal Adaptive Payments Configuration. */ | |
$this->sandbox = $this->settings['sandbox_enabled']; | |
$this->main_paypal = $this->sandbox == 'yes' ? $this->settings['main_paypal'] : $this->settings['main_paypal_live']; | |
$this->instapay = WC_Vendors::$pv_options->get_option( 'instapay' ); | |
$this->give_tax = WC_Vendors::$pv_options->get_option( 'give_tax' ); | |
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) ); | |
// Payment listener/API hook | |
add_action( 'woocommerce_api_wc_paypalap', array( $this, 'paypal_ap_ipn' ) ); | |
$this->debug_me = false; | |
} | |
/** | |
* | |
* | |
* @return unknown | |
*/ | |
public function is_available() | |
{ | |
return ( $this->is_valid_currency() && $this->enabled == 'yes' ); | |
} | |
/** | |
* | |
* | |
* @return unknown | |
*/ | |
public function is_valid_currency() | |
{ | |
return in_array( get_woocommerce_currency(), 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' ) ); | |
} | |
/** | |
* | |
*/ | |
public function include_paypal_sdk() | |
{ | |
$path = self::$pluginDir . 'classes/adaptivepayments-sdk/lib'; | |
set_include_path( get_include_path() . PATH_SEPARATOR . $path ); | |
require_once 'services/AdaptivePayments/AdaptivePaymentsService.php'; | |
} | |
/** | |
* | |
* | |
* @return unknown | |
*/ | |
public function paypal_ap_ipn() | |
{ | |
if ( empty( $_GET['paypal_chain_ipn'] ) || empty( $_GET['order_id'] ) ) return false; | |
$order_id = (int) $_GET['order_id']; | |
$order = new WC_Order( $order_id ); | |
if ( ! $order ) return false; | |
if ( $_POST['status'] !== 'COMPLETED' ) { | |
$order->update_status( 'failed', sprintf( __( 'Something went wrong. Response from PayPal invalidated this order. Status: %s.', 'wcvendors' ), $_POST['status'] ) ); | |
exit; | |
} | |
$order->payment_complete(); | |
$order->add_order_note( __( 'IPN payment completed', 'wcvendors' ) ); | |
if ( $this->instapay ) { | |
WCV_Commission::set_order_commission_paid( $order_id ); | |
} | |
exit; | |
} | |
/** | |
* Initialise Gateway Settings Form Fields | |
* | |
* @access public | |
* @return void | |
*/ | |
function init_form_fields() | |
{ | |
$this->form_fields = array(); | |
// List each option in order of appearance with details | |
$this->form_fields['enabled'] = array( | |
'title' => __( 'Enable PayPal Adaptive Payments', 'wcvendors' ), | |
'default' => 'no', | |
'type' => 'checkbox', | |
); | |
$this->form_fields['title'] = array( | |
'title' => __( 'Method Title', 'wcvendors' ), | |
'description' => __( 'This controls the title which the user sees during checkout.', 'wcvendors' ), | |
'default' => __( 'PayPal', 'wcvendors' ), | |
'type' => 'text' | |
); | |
$this->form_fields['description'] = array( | |
'title' => __( 'Description', 'wcvendors' ), | |
'description' => __( 'This controls the description which the user sees during checkout.', 'wcvendors' ), | |
'default' => __( "Pay via PayPal!", 'wcvendors' ), | |
'type' => 'textarea' | |
); | |
// ================================================================== | |
// | |
// Credentials | |
// | |
// ------------------------------------------------------------------ | |
$this->form_fields[] = array( | |
'title' => __( 'Live Credentials', 'wcvendors' ), | |
'type' => 'title', | |
'description' => sprintf( __( 'You must have an <a href="%s">Application ID</a> to process live transactions. You do not need one for testing in Sandbox mode.', 'wcvendors' ) | |
, 'https://developer.paypal.com/webapps/developer/docs/classic/lifecycle/goingLive/' ) | |
); | |
$this->form_fields['main_paypal_live'] = array( | |
'title' => __( 'PayPal Email', 'wcvendors' ), | |
'description' => __( 'The email address main payments should go to.', 'wcvendors' ), | |
'type' => 'text' | |
); | |
$this->form_fields['username_live'] = array( | |
'title' => __( 'API Username', 'wcvendors' ), | |
'type' => 'text' | |
); | |
$this->form_fields['password_live'] = array( | |
'title' => __( 'API Password', 'wcvendors' ), | |
'type' => 'text' | |
); | |
$this->form_fields['signature_live'] = array( | |
'title' => __( 'API Signature', 'wcvendors' ), | |
'type' => 'text' | |
); | |
$this->form_fields['app_id'] = array( | |
'title' => __( 'Application ID', 'wcvendors' ), | |
'type' => 'text', | |
'description' => __( 'Only required when doing live transactions.', 'wcvendors' ), | |
); | |
$this->form_fields[] = array( | |
'title' => __( 'Sandbox Credentials', 'wcvendors' ), | |
'type' => 'title', | |
'description' => sprintf( __( 'You can signup for a sandbox developer account <a href="%s">here</a>. You need a developer account if you want to enable Sandbox mode for testing.', 'wcvendors' ) | |
, 'https://developer.paypal.com/' ) | |
); | |
$this->form_fields['main_paypal'] = array( | |
'title' => __( 'PayPal Email', 'wcvendors' ), | |
'description' => __( 'The email address main payments should go to.', 'wcvendors' ), | |
'type' => 'text' | |
); | |
$this->form_fields['username'] = array( | |
'title' => __( 'API Username', 'wcvendors' ), | |
'type' => 'text' | |
); | |
$this->form_fields['password'] = array( | |
'title' => __( 'API Password', 'wcvendors' ), | |
'type' => 'text' | |
); | |
$this->form_fields['signature'] = array( | |
'title' => __( 'API Signature', 'wcvendors' ), | |
'type' => 'text' | |
); | |
// ================================================================== | |
// | |
// Misc. Settings | |
// | |
// ------------------------------------------------------------------ | |
$this->form_fields[] = array( | |
'title' => __( 'Misc. Settings', 'wcvendors' ), | |
'type' => 'title', | |
); | |
$this->form_fields['sandbox_enabled'] = array( | |
'title' => __( 'Enable PayPal Sandbox mode', 'wcvendors' ), | |
'default' => 'yes', | |
'type' => 'checkbox', | |
); | |
$this->form_fields['logging_enabled'] = array( | |
'title' => __( 'Enable logging', 'wcvendors' ), | |
'default' => 'no', | |
'type' => 'checkbox', | |
); | |
} | |
/** | |
* Admin Panel Options | |
* | |
* @access public | |
* @return void | |
*/ | |
function admin_options() | |
{ ?> | |
<h3><?php echo $this->method_title; ?></h3> | |
<p><?php _e( 'The PayPal Adaptive Payments gateway can instantly pay your vendors their due commission (if enabled). Also used to mass pay vendors on a schedule / manual method (if enabled).', 'wcvendors' ); ?></p> | |
<p><?php printf(__( '<b>Important:</b> Unless you\'re using the beta version of TRS2, all shipping costs will be given to the shop admin. Vendors will not receive shipping costs.', 'wcvendors' )); ?></p> | |
<table class="form-table"> | |
<?php if ( $this->is_valid_currency() ) : | |
// Generate the HTML For the settings form. | |
$this->generate_settings_html(); | |
else : ?> | |
<div class="inline error"><p><strong><?php _e( 'Gateway Disabled', 'wcvendors' ); ?></strong>: <?php printf( __( '%s does not support your store currency.', 'wcvendors' ), $this->method_title ); ?></p></div> | |
<?php endif; ?> | |
</table> | |
<?php | |
} | |
/** | |
* | |
* | |
* @param unknown $order | |
* @return unknown | |
*/ | |
private function get_receivers( $order ) | |
{ | |
$receivers = WCV_Vendors::get_vendor_dues_from_order( $order ); | |
$i = 0; $response = array(); | |
foreach ( $receivers as $author => $values ) { | |
if ( empty( $values['total'] ) ) continue; | |
$response[$i] = new Receiver(); | |
$response[$i]->email = $values['vendor_id'] == 1 ? $this->main_paypal : WCV_Vendors::get_vendor_paypal( $values['vendor_id'] ); | |
//$response[$i]->amount = $values['total']; | |
//$response[$i]->primary = false; | |
$response[$i]->amount = $values['vendor_id'] == 1 ? $order->order_total : $values['total']; | |
$response[$i]->primary = $values['vendor_id'] == 1 ? true : ''; | |
$response[$i]->invoiceId = $order->id; | |
$i++; | |
} | |
if ( $this->debug_me ) { | |
var_dump($response); | |
} | |
return $response; | |
} | |
/** | |
* | |
* | |
* @param unknown $order_id | |
* @return unknown | |
*/ | |
public function paypalap_check_form( $order_id ) | |
{ | |
global $woocommerce; | |
$this->include_paypal_sdk(); | |
$this->logger = new PPLoggingManager( 'Pay' ); | |
$order = new WC_Order( $order_id ); | |
$receivers = $this->get_receivers( $order ); | |
$receiverList = new ReceiverList( $receivers ); | |
$actionType = 'CREATE'; | |
$cancelUrl = $order->get_cancel_order_url(); | |
$currencyCode = get_woocommerce_currency(); | |
$returnUrl = add_query_arg( 'key', $order->order_key, add_query_arg( 'order', $order->id, get_permalink( apply_filters( 'woocommerce_get_checkout_redirect_page_id', woocommerce_get_page_id( 'thanks' ) ) ) ) ); | |
$payRequest = new PayRequest( new RequestEnvelope( "en_US" ), $actionType, $cancelUrl, $currencyCode, $receiverList, $returnUrl ); | |
// ================================================================== | |
// | |
// Optional params | |
// | |
// ------------------------------------------------------------------ | |
$payRequest->feesPayer = 'EACHRECEIVER'; | |
$args = array( | |
'wc-api' => 'WC_PayPalAP', | |
'paypal_chain_ipn' => '1', | |
'order_id' => $order_id, | |
); | |
$payRequest->ipnNotificationUrl = str_replace( 'https:', 'http:', add_query_arg( $args, home_url( '/' ) ) ); | |
$payRequest->memo = !empty( $order->customer_note ) ? $order->customer_note : ''; | |
$payRequest->reverseAllParallelPaymentsOnError = ''; | |
$service = new AdaptivePaymentsService(); | |
try { | |
$response = $service->Pay( $payRequest ); | |
} catch( Exception $ex ) { | |
$woocommerce->add_error( sprintf( __( 'Error: %s', 'wcvendors' ), $ex->getMessage() ) ); | |
return false; | |
} | |
$this->logger->log( "Received payResponse:" ); | |
$ack = strtoupper( $response->responseEnvelope->ack ); | |
if ( $ack != 'SUCCESS' ) { | |
$order->update_status( 'cancelled', sprintf( __( 'Error ID: %s. %s', 'wcvendors' ), $response->error[0]->errorId, $response->error[0]->message ) ); | |
$woocommerce->add_error( sprintf( __( 'Error ID: %s. %s', 'wcvendors' ), $response->error[0]->errorId, $response->error[0]->message ) ); | |
return false; | |
} | |
return $response->payKey; | |
} | |
/** | |
* | |
* | |
* @param unknown $order | |
* @param unknown $author_email | |
* @param unknown $setPaymentOptionsRequest | |
* @param unknown $is_admin (optional) | |
* @return unknown | |
*/ | |
public function set_vendor_items( $order, $setPaymentOptionsRequest ) | |
{ | |
$receivers = WCV_Vendors::get_vendor_dues_from_order( $order, false ); | |
foreach ( $receivers as $products ) { | |
$invoice_items = array(); | |
$shipping_given = $tax_given = 0; | |
foreach ($products as $key => $product) { | |
$product_id = $product['product_id']; | |
$is_vendor = WCV_Vendors::is_vendor( $product['vendor_id'] ); | |
$shipping_given += $product['shipping']; | |
$tax_given += $product['tax']; | |
if ( ! empty( $product['commission'] ) ) { | |
/* | |
$item = new InvoiceItem(); | |
$item->name = get_the_title( $product_id ); | |
$item->identifier = $product_id; | |
$item->price = $product['commission']; | |
$item->itemPrice = round( $product['commission'] / $product['qty'], 2 ); | |
$item->itemCount = $product['qty']; | |
$invoice_items[] = $item; | |
*/ | |
} | |
if ($product['vendor_id'] != 1) | |
{ | |
$item = new InvoiceItem(); | |
$item->name = get_the_title( $product_id ); | |
$item->identifier = $product_id; | |
$item->price = $product['commission']; | |
$item->itemPrice = round( $product['commission'] / $product['qty'], 2 ); | |
$item->itemCount = $product['qty']; | |
$invoice_items[] = $item; | |
} | |
} | |
if ( empty( $invoice_items ) ) { | |
continue; | |
} | |
$receiverOptions = new ReceiverOptions(); | |
$setPaymentOptionsRequest->receiverOptions[] = $receiverOptions; | |
// Set the current vendor | |
$receiverId = new ReceiverIdentifier(); | |
$receiverId->email = $product['vendor_id'] == 1 ? $this->main_paypal : WCV_Vendors::get_vendor_paypal( $product['vendor_id'] ); | |
$receiverOptions->receiver = $receiverId; | |
$receiverOptions->invoiceData = new InvoiceData(); | |
$receiverOptions->invoiceData->item = $invoice_items; | |
$receiverOptions->invoiceData->totalTax = $tax_given; | |
$receiverOptions->invoiceData->totalShipping = $shipping_given; | |
} | |
return $setPaymentOptionsRequest; | |
} | |
/** | |
* | |
* | |
* @param unknown $pay_key | |
* @param unknown $order_id | |
* @return unknown | |
*/ | |
public function set_paypal_author_specifics( $pay_key, $order_id ) | |
{ | |
global $woocommerce; | |
$this->include_paypal_sdk(); | |
$order = new WC_Order( $order_id ); | |
// Create request | |
$setPaymentOptionsRequest = new SetPaymentOptionsRequest( new RequestEnvelope( "en_US" ) ); | |
$setPaymentOptionsRequest->payKey = $pay_key; | |
if ( $this->instapay ) { | |
$setPaymentOptionsRequest = $this->set_vendor_items( $order, $setPaymentOptionsRequest ); | |
} | |
if ( $this->debug_me ) { | |
foreach ( $setPaymentOptionsRequest->receiverOptions as $k ) { | |
var_dump( $k->invoiceData ); | |
} | |
exit; | |
} | |
$setPaymentOptionsRequest->senderOptions = new SenderOptions(); | |
$setPaymentOptionsRequest->senderOptions->requireShippingAddressSelection = true; | |
$service = new AdaptivePaymentsService(); | |
try { | |
$response = $service->SetPaymentOptions( $setPaymentOptionsRequest ); | |
} catch( Exception $ex ) { | |
if ( function_exists('wc_add_error') ) wc_add_error( sprintf( __( 'Error: %s', 'wcvendors' ), $ex->getMessage() ) ); else $woocommerce->add_error( sprintf( __( 'Error: %s', 'wcvendors' ), $ex->getMessage() ) ); | |
return false; | |
} | |
$this->logger->error( "Received SetPaymentOptionsResponse:" ); | |
$ack = strtoupper( $response->responseEnvelope->ack ); | |
if ( $ack != "SUCCESS" ) { | |
$order->update_status( 'cancelled', __( sprintf( 'Error ID: %s. %s', $response->error[0]->errorId, $response->error[0]->message ), 'wcvendors' ) ); | |
if ( function_exists('wc_add_error') ) wc_add_error( sprintf( 'Error ID: %s. %s', $response->error[0]->errorId, $response->error[0]->message ) ); else $woocommerce->add_error( sprintf( 'Error ID: %s. %s', $response->error[0]->errorId, $response->error[0]->message ) ); | |
return false; | |
} | |
return true; | |
} | |
/** | |
* Payment fields | |
*/ | |
function payment_fields() | |
{ | |
if ( $description = $this->settings['description'] ) echo wpautop( wptexturize( $this->description ) ); | |
} | |
/** | |
* Process the payment and return the result | |
* | |
* @param unknown $order_id | |
* @return unknown | |
*/ | |
function process_payment( $order_id ) | |
{ | |
global $woocommerce; | |
$order = new WC_Order( $order_id ); | |
$pay_key = $this->paypalap_check_form( $order_id ); | |
if ( !empty( $woocommerce->errors ) ) return false; | |
if ( $this->instapay ) { | |
$this->set_paypal_author_specifics( $pay_key, $order_id ); | |
if ( !empty( $woocommerce->errors ) ) return false; | |
} | |
$paypal_redirect_url = $this->sandbox == 'yes' ? 'https://www.sandbox.paypal.com/webscr&cmd=' : 'https://www.paypal.com/webscr&cmd='; | |
$pay_url = $paypal_redirect_url . '_ap-payment&paykey=' . $pay_key; | |
return array( | |
'result' => 'success', | |
'redirect' => $pay_url, | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment