Version 4.7.0

This commit is contained in:
Neo committed 2025-12-19 16:00:35 -08:00
1 parent 517a5e1f70
commit 8ba7d43898
1933 files changed
+65613 -11332

No files matched your search

@@ -47,12 +47,6 @@ class _PayPal extends \IPS\nexus\Gateway
return FALSE;
}
/* Billing agreements require a billing address */
elseif ( static::_canProcessRecurringsAsBillingAgreement( $recurrings ) and ( isset( $settings['billing_agreements'] ) and $settings['billing_agreements'] == 'required' ) and !$billingAddress )
{
return FALSE;
}
/* Check transaction limit */
switch ( $amount->currency )
{
@@ -538,7 +532,7 @@ class _PayPal extends \IPS\nexus\Gateway
'description' => $description,
'billing_cycles' => array(),
'payment_preferences' => array(
'auto_bill_outstanding' => TRUE,
'auto_bill_outstanding' => FALSE,
'payment_failure_threshold' => \intval( $settings['billing_agreement_allowed_fails'] )
),
'taxes' => array(
@@ -618,29 +612,36 @@ class _PayPal extends \IPS\nexus\Gateway
public function void( \IPS\nexus\Transaction $transaction )
{
/* If this is is the intitial transaction for a billing agreement which hasn't
been processed yet, cancel the billing agreement */
been processed yet, cancel the billing agreement. If it's a subscription it may still be the first payment */
if ( $transaction->status === $transaction::STATUS_GATEWAY_PENDING and $transaction->billing_agreement )
{
$transaction->billing_agreement->cancel();
return;
}
/* Try to find the authorization ID */
if ( mb_substr( $transaction->gw_id, 0, 4 ) === 'PAY-' )
{
$authId = NULL;
$payment = $this->api( "payments/payment/{$transaction->gw_id}", NULL, 'get' );
foreach ( $payment['transactions'][0]['related_resources'] as $rr )
try
{
if ( isset( $rr['authorization'] ) )
$payment = $this->api( "payments/payment/{$transaction->gw_id}", NULL, 'get' );
foreach ( $payment['transactions'][0]['related_resources'] as $rr )
{
$authId = $rr['authorization']['id'];
if ( isset( $rr['authorization'] ) )
{
$authId = $rr['authorization']['id'];
}
}
if ( !$authId )
{
throw new \RuntimeException;
}
}
if ( !$authId )
/* Let's try the gateway id as the auth id */
catch ( \IPS\nexus\Gateway\PayPal\Exception $e )
{
throw new \RuntimeException;
$authId = $transaction->gw_id;
}
}
else
@@ -683,24 +684,53 @@ class _PayPal extends \IPS\nexus\Gateway
if ( $billingAgreement = $transaction->billing_agreement )
{
$response = 'WAIT';
$transactions = $this->api( "payments/billing-agreements/{$transaction->billing_agreement->gw_id}/transactions?start_date=" . date( 'Y-m-d', $transaction->date->getTimestamp() - 86400 ) . '&end_date=' . date( 'Y-m-d' ), NULL, 'get' );
foreach ( $transactions['agreement_transaction_list'] as $t )
/* Subscriptions API */
if( $data = $billingAgreement->_getData() AND isset( $data['plan_id'] ) )
{
if ( ( !$transaction->gw_id or $transaction->gw_id == $t['transaction_id'] ) and $transaction->amount->currency == $t['amount']['currency'] and $transaction->amount->amountAsString() == $t['amount']['value'] )
{
if ( $t['status'] == 'Completed' )
$transactions = $this->api( "billing/subscriptions/{$transaction->billing_agreement->gw_id}/transactions?start_time=" . \IPS\DateTime::ts( $transaction->date->getTimestamp() - 86400 )->rfc3339() . '&end_time=' . \IPS\DateTime::ts( time() )->rfc3339(), NULL, 'get' );
foreach ( $transactions['transactions'] as $t )
{
if ( ( !$transaction->gw_id or $transaction->gw_id == $t['id'] ) and $transaction->amount->currency == $t['amount_with_breakdown']['gross_amount']['currency_code'] and $transaction->amount->amountAsString() == $t['amount_with_breakdown']['gross_amount']['value'] )
{
$transaction->gw_id = $t['transaction_id'];
$transaction->save();
return TRUE;
if ( $t['status'] == 'COMPLETED' )
{
$transaction->gw_id = $t['id'];
$transaction->save();
return TRUE;
}
elseif ( $t['status'] == 'REFUNDED' )
{
$response = 'RFND';
}
elseif ( $t['status'] == 'DECLINED' )
{
$response = 'FAIL';
}
}
elseif ( $t['status'] == 'Refunded' )
}
}
/* Legacy Billing Agreements */
else
{
$transactions = $this->api( "payments/billing-agreements/{$transaction->billing_agreement->gw_id}/transactions?start_date=" . date( 'Y-m-d', $transaction->date->getTimestamp() - 86400 ) . '&end_date=' . date( 'Y-m-d' ), NULL, 'get' );
foreach ( $transactions['agreement_transaction_list'] as $t )
{
if ( ( !$transaction->gw_id or $transaction->gw_id == $t['transaction_id'] ) and $transaction->amount->currency == $t['amount']['currency'] and $transaction->amount->amountAsString() == $t['amount']['value'] )
{
$response = 'RFND';
}
elseif ( $t['status'] == 'Failed' )
{
$response = 'FAIL';
if ( $t['status'] == 'Completed' )
{
$transaction->gw_id = $t['transaction_id'];
$transaction->save();
return TRUE;
}
elseif ( $t['status'] == 'Refunded' )
{
$response = 'RFND';
}
elseif ( $t['status'] == 'Failed' )
{
$response = 'FAIL';
}
}
}
}
@@ -781,9 +811,21 @@ class _PayPal extends \IPS\nexus\Gateway
{
/* The capture ID is *normally* the gateway transaction ID */
$captureId = $transaction->gw_id;
/* Refund Amount */
$amount = $amount ? new \IPS\nexus\Money( $amount, $transaction->currency ) : $transaction->amount;
/* If it's a billing agreement and the gateway ID isn't prefixed with an I, it's likely to be a subscription */
if( $transaction->billing_agreement AND $transaction->gw_id AND mb_substr( $transaction->gw_id, 0, 2 ) !== 'I-' )
{
$response = $this->api( "payments/sale/{$transaction->gw_id}/refund", array( 'amount' => array(
'currency' => $amount->currency,
'total' => $amount->amountAsString()
) ) );
return $response['id'];
}
/* But if it starts with I- (or is a blank but known to be a billing agreement payment) - that's a billing agreement */
if ( ( $transaction->billing_agreement and !$transaction->gw_id ) or ( mb_substr( $transaction->gw_id, 0, 2 ) === 'I-' ) )
elseif ( ( $transaction->billing_agreement and !$transaction->gw_id ) or ( mb_substr( $transaction->gw_id, 0, 2 ) === 'I-' ) )
{
$transactions = $this->api( "payments/billing-agreements/{$transaction->billing_agreement->gw_id}/transactions?start_date=" . $transaction->date->sub( new \DateInterval('P1D') )->format('Y-m-d') . '&end_date=' . $transaction->date->format('Y-m-d'), NULL, 'get' );
foreach ( $transactions['agreement_transaction_list'] as $t )
@@ -813,7 +855,6 @@ class _PayPal extends \IPS\nexus\Gateway
}
/* Process Refund */
$amount = $amount ? new \IPS\nexus\Money( $amount, $transaction->currency ) : $transaction->amount;
$response = $this->api( "payments/capture/{$captureId}/refund", array( 'amount' => array(
'currency' => $amount->currency,
'total' => $amount->amountAsString()
@@ -1157,8 +1198,11 @@ class _PayPal extends \IPS\nexus\Gateway
if ( \count( $recurrings ) == 1 )
{
$recurrance = array_pop( $recurrings );
if ( $recurrance['dueDate']->getTimestamp() === \IPS\DateTime::create()->add( $recurrance['term']->interval )->getTimestamp() )
/* We need to allow for some minor deviation than checking for the exact second, this can happen if the request is at just the exact time where
the clock ticks over to the next second */
$difference = \IPS\DateTime::create()->add( $recurrance['term']->interval )->getTimestamp() - $recurrance['dueDate']->getTimestamp();
if ( $difference >= 0 AND $difference < 10 )
{
return TRUE;
}