Version 5.0.0 beta 1
This commit is contained in:
1 parent
25ddeb65d6
commit
15c7beabc5
6736 files changed
+627902
-497943
No files matched your search
@@ -12,43 +12,66 @@
|
||||
namespace IPS\nexus\Customer;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use DomainException;
|
||||
use Exception;
|
||||
use IPS\Helpers\Form;
|
||||
use IPS\Helpers\Form\Radio;
|
||||
use IPS\Member;
|
||||
use IPS\nexus\Customer;
|
||||
use IPS\nexus\Gateway;
|
||||
use IPS\nexus\Invoice;
|
||||
use IPS\nexus\Transaction;
|
||||
use IPS\Patterns\ActiveRecord;
|
||||
use IPS\Theme;
|
||||
use function count;
|
||||
use function defined;
|
||||
use function is_array;
|
||||
use function strlen;
|
||||
use function substr;
|
||||
|
||||
/* @property Customer $member
|
||||
* @property \IPS\nexus\CreditCard $card
|
||||
*/
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Customer Stored Card Model
|
||||
*/
|
||||
class _CreditCard extends \IPS\Patterns\ActiveRecord
|
||||
|
||||
/* @property Customer $member */
|
||||
class CreditCard extends ActiveRecord
|
||||
{
|
||||
/**
|
||||
* @brief Multiton Store
|
||||
*/
|
||||
protected static $multitons;
|
||||
protected static array $multitons;
|
||||
|
||||
/**
|
||||
* @brief Database Table
|
||||
*/
|
||||
public static $databaseTable = 'nexus_customer_cards';
|
||||
public static ?string $databaseTable = 'nexus_customer_cards';
|
||||
|
||||
/**
|
||||
* @brief Database Prefix
|
||||
*/
|
||||
public static $databasePrefix = 'card_';
|
||||
public static string $databasePrefix = 'card_';
|
||||
|
||||
/**
|
||||
* Construct ActiveRecord from database row
|
||||
*
|
||||
* @param array $data Row from database table
|
||||
* @param bool $updateMultitonStoreIfExists Replace current object in multiton store if it already exists there?
|
||||
* @return static
|
||||
* @param array $data Row from database table
|
||||
* @param bool $updateMultitonStoreIfExists Replace current object in multiton store if it already exists there?
|
||||
* @return static
|
||||
*/
|
||||
public static function constructFromData( $data, $updateMultitonStoreIfExists = TRUE )
|
||||
public static function constructFromData( array $data, bool $updateMultitonStoreIfExists = TRUE ): static
|
||||
{
|
||||
$gateway = \IPS\nexus\Gateway::load( $data['card_method'] );
|
||||
$classname = \IPS\nexus\Gateway::gateways()[ $gateway->gateway ] . '\\CreditCard';
|
||||
$gateway = Gateway::load( $data['card_method'] );
|
||||
$classname = Gateway::gateways()[ $gateway->gateway ] . '\\CreditCard';
|
||||
|
||||
/* Initiate an object */
|
||||
$obj = new $classname;
|
||||
@@ -57,13 +80,13 @@ class _CreditCard extends \IPS\Patterns\ActiveRecord
|
||||
/* Import data */
|
||||
if ( static::$databasePrefix )
|
||||
{
|
||||
$databasePrefixLength = \strlen( static::$databasePrefix );
|
||||
$databasePrefixLength = strlen( static::$databasePrefix );
|
||||
}
|
||||
foreach ( $data as $k => $v )
|
||||
{
|
||||
if( static::$databasePrefix AND mb_strpos( $k, static::$databasePrefix ) === 0 )
|
||||
{
|
||||
$k = \substr( $k, $databasePrefixLength );
|
||||
$k = substr( $k, $databasePrefixLength );
|
||||
}
|
||||
|
||||
$obj->_data[ $k ] = $v;
|
||||
@@ -83,13 +106,13 @@ class _CreditCard extends \IPS\Patterns\ActiveRecord
|
||||
/**
|
||||
* Add Form
|
||||
*
|
||||
* @param \IPS\nexus\Customer $customer The customer
|
||||
* @param Customer $customer The customer
|
||||
* @param bool $admin Set to TRUE if the *admin* (opposed to the customer themselves) wants to create a new payment method
|
||||
* @return \IPS\Helpers\Form|\IPS\nexus\CreditCard
|
||||
* @return string|CreditCard
|
||||
*/
|
||||
public static function create( \IPS\nexus\Customer $customer, $admin )
|
||||
public static function create( Customer $customer, bool $admin ) : string|CreditCard
|
||||
{
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form = new Form;
|
||||
$showSubmitButton = FALSE;
|
||||
$hiddenValues = array();
|
||||
foreach ( static::createFormElements( $customer, $admin, $showSubmitButton, $hiddenValues ) as $element )
|
||||
@@ -107,62 +130,33 @@ class _CreditCard extends \IPS\Patterns\ActiveRecord
|
||||
{
|
||||
return static::createFormSubmit( $values, $customer, $admin );
|
||||
}
|
||||
catch ( \DomainException $e )
|
||||
catch ( DomainException $e )
|
||||
{
|
||||
$form->error = $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
return $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'forms', 'nexus', 'global' ), 'addPaymentMethodForm' ), $showSubmitButton );
|
||||
return $form->customTemplate( array( Theme::i()->getTemplate( 'forms', 'nexus', 'global' ), 'addPaymentMethodForm' ), $showSubmitButton );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get form elements for creating a new card
|
||||
*
|
||||
* @param \IPS\nexus\Customer $customer The customer
|
||||
* @param Customer $customer The customer
|
||||
* @param bool $admin Set to TRUE if the *admin* (opposed to the customer themselves) wants to create a new payment method
|
||||
* @param bool $showSubmitButton Will be set to a bool indicating if the submit button should be shown
|
||||
* @param array $hiddenValues Hidden values to add to the form
|
||||
* @param array|null $allowedPaymentMethods Payment method IDs that should be included. Populated when called from checkout.
|
||||
* @return array
|
||||
*/
|
||||
public static function createFormElements( \IPS\nexus\Customer $customer, $admin, &$showSubmitButton, &$hiddenValues, $allowedPaymentMethods=null )
|
||||
public static function createFormElements( Customer $customer, bool $admin, bool &$showSubmitButton, array &$hiddenValues ) : array
|
||||
{
|
||||
$gateways = \IPS\nexus\Gateway::cardStorageGateways( $admin );
|
||||
|
||||
/* Remove any gateways that can't be used here */
|
||||
if( !empty( $allowedPaymentMethods ) )
|
||||
{
|
||||
foreach( $gateways as $id => $gateway )
|
||||
{
|
||||
if( !\in_array( $id, $allowedPaymentMethods ) )
|
||||
{
|
||||
unset( $gateways[ $id ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif( $address = $customer->primaryBillingAddress() )
|
||||
{
|
||||
/* If we're not coming from the checkout, we're trying to manually add a card.
|
||||
Check the user's country, and if it's not available, skip it */
|
||||
foreach( $gateways as $id => $gateway )
|
||||
{
|
||||
/* @var \IPS\nexus\Gateway $gateway */
|
||||
if( $gateway->countries !== '*' )
|
||||
{
|
||||
if( !\in_array( $address->country, explode( ',', $gateway->countries ) ) )
|
||||
{
|
||||
unset( $gateways[ $id ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$gateways = Gateway::cardStorageGateways( $admin );
|
||||
|
||||
$elements = array();
|
||||
$paymentMethodsToggles = array();
|
||||
foreach ( $gateways as $gateway )
|
||||
{
|
||||
$invoice = new \IPS\nexus\Invoice;
|
||||
$invoice = new Invoice;
|
||||
$invoice->currency = $customer->defaultCurrency();
|
||||
foreach ( $gateway->paymentScreen( $invoice, $invoice->total, $customer, array(), 'card' ) as $element )
|
||||
{
|
||||
@@ -179,11 +173,10 @@ class _CreditCard extends \IPS\Patterns\ActiveRecord
|
||||
}
|
||||
}
|
||||
|
||||
if ( \count( $gateways ) > 1 )
|
||||
if ( count( $gateways ) > 1 )
|
||||
{
|
||||
$showSubmitButton = FALSE;
|
||||
$options = array();
|
||||
$toggles = array();
|
||||
foreach ( $gateways as $gateway )
|
||||
{
|
||||
$options[ $gateway->id ] = $gateway->_title;
|
||||
@@ -194,8 +187,8 @@ class _CreditCard extends \IPS\Patterns\ActiveRecord
|
||||
}
|
||||
}
|
||||
|
||||
$element = new \IPS\Helpers\Form\Radio( 'payment_method', NULL, TRUE, array( 'options' => $options, 'toggles' => $paymentMethodsToggles ) );
|
||||
$element->label = \IPS\Member::loggedIn()->language()->addToStack('card_gateway');
|
||||
$element = new Radio( 'payment_method', NULL, TRUE, array( 'options' => $options, 'toggles' => $paymentMethodsToggles ) );
|
||||
$element->label = Member::loggedIn()->language()->addToStack('card_gateway');
|
||||
|
||||
array_unshift( $elements, $element );
|
||||
}
|
||||
@@ -215,41 +208,41 @@ class _CreditCard extends \IPS\Patterns\ActiveRecord
|
||||
* Handle submission of the form for creating a new card
|
||||
*
|
||||
* @param array $values Values from the form
|
||||
* @param \IPS\nexus\Customer $customer The customer
|
||||
* @param Customer $customer The customer
|
||||
* @param bool $admin Set to TRUE if the *admin* (opposed to the customer themselves) wants to create a new payment method
|
||||
* @param ?\IPS\nexus\Invoice $invoice If customer is a guest, will sa`ve the guest data onto the provided invoice
|
||||
* @return \IPS\nexus\CreditCard
|
||||
* @throws \DomainException
|
||||
* @param ?Invoice $invoice If customer is a guest, will sa`ve the guest data onto the provided invoice
|
||||
* @return CreditCard
|
||||
* @throws DomainException
|
||||
*/
|
||||
public static function createFormSubmit( $values, $customer, $admin, \IPS\nexus\Invoice $invoice = NULL )
|
||||
public static function createFormSubmit( array $values, Customer $customer, bool $admin, ?Invoice $invoice = NULL ) : CreditCard
|
||||
{
|
||||
if ( isset( $values['payment_method'] ) )
|
||||
{
|
||||
if ( $values['payment_method'] != 0 )
|
||||
{
|
||||
$gateway = \IPS\nexus\Gateway::load( $values['payment_method'] );
|
||||
$gateway = Gateway::load( $values['payment_method'] );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$gateways = \IPS\nexus\Gateway::cardStorageGateways( $admin );
|
||||
$gateways = Gateway::cardStorageGateways( $admin );
|
||||
$gateway = array_pop( $gateways );
|
||||
}
|
||||
|
||||
if ( !$values[ $gateway->id . '_card' ] )
|
||||
{
|
||||
throw new \DomainException( \IPS\Member::loggedIn()->language()->addToStack('card_number_invalid') );
|
||||
throw new DomainException( Member::loggedIn()->language()->addToStack('card_number_invalid') );
|
||||
}
|
||||
else
|
||||
{
|
||||
$classname = \IPS\nexus\Gateway::gateways()[ $gateway->gateway ] . '\\CreditCard';
|
||||
$classname = Gateway::gateways()[ $gateway->gateway ] . '\\CreditCard';
|
||||
$card = new $classname;
|
||||
$card->member = $customer;
|
||||
$card->method = $gateway;
|
||||
|
||||
if ( \is_array( $values[ $gateway->id . '_card' ] ) )
|
||||
if ( is_array( $values[ $gateway->id . '_card' ] ) )
|
||||
{
|
||||
$_card = new \IPS\nexus\CreditCard;
|
||||
$_card = new CreditCard;
|
||||
$_card->token = $values[ $gateway->id . '_card' ]['token'];
|
||||
$card->set_card( $_card, $invoice );
|
||||
}
|
||||
@@ -268,20 +261,20 @@ class _CreditCard extends \IPS\Patterns\ActiveRecord
|
||||
/**
|
||||
* Get member
|
||||
*
|
||||
* @return \IPS\Member
|
||||
* @return Customer
|
||||
*/
|
||||
public function get_member()
|
||||
public function get_member() : Customer
|
||||
{
|
||||
return \IPS\nexus\Customer::load( $this->_data['member'] );
|
||||
return Customer::load( $this->_data['member'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set member
|
||||
*
|
||||
* @param \IPS\Member $member Member
|
||||
* @param Member $member Member
|
||||
* @return void
|
||||
*/
|
||||
public function set_member( \IPS\Member $member )
|
||||
public function set_member( Member $member ) : void
|
||||
{
|
||||
$this->_data['member'] = $member->member_id ?: 0;
|
||||
}
|
||||
@@ -289,21 +282,83 @@ class _CreditCard extends \IPS\Patterns\ActiveRecord
|
||||
/**
|
||||
* Get payment gateway
|
||||
*
|
||||
* @return \IPS\nexus\Gateway
|
||||
* @return Gateway
|
||||
*/
|
||||
public function get_method()
|
||||
public function get_method() : Gateway
|
||||
{
|
||||
return \IPS\nexus\Gateway::load( $this->_data['method'] );
|
||||
return Gateway::load( $this->_data['method'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set payment gateway
|
||||
*
|
||||
* @param \IPS\nexus\Gateway $gateway Payment gateway
|
||||
* @param Gateway $gateway Payment gateway
|
||||
* @return void
|
||||
*/
|
||||
public function set_method( \IPS\nexus\Gateway $gateway )
|
||||
public function set_method( Gateway $gateway ) : void
|
||||
{
|
||||
$this->_data['method'] = $gateway->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatically take payment
|
||||
*
|
||||
* @param Invoice $invoice
|
||||
* @return Transaction
|
||||
* @throws Exception
|
||||
*/
|
||||
public function takePayment( Invoice $invoice ) : Transaction
|
||||
{
|
||||
$cardDetails = $this->card; // We're just checking this doesn't throw an exception
|
||||
|
||||
$amountToPay = $invoice->amountToPay();
|
||||
$gateway = $this->method;
|
||||
|
||||
$transaction = new Transaction;
|
||||
$transaction->member = $invoice->member;
|
||||
$transaction->invoice = $invoice;
|
||||
$transaction->method = $gateway;
|
||||
$transaction->amount = $amountToPay;
|
||||
$transaction->currency = $amountToPay->currency;
|
||||
$transaction->extra = array( 'automatic' => TRUE );
|
||||
|
||||
try
|
||||
{
|
||||
$transaction->auth = $gateway->auth( $transaction, array(
|
||||
( $gateway->id . '_card' ) => $this
|
||||
), NULL, array(), 'renewal' );
|
||||
$transaction->capture();
|
||||
|
||||
$transaction->member->log( 'transaction', array(
|
||||
'type' => 'paid',
|
||||
'status' => Transaction::STATUS_PAID,
|
||||
'id' => $transaction->id,
|
||||
'invoice_id' => $invoice->id,
|
||||
'invoice_title' => $invoice->title,
|
||||
'automatic' => TRUE,
|
||||
), FALSE );
|
||||
|
||||
$transaction->approve();
|
||||
return $transaction;
|
||||
}
|
||||
catch ( Exception $e )
|
||||
{
|
||||
$transaction->status = Transaction::STATUS_REFUSED;
|
||||
$extra = $transaction->extra;
|
||||
$extra['history'][] = array( 's' => Transaction::STATUS_REFUSED, 'noteRaw' => $e->getMessage() );
|
||||
$transaction->extra = $extra;
|
||||
$transaction->save();
|
||||
|
||||
$transaction->member->log( 'transaction', array(
|
||||
'type' => 'paid',
|
||||
'status' => Transaction::STATUS_REFUSED,
|
||||
'id' => $transaction->id,
|
||||
'invoice_id' => $invoice->id,
|
||||
'invoice_title' => $invoice->title,
|
||||
'automatic' => TRUE,
|
||||
), FALSE );
|
||||
|
||||
return $transaction;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user