context = $context; $this->module = $module; $this->paymentClient = new Payment($module->getPaynowClient()); $this->paymentDataBuilder = new PaynowPaymentDataBuilder($this->module); } /** * @return array * @throws Exception */ public function process(): array { if (PaynowConfigurationHelper::CREATE_ORDER_BEFORE_PAYMENT === (int)Configuration::get('PAYNOW_CREATE_ORDER_STATE') && ! empty($this->module->currentOrder)) { $order = new Order($this->module->currentOrder); $payment = $this->processFromOrder($order, $this->getExternalId()); PaynowPaymentData::create( $payment->getPaymentId(), Paynow\Model\Payment\Status::STATUS_NEW, $order->id, $order->id_cart, $order->reference, $order->reference, $order->total_paid ); } else { $cart = $this->context->cart; $payment = $this->processFromCart($cart, $this->getExternalId()); PaynowPaymentData::create( $payment->getPaymentId(), Paynow\Model\Payment\Status::STATUS_NEW, null, $cart->id, null, $this->getExternalId(), $cart->getOrderTotal() ); } PaynowLogger::info( 'Payment has been successfully created {cartId={}, externalId={}, paymentId={}, status={}}', [ $this->context->cart->id, $this->getExternalId(), $payment->getPaymentId(), $payment->getStatus() ] ); return [ 'payment_id' => $payment->getPaymentId(), 'status' => $payment->getStatus(), 'redirect_url' => $payment->getRedirectUrl() ?? null, 'external_id' => $this->getExternalId() ]; } /** * @return string */ public function getExternalId(): string { if (empty($this->externalId)) { $this->generateExternalId(); } return $this->externalId; } /** * @throws PaynowPaymentAuthorizeException */ private function processFromOrder($order, $external_id): ?Authorize { PaynowLogger::info( 'Processing payment for order {cartId={}, externalId={}, orderId={}, orderReference={}}', [ $order->id_cart, $external_id, $order->id, $order->reference ] ); $idempotency_key = $this->generateIdempotencyKey($external_id); $payment_request_data = $this->paymentDataBuilder->fromOrder($order); return $this->sendPaymentRequest($payment_request_data, $idempotency_key); } /** * @throws PaynowPaymentAuthorizeException */ private function processFromCart($cart, $external_id): ?Authorize { PaynowLogger::info( 'Processing payment for cart {cartId={}, externalId={}}', [ $cart->id, $external_id ] ); $idempotency_key = $this->generateIdempotencyKey($external_id); $payment_request_data = $this->paymentDataBuilder->fromCart($cart, $external_id); return $this->sendPaymentRequest($payment_request_data, $idempotency_key); } private function generateIdempotencyKey($external_id): string { return substr(uniqid($external_id . '_', true), 0, 45); } /** * @return void */ private function generateExternalId(): void { if (PaynowConfigurationHelper::CREATE_ORDER_BEFORE_PAYMENT === (int)Configuration::get('PAYNOW_CREATE_ORDER_STATE') && ! empty($this->module->currentOrder)) { $order = new Order($this->module->currentOrder); $this->externalId = $order->reference; } else { $cart = $this->context->cart; $this->externalId = uniqid($cart->id . '_', false); } } /** * @param $payment_request_data * @param $idempotency_key * * @return Authorize|null * @throws PaynowPaymentAuthorizeException */ private function sendPaymentRequest($payment_request_data, $idempotency_key): ?Authorize { try { return $this->paymentClient->authorize($payment_request_data, $idempotency_key); } catch (PaynowException $exception) { throw new PaynowPaymentAuthorizeException( $exception->getMessage(), $payment_request_data['externalId'], $exception ); } } }