File: D:/HostingSpaces/SBogers10/topswtw.komma.pro/app/KommaApp/Shop/Checkout/Payment/PaymentService.php
<?php
namespace KommaApp\Shop\Checkout\Payment;
use Carbon\Carbon;
use Illuminate\Support\Facades\Config;
use KommaApp\Shop\Modules\Kiyoh\KiyohService;
use KommaApp\Shop\Orders\Order;
use KommaApp\Shop\Orders\OrderTransaction;
use KommaApp\Shop\Orders\OrderRepository;
use KommaApp\Shop\FormValidation\CompletePendingPaymentForm;
use Sokil\IsoCodes\Database\Subdivisions\Subdivision;
class PaymentService
{
/**
* @var ShaSign
*/
private $shaSign;
/**
* @var Order
*/
private $orderModel;
/**
* @var IngenicoService
*/
private $ingenicoService;
/**
* @var OrderTransaction
*/
private $orderTransaction;
/**
* @var OrderRepository
*/
private $orderRepository;
/**
* @var CompletePendingPaymentForm
*/
private $completePendingPaymentForm;
/**
* @var KiyohService
*/
private $kiyohService;
/**
* @param ShaSign $shaSign
* @param IngenicoService $ingenicoService
* @param Order $orderModel
* @param OrderTransaction $orderTransaction
* @param OrderRepository $orderRepository
* @param CompletePendingPaymentForm $completePendingPaymentForm
* @param KiyohService $kiyohService
*/
public function __construct(
ShaSign $shaSign,
IngenicoService $ingenicoService,
Order $orderModel,
OrderTransaction $orderTransaction,
OrderRepository $orderRepository,
CompletePendingPaymentForm $completePendingPaymentForm,
KiyohService $kiyohService)
{
$this->shaSign = $shaSign;
$this->ingenicoService = $ingenicoService;
$this->orderModel = $orderModel;
$this->orderTransaction = $orderTransaction;
$this->orderRepository = $orderRepository;
$this->completePendingPaymentForm = $completePendingPaymentForm;
$this->kiyohService = $kiyohService;
}
public function ingenicoService()
{
return $this->ingenicoService;
}
/**
* Create a form for Ingenico with all the order data
* @param $data
* @return \View
*/
public function form($data)
{
// Create a new transaction for the Order with id: $data['orderId']
/** @var Order $order */
$order = $this->orderModel->find($data['orderId']);
$transaction = $order->createNewTransaction();
$data['orderId'] = $transaction->custom_identifier;
// Url for redirect
$paymentUrl = \Config::get('komma/ingenico.paymentUrl');
// Default form data
$default = $this->ingenicoService->defaultFormData($order->order_token);
if($data['pm'] == 'CreditCard') {
//It now is required to add the operation field for two stage creditcard payments.
$data['operation'] = 'SAL'; //SAL: request for sale (payment), RES: request for authorization, PAU: Request for pre-authorization
}
//Gather data for paypal seller protection
if($data['pm'] == "PAYPAL") {
$data['ECOM_SHIPTO_POSTAL_NAME_FIRST'] = $order->shipping_first_name;
$data['ECOM_SHIPTO_POSTAL_NAME_LAST'] = $order->shipping_last_name;
$data['ECOM_SHIPTO_POSTAL_STREET_LINE1'] = $order->shipping_street;
$data['ECOM_SHIPTO_POSTAL_STREET_LINE2'] = implode(' ',[$order->shipping_house_number, $order->shipping_house_number_suffix]);
$data['ECOM_SHIPTO_POSTAL_COUNTRYCODE'] = $order->shipping_country; //Two letter country code. Like NL, EN
$data['ECOM_SHIPTO_POSTAL_CITY'] = $order->shipping_city;
$data['ECOM_SHIPTO_POSTAL_POSTALCODE'] = $order->shipping_postal;
//$data['ECOM_SHIPTO_POSTAL_STATE'] //Is already included
}
// dd($data);
// Create the shaSign from all the $data for the Ingenico security check
$default['shaSign'] = $this->shaSign->create(array_merge($data, $default));
if (isset($data['issuerId']) && !empty($data['issuerId'])) {
$transaction->payment_issuer_id = $data['issuerId'];
}
$transaction->payment_method = $data['brand'];
$transaction->save();
// Return View
return \View::make('checkout.payment.ingenico.paymentForm')->with([
'data' => $data,
'default' => $default,
'url' => $paymentUrl
]);
}
/*
* Process the form
*/
public function processPaymentProviderResponse()
{
$paymentData = \Input::all();
//\Input::except trows an error, so use all and unset SHASIGN
unset($paymentData['SHASIGN']);
// Todo: technical error page
if ($this->shaSign->create($paymentData) != \Input::get('SHASIGN'))
return ['paymentData' => 'unvalid!'];
// Get order by transaction id
if (!$order = $this->orderModel->findByCustomTransactionIdentifier($paymentData['orderID'])) {
return ['paymentData' => 'unvalid!'];
}
// Make sure array keys are upper case
$paymentData = array_change_key_case($paymentData, CASE_UPPER);
// Update payment in database
$this->updatePaymentInDatabase($paymentData);
return ['paymentData' => $paymentData, 'order' => $order];
}
/*
* Process complete pending payment
*/
public function processPending()
{
// Because this route isn't in the database we manually need to boot the languageService
\Shop::getLanguageService()->bootFromUri(\Shop::getId());
// Get form data
$inputData = \Input::all();
// Validate fom data
if (!$this->completePendingPaymentForm->isValid($inputData)) {
return \Redirect::back()
->withErrors($this->completePendingPaymentForm->errorMessages());
}
// Validate form
// Get Payment method and brand
$token = \Input::get('token');
$paymentData = $this->ingenicoService->paymentData($inputData);
// Get Form data (name, address etc.)
$order = $this->orderRepository->getOrderFromToken($token);
$formData = $this->ingenicoService->formData($order->toArray());
// Set data for form
$data = array_merge(['orderId' => $order->id], $paymentData, $formData);
return $this->form($data);
}
/**
* Update payment fields in database
* @param (upper case keys) $paymentData
*/
protected function updatePaymentInDatabase($paymentData)
{
// Fill data and save order
$data = [];
// Translate DB_TABLE_NAME => ARRAY_KEY
$translateArray = [
'payment_method' => 'PM',
'payment_date' => 'TRXDATE',
'payment_status' => 'STATUS',
'payment_currency' => 'CURRENCY',
'payment_acceptance' => 'ACCEPTANCE',
'payment_card_number' => 'CARDNO',
'payment_cardholder_name' => 'CN',
'payment_provider_id' => 'PAYID',
'payment_error_code' => 'NCERROR',
'payment_card_brand' => 'BRAND',
'payment_ip' => 'IP',
'payment_issuer_id' => 'ISSUERID'
];
foreach ($translateArray as $databaseField => $providerField) {
if ($databaseField == 'payment_date')
$paymentData[$providerField] = $this->convertPaymentDate($paymentData[$providerField]);
if (isset($paymentData[$providerField])) $data[$databaseField] = mb_convert_encoding($paymentData[$providerField],'utf-8');
}
// Find order and update data
$orderTransaction = $this->orderTransaction->where('custom_identifier', $paymentData['ORDERID'])->first();
if (!$orderTransaction
->fill($data)
->save()
) ;
}
/**
* @param $dateString
* @return static
*/
protected function convertPaymentDate($dateString)
{
$temp = explode('/', $dateString);
if (count($temp) == 3) {
$year = (int)'20' . $temp[2];
$month = (int)$temp[0];
$day = (int)$temp[1];
return Carbon::createFromDate($year, $month, $day);
}
return null;
}
/*
* Get optional payment methods
* @return Array
*/
public function getPaymentMethods()
{
$methods['default'] = [
'iDeal',
'bancontactMisterCash',
'sofort_de',
'masterCard',
'maestro',
'visa',
'ingHomePay',
'belfius',
'giropay',
'cbcOnline',
'kbcOnline',
'bankTransfer_nl',
'bankTransfer_de',
];
//methods / shopCountry
$methods['NL'] = [
'iDeal',
'bancontactMisterCash',
'visa',
'masterCard',
'maestro',
'payPal',
'ingHomePay',
'belfius',
'cbcOnline',
'kbcOnline',
'bankTransfer_nl'
];
$methods['BE'] = [
'bancontactMisterCash',
'visa',
'masterCard',
'maestro',
'payPal',
'ingHomePay',
'belfius',
'cbcOnline',
'kbcOnline',
'iDeal',
'bankTransfer_nl'
];
$methods['DE'] = [
'sofort_de',
'payPal',
'giropay',
'masterCard',
'maestro',
'visa',
'bancontactMisterCash',
'belfius',
'cbcOnline',
'kbcOnline',
'bankTransfer_de'
];
$methods['AT'] = [
'sofort_de',
'payPal',
'giropay',
'masterCard',
'maestro',
'visa',
'bancontactMisterCash',
'belfius',
'cbcOnline',
'kbcOnline',
'bankTransfer_de'
];
$methods['GB'] = [
'masterCard',
'visa',
'payPal',
'maestro',
'sofort_de',
'iDeal',
'bancontactMisterCash',
'giropay',
'bankTransfer_nl',
];
// Select methods based on the country of the domain
$country_iso = \Shop::getDomainCountry();
isset($methods[$country_iso]) ? $paymentMethods = $methods[$country_iso] : $paymentMethods = $methods['default'];
// Generate array
$list = [];
$first = true;
foreach ($paymentMethods as $paymentMethod) {
//Check if the payment exist in the config
if (!\Config::has('komma/ingenico.paymentMethods.' . $paymentMethod)) continue;
//Set the payment from the config
$payment = \Config::get('komma/ingenico.paymentMethods.' . $paymentMethod);
//Check if there is an translation for this payment
if (\Lang::has('checkout/payment.' . $paymentMethod)) {
//if so merge this with the current payment
$payment = array_merge($payment, \Lang::get('checkout/payment.' . $paymentMethod));
}
//If this isnt the first run set the streamer to null
if (!$first) $payment['streamer'] = null;
//set first to false
$first = false;
//add the payment to the list
$list[$paymentMethod] = $payment;
}
return $list;
}
public function paymentLink($orderId)
{
//return url() . '/' . \Shop::getPageService()->page('pendingPayment')->route . '?token=' .$token;
}
/**
* @param $paymentData
* @return mixed
*/
public function redirectUsingStatus($paymentData, $order)
{
// Token
$withToken = '?token=' . $order->order_token;
// Routes
$paymentCancelRoute = \Shop::getPageService()->page('paymentToCancel')->route;
$paymentFailedRoute = \Shop::getPageService()->page('paymentFailed')->route;
$checkoutThanksRoute = \Shop::getPageService()->page('checkoutThanks')->route;
$waitingRoute = \Shop::getPageService()->page('waiting')->route;
$status = (int)$paymentData['STATUS'];
switch ($status) {
// 0: Incomplete or invalid
case 0:
// 1: Cancelled by client
case 1:
return \Redirect::to($paymentCancelRoute . $withToken);
// 2: Payment Failed
case 2:
return \Redirect::to($paymentFailedRoute . $withToken);
// Waiting on client payment (F.e. BankTransfer)
case 41:
return \Redirect::to($waitingRoute . $withToken);
// 9: Payment requested
case 9:
return \Redirect::to($checkoutThanksRoute . $withToken);
// No status: redirect to payment failed
default:
return \Redirect::to($paymentFailedRoute . $withToken);
}
}
/**
* The method that will change the order status.
*/
public function changeOrderStatus($paymentData, $order)
{
$status = (int)$paymentData['STATUS'];
switch ($status) {
// 0: Incomplete or invalid
case 0:
// 1: Cancelled by client
case 1:
case 2:
break;
// Waiting on client payment (F.e. BankTransfer)
case 41:
break;
// 9: Payment requested
case 9:
if ($order->status != Order::OPEN) {
return 'Status is already changed';
}
$order->status = Order::PAYED;
$order->save();
//todo: Het mailen zou eigenlijk via CustomerMailer moeten lopen
// Dit wil TOPS voorlopig handmatig doen
//$this->kiyohService->sendReviewEmailToCustomer($order);
$data = $order->toArray();
$data['order'] = $order;
//send mail with the customerMailer
$customerMailer = \App::make('KommaApp\Shop\Mailers\CustomerMailer');
$customerMailer->sendOrderPayed($order);
break;
// No status: redirect to payment failed
default:
break;
}
return 'Status changed';
}
/***
* This method will search for the order by token.
* And set the status of the order to CANCELLED
*
* @param $token
* @return bool
*/
public function cancelOrderWithToken($token){
if(!$order = $this->orderRepository->getOrderFromToken($token)){
return false;
}
$order->status = Order::CANCELLED;
$order->save();
return true;
}
}