/** * The main action for handling all requests. * It will redirect back to the application in all cases, * but will not update the Payment/Transaction models if they are not found, * or allowed to be updated. */ public function index() { $response = null; $payment = $this->getPayment(); if (!$payment) { $this->httpError(404, _t('Payment.NotFound', 'Payment could not be found.')); } $intent = null; switch ($payment->Status) { // We have to check for both states here, since the notification might come in before the gateway returns // if that's the case, the status of the payment will already be set to 'Authorized' case 'PendingAuthorization': case 'Authorized': $intent = ServiceFactory::INTENT_AUTHORIZE; break; case 'PendingCapture': $intent = ServiceFactory::INTENT_CAPTURE; break; // Both states have to be checked (see explanation with 'Authorized') // Both states have to be checked (see explanation with 'Authorized') case 'PendingPurchase': case 'Captured': $intent = ServiceFactory::INTENT_PURCHASE; break; case 'PendingRefund': $intent = ServiceFactory::INTENT_REFUND; break; case 'PendingVoid': $intent = ServiceFactory::INTENT_VOID; break; default: $this->httpError(403, _t('Payment.InvalidStatus', 'Invalid/unhandled payment status')); } $service = ServiceFactory::create()->getService($payment, $intent); //do the payment update switch ($this->request->param('Status')) { case "complete": $serviceResponse = $service->complete(); $response = $serviceResponse->redirectOrRespond(); break; case "notify": $serviceResponse = $service->complete(array(), true); $response = $serviceResponse->redirectOrRespond(); break; case "cancel": $serviceResponse = $service->cancel(); $response = $serviceResponse->redirectOrRespond(); break; default: $this->httpError(404, _t('Payment.InvalidUrl', 'Invalid payment url.')); } return $response; }
/** * Handle the actions and apply any changes to the GridField * * @param \GridField $gridField * @param string $actionName * @param mixed $arguments * @param array $data - form data * @return void * @throws \ValidationException when there was an error */ public function handleAction(\GridField $gridField, $actionName, $arguments, $data) { if ($actionName == 'voidpayment') { $item = $gridField->getList()->byID($arguments['RecordID']); if (!$item instanceof \Payment) { return; } /** @var ServiceFactory $factory */ $factory = ServiceFactory::create(); $voidService = $factory->getService($item, ServiceFactory::INTENT_VOID); try { $serviceResponse = $voidService->initiate(); } catch (Exception $ex) { throw new \ValidationException($ex->getMessage(), 0); } if ($serviceResponse->isError()) { throw new \ValidationException(_t('GridFieldVoidAction.VoidError', 'Unable to void payment. An error occurred.'), 0); } } }
/** * Handle the actions and apply any changes to the GridField * * @param \GridField $gridField * @param string $actionName * @param mixed $arguments * @param array $data - form data * @return void * @throws \ValidationException when there was an error */ public function handleAction(\GridField $gridField, $actionName, $arguments, $data) { if ($actionName == 'refundpayment') { $item = $gridField->getList()->byID($arguments['RecordID']); if (!$item instanceof \Payment) { return; } $serviceData = array_intersect_key($data, array('amount' => null)); /** @var ServiceFactory $factory */ $factory = ServiceFactory::create(); $refundService = $factory->getService($item, ServiceFactory::INTENT_REFUND); try { $serviceResponse = $refundService->initiate($serviceData); } catch (Exception $ex) { throw new \ValidationException($ex->getMessage(), 0); } if ($serviceResponse->isError()) { throw new \ValidationException(_t('GridFieldRefundAction.RefundError', 'Unable to refund payment. An error occurred.'), 0); } } }
/** * Create a payment model, and provide link to redirect to external gateway, * or redirect to order link. * * @param string $gateway the gateway to use * @param array $gatewaydata the data that should be passed to the gateway * @param string $successUrl (optional) return URL for successful payments. * If left blank, the default return URL will be used @see getReturnUrl * @param string $cancelUrl (optional) return URL for cancelled/failed payments * * @return ServiceResponse|null */ public function makePayment($gateway, $gatewaydata = array(), $successUrl = null, $cancelUrl = null) { //create payment $payment = $this->createPayment($gateway); if (!$payment) { //errors have been stored. return null; } $payment->setSuccessUrl($successUrl ? $successUrl : $this->getReturnUrl()); // Explicitly set the cancel URL if ($cancelUrl) { $payment->setFailureUrl($cancelUrl); } // Create a payment service, by using the Service Factory. This will automatically choose an // AuthorizeService or PurchaseService, depending on Gateway configuration. // Set the user-facing success URL for redirects /** @var ServiceFactory $factory */ $factory = ServiceFactory::create(); $service = $factory->getService($payment, ServiceFactory::INTENT_PAYMENT); // Initiate payment, get the result back try { $serviceResponse = $service->initiate($this->getGatewayData($gatewaydata)); } catch (SilverStripe\Omnipay\Exception\Exception $ex) { // error out when an exception occurs $this->error($ex->getMessage()); return null; } // Check if the service response itself contains an error if ($serviceResponse->isError()) { if ($opResponse = $serviceResponse->getOmnipayResponse()) { $this->error($opResponse->getMessage()); } else { $this->error('An unspecified payment error occurred. Please check the payment messages.'); } } // For an OFFSITE payment, serviceResponse will now contain a redirect // For an ONSITE payment, ShopPayment::onCaptured will have been called, which will have called completePayment return $serviceResponse; }