/**
  * @param Order $order - the order that is being paid
  * @param Form $form - the form that is being submitted
  * @param Array $data - Array of data that is submittted
  * @return Boolean - true if the data is valid
  */
 public static function validate_payment(Order $order, Form $form, array $data)
 {
     if (!$order) {
         $form->sessionMessage(_t('EcommercePayment.NOORDER', 'Order not found.'), 'bad');
         return false;
     }
     //nothing to pay, always valid
     if ($order->TotalOutstanding() == 0) {
         return true;
     }
     $hasValidPaymentClass = false;
     $paymentClass = !empty($data['PaymentMethod']) ? $data['PaymentMethod'] : null;
     if ($paymentClass) {
         if (class_exists($paymentClass)) {
             $paymentClass = new $paymentClass();
             if ($paymentClass instanceof EcommercePayment) {
                 $hasValidPaymentClass = true;
             }
         }
     }
     if (!$hasValidPaymentClass) {
         $form->sessionMessage(_t('EcommercePayment.NOPAYMENTOPTION', 'No Payment option selected.'), 'bad');
         return false;
     }
     // Check payment, get the result back
     return $paymentClass->validatePayment($data, $form);
 }
 public function __construct($controller, $name, Order $order)
 {
     $this->order = $order;
     $fields = FieldList::create(HiddenField::create('OrderID', '', $order->ID));
     $actions = FieldList::create();
     //payment
     if (self::config()->allow_paying && $order->canPay()) {
         $gateways = GatewayInfo::get_supported_gateways();
         //remove manual gateways
         foreach ($gateways as $gateway => $gatewayname) {
             if (GatewayInfo::is_manual($gateway)) {
                 unset($gateways[$gateway]);
             }
         }
         if (!empty($gateways)) {
             $fields->push(HeaderField::create("MakePaymentHeader", _t("OrderActionsForm.MAKEPAYMENT", "Make Payment")));
             $outstandingfield = Currency::create();
             $outstandingfield->setValue($order->TotalOutstanding());
             $fields->push(LiteralField::create("Outstanding", sprintf(_t("OrderActionsForm.OUTSTANDING", "Outstanding: %s"), $outstandingfield->Nice())));
             $fields->push(OptionsetField::create('PaymentMethod', _t("OrderActionsForm.PAYMENTMETHOD", "Payment Method"), $gateways, key($gateways)));
             $actions->push(FormAction::create('dopayment', _t('OrderActionsForm.PAYORDER', 'Pay outstanding balance')));
         }
     }
     //cancelling
     if (self::config()->allow_cancelling && $order->canCancel()) {
         $actions->push(FormAction::create('docancel', _t('OrderActionsForm.CANCELORDER', 'Cancel this order')));
     }
     parent::__construct($controller, $name, $fields, $actions);
     $this->extend("updateForm", $order);
 }
 public function testRounding()
 {
     //create an order with unrounded total
     $order = new Order(array('Total' => 123.257323, 'Status' => 'Unpaid'));
     $order->Total = 123.257323;
     //setTotal IS called here
     $this->assertEquals(123.26, $order->Total(), "Check total rounds appropriately");
     $this->assertEquals(123.26, $order->TotalOutstanding(), "Check total outstanding rounds appropriately");
 }
 public function __construct($controller, $name, Order $order)
 {
     $this->order = $order;
     $fields = FieldList::create(HiddenField::create('OrderID', '', $order->ID));
     $actions = FieldList::create();
     //payment
     if (self::config()->allow_paying && $order->canPay()) {
         $gateways = GatewayInfo::getSupportedGateways();
         //remove manual gateways
         foreach ($gateways as $gateway => $gatewayname) {
             if (GatewayInfo::isManual($gateway)) {
                 unset($gateways[$gateway]);
             }
         }
         if (!empty($gateways)) {
             $fields->push(HeaderField::create("MakePaymentHeader", _t("OrderActionsForm.MakePayment", "Make Payment")));
             $outstandingfield = Currency::create();
             $outstandingfield->setValue($order->TotalOutstanding(true));
             $fields->push(LiteralField::create("Outstanding", _t('Order.OutstandingWithAmount', 'Outstanding: {Amount}', '', array('Amount' => $outstandingfield->Nice()))));
             $fields->push(OptionsetField::create('PaymentMethod', _t("OrderActionsForm.PaymentMethod", "Payment Method"), $gateways, key($gateways)));
             if ($ccFields = $this->getCCFields($gateways)) {
                 if ($this->config()->include_jquery) {
                     Requirements::javascript(THIRDPARTY_DIR . '/jquery/jquery.min.js');
                 }
                 Requirements::javascript(SHOP_DIR . '/javascript/OrderActionsForm.js');
                 $fields->push($ccFields);
             }
             $actions->push(FormAction::create('dopayment', _t('OrderActionsForm.PayOrder', 'Pay outstanding balance')));
         }
     }
     //cancelling
     if (self::config()->allow_cancelling && $order->canCancel()) {
         $actions->push(FormAction::create('docancel', _t('OrderActionsForm.CancelOrder', 'Cancel this order')));
     }
     parent::__construct($controller, $name, $fields, $actions, OrderActionsForm_Validator::create(array('PaymentMethod')));
     $this->extend("updateForm", $order);
 }
 /**
  * Takes an order from being a cart to awaiting payment.
  *
  * @param Member $member - assign a member to the order
  *
  * @return boolean - success/failure
  */
 public function placeOrder()
 {
     if (!$this->order) {
         $this->error(_t("OrderProcessor.NoOrderStarted", "A new order has not yet been started."));
         return false;
     }
     if (!$this->canPlace($this->order)) {
         //final cart validation
         return false;
     }
     if ($this->order->Locale) {
         ShopTools::install_locale($this->order->Locale);
     }
     // recalculate order to be sure we have the correct total
     $this->order->calculate();
     if (ShopTools::DBConn()->supportsTransactions()) {
         ShopTools::DBConn()->transactionStart();
     }
     //update status
     if ($this->order->TotalOutstanding(false)) {
         $this->order->Status = 'Unpaid';
     } else {
         $this->order->Status = 'Paid';
     }
     if (!$this->order->Placed) {
         $this->order->Placed = SS_Datetime::now()->Rfc2822();
         //record placed order datetime
         if ($request = Controller::curr()->getRequest()) {
             $this->order->IPAddress = $request->getIP();
             //record client IP
         }
     }
     // Add an error handler that throws an exception upon error, so that we can catch errors as exceptions
     // in the following block.
     set_error_handler(function ($severity, $message, $file, $line) {
         throw new ErrorException($message, 0, $severity, $file, $line);
     }, E_ALL & ~(E_STRICT | E_NOTICE));
     try {
         //re-write all attributes and modifiers to make sure they are up-to-date before they can't be changed again
         $items = $this->order->Items();
         if ($items->exists()) {
             foreach ($items as $item) {
                 $item->onPlacement();
                 $item->write();
             }
         }
         $modifiers = $this->order->Modifiers();
         if ($modifiers->exists()) {
             foreach ($modifiers as $modifier) {
                 $modifier->write();
             }
         }
         //add member to order & customers group
         if ($member = Member::currentUser()) {
             if (!$this->order->MemberID) {
                 $this->order->MemberID = $member->ID;
             }
             $cgroup = ShopConfig::current()->CustomerGroup();
             if ($cgroup->exists()) {
                 $member->Groups()->add($cgroup);
             }
         }
         //allow decorators to do stuff when order is saved.
         $this->order->extend('onPlaceOrder');
         $this->order->write();
     } catch (Exception $ex) {
         // Rollback the transaction if an error occurred
         if (ShopTools::DBConn()->supportsTransactions()) {
             ShopTools::DBConn()->transactionRollback();
         }
         $this->error($ex->getMessage());
         return false;
     } finally {
         // restore the error handler, no matter what
         restore_error_handler();
     }
     // Everything went through fine, complete the transaction
     if (ShopTools::DBConn()->supportsTransactions()) {
         ShopTools::DBConn()->transactionEnd();
     }
     //remove from session
     $cart = ShoppingCart::curr();
     if ($cart && $cart->ID == $this->order->ID) {
         // clear the cart, but don't write the order in the process (order is finalized and should NOT be overwritten)
         ShoppingCart::singleton()->clear(false);
     }
     //send confirmation if configured and receipt hasn't been sent
     if (self::config()->send_confirmation && !$this->order->ReceiptSent) {
         $this->notifier->sendConfirmation();
     }
     //notify admin, if configured
     if (self::config()->send_admin_notification) {
         $this->notifier->sendAdminNotification();
     }
     // Save order reference to session
     OrderManipulation::add_session_order($this->order);
     return true;
     //report success
 }
 /**
  * Takes an order from being a cart to awaiting payment.
  *
  * @param Member $member - assign a member to the order
  *
  * @return boolean - success/failure
  */
 public function placeOrder()
 {
     if (!$this->order) {
         $this->error(_t("OrderProcessor.NULL", "A new order has not yet been started."));
         return false;
     }
     if (!$this->canPlace($this->order)) {
         //final cart validation
         return false;
     }
     if ($this->order->Locale) {
         ShopTools::install_locale($this->order->Locale);
     }
     //remove from session
     $cart = ShoppingCart::curr();
     if ($cart && $cart->ID == $this->order->ID) {
         ShoppingCart::singleton()->clear();
     }
     //update status
     if ($this->order->TotalOutstanding()) {
         $this->order->Status = 'Unpaid';
     } else {
         $this->order->Status = 'Paid';
     }
     if (!$this->order->Placed) {
         $this->order->Placed = SS_Datetime::now()->Rfc2822();
         //record placed order datetime
         if ($request = Controller::curr()->getRequest()) {
             $this->order->IPAddress = $request->getIP();
             //record client IP
         }
     }
     //re-write all attributes and modifiers to make sure they are up-to-date before they can't be changed again
     $items = $this->order->Items();
     if ($items->exists()) {
         foreach ($items as $item) {
             $item->onPlacement();
             $item->write();
         }
     }
     $modifiers = $this->order->Modifiers();
     if ($modifiers->exists()) {
         foreach ($modifiers as $modifier) {
             $modifier->write();
         }
     }
     //add member to order & customers group
     if ($member = Member::currentUser()) {
         if (!$this->order->MemberID) {
             $this->order->MemberID = $member->ID;
         }
         $cgroup = ShopConfig::current()->CustomerGroup();
         if ($cgroup->exists()) {
             $member->Groups()->add($cgroup);
         }
     }
     //allow decorators to do stuff when order is saved.
     $this->order->extend('onPlaceOrder');
     $this->order->write();
     //send confirmation if configured and receipt hasn't been sent
     if (self::config()->send_confirmation && !$this->order->ReceiptSent) {
         $this->notifier->sendConfirmation();
     }
     //notify admin, if configured
     if (self::config()->send_admin_notification) {
         $this->notifier->sendAdminNotification();
     }
     // Save order reference to session
     OrderManipulation::add_session_order($this->order);
     return true;
     //report success
 }