/** * FORM ACTION /payment * Take the given order, take payment and process it. * * @param $data * @param $form * @param SS_HTTPRequest $request * @return Various */ public function payment($data, $form = null, SS_HTTPRequest $request) { /** * If a TempBasketID exists, process new payment. */ if (Store_BasketController::get_temp_basket_id()) { /* Temporary Basket Identifier */ $TempBasketID = Store_BasketController::get_temp_basket_id(); /* Order Object */ $Order = Order::get_one("Order", "(TempBasketID='{$TempBasketID}')"); /* Order ID */ $order_id = new SQLQuery("id"); $order_id = $order_id->setFrom("`order`")->addWhere("(TempBasketID='{$TempBasketID}')")->execute()->value(); /** * STEP ONE - Alter the Order record. * * 1 - Alter the Order status to 1 ("Pending/Awaiting Payment") so store admins can now it. * 2 - Assign CustomerID to this Order so that it is now linked to the customers account. * 3 - As the order is now linked to a customer, remove all of the TempBasketID references. * 4 - Add any CustomerComments (if entered) */ DB::Query("\n\t\t\tUPDATE `order`\n\t\t\tSET `Status`='1',\n\t\t\t`CustomerID`='" . Customer::currentUserID() . "',\n\t\t\t`TempBasketID`=NULL,\n\t\t\tCustomerComments='" . $data["CustomerComments"] . "'\n\t\t\tWHERE `ID`='" . $order_id . "'"); /** * STEP TWO - Remove TempBasketID references from Order_Items records. */ DB::Query("UPDATE `order_items` SET `TempBasketID`=NULL WHERE `OrderID`='" . $order_id . "'"); /** * STEP THREE - Destroy TempBasketID Cookies so this customer can shop again later. */ Store_BasketController::destroy_temp_basket_id(); /** * STEP FOUR - Handle Stock (if Stock Management Enabled) * * 1 - Check desired products are still in stock. * 2 - Deduct requested stock from inventory to prevent double-allocation. */ if (StoreSettings::get_settings()->Stock_StockManagement) { //Prepare the query to retreive the products in this order $product = new SQLQuery(); $product->setFrom("Order_Items")->addWhere("(`OrderID`=" . $order_id . ")"); //Execute the query $result = $product->execute(); //Loop through each product in the order and check stock still exists in the inventory. foreach ($result as $row) { //Products ID $product_id = $row["OriginalProductID"]; //If not in stock, break loop by failing. if (DataObject::get_by_id("Product", $product_id)->StockLevel < $row["Quantity"]) { return $this->redirect($this->link() . "/place/order-stock"); } //Otherwise, deduct requested stock from inventory. DB::Query("UPDATE `product` SET `StockLevel`=StockLevel - " . $row["Quantity"] . " WHERE `ID`='" . $product_id . "'"); } } /** * STEP FIVE * Hand control over to the requested payment gateway class to continue with remainder of the order. * * 1 - Get the ClassName of the selected payment gateway and create a new Object. * 2 - Call upon the method newPayment() within the gateway's class. */ $ClassName = $data["PaymentMethod"] ? $data["PaymentMethod"] : null; return !is_null($ClassName) ? $ClassName::create()->newPayment($order_id) : null; } else { switch ($this->request->param("ID")) { /** * A user has been returned after payment from their selected * payment gateway. Pass control to the object of the * Gateway class they used in order to fetch instructions. */ case "success": /** * STEP ONE * Does a Class exist for the requested Gateway? * If not, throw HTTP 403 - Forbidden. */ $request = $this->request; if (class_exists($request->getVar("gateway"))) { /** * STEP TWO * Is this gateway even enabled? * If not, throw HTTP 403 - Forbidden. */ $Gateway = $request->getVar("gateway"); if (DataObject::get_one($Gateway)->Enabled) { /** * STEP THREE * Initiate the Gateway class and pass the * control to its newPaymentSuccess() method. */ return $Gateway::create()->newPaymentSuccess($request); } else { return $this->httpError(403); } } else { return $this->httpError(403); } break; /** * A user has cancelled making a payment for a given order. */ /** * A user has cancelled making a payment for a given order. */ case "cancelled": return $this->customise(array("Title" => "An unexpected error occurred."))->renderWith(array("Store_Order_Error_PaymentCancelled", "Page")); break; /** * A payment gateway has sent a response for a payment. We need to process that. */ /** * A payment gateway has sent a response for a payment. We need to process that. */ case "response": /** * STEP ONE * Does a Class exist for the requested Gateway? * If not, throw HTTP 403 - Forbidden. */ $request = $this->request; if (class_exists($request->getVar("gateway"))) { /** * STEP TWO * Is this gateway even enabled? * If not, throw HTTP 403 - Forbidden. */ $Gateway = $request->getVar("gateway"); if (DataObject::get_one($Gateway)->Enabled) { /** * STEP THREE * Initiate the Gateway class and pass the * control to its handleGatewayResponse() method. */ return $Gateway::create()->handleGatewayResponse($request); } else { return $this->httpError(403); } } else { return $this->httpError(403); } break; /** * Default is duplicate basket error. */ /** * Default is duplicate basket error. */ default: return $this->customise(array("Title" => "An unexpected error occurred."))->renderWith(array("Store_Order_Error_Duplicate", "Page")); break; } } }