We will be off from 27/1 (Monday) to 31/1 (Friday) (GMT +7) for our Tet Holiday (Lunar New Year) in our country

Commit 9acc8eb5 authored by rikterbeek's avatar rikterbeek

fix notificaitons handler with invoice creation build into and added...

fix notificaitons handler with invoice creation build into and added AdyenAbstract model for abstract configuration
parent 10bcbf45
...@@ -47,7 +47,7 @@ class Json extends \Magento\Framework\App\Action\Action ...@@ -47,7 +47,7 @@ class Json extends \Magento\Framework\App\Action\Action
try { try {
// $notificationItems = json_decode(file_get_contents('php://input'), true); // $notificationItems = json_decode(file_get_contents('php://input'), true);
$notificationItems = json_decode('{"live":"false","notificationItems":[{"NotificationRequestItem":{"additionalData":{"expiryDate":"12\/2012"," NAME1 ":"VALUE1","authCode":"1234","cardSummary":"7777","totalFraudScore":"10","hmacSignature":"yGnVWLP+UcpqjHTJbO5IUkG4ZdIk3uHCu62QAJvbbyg=","NAME2":" VALUE2 ","fraudCheck-6-ShopperIpUsage":"10"},"amount":{"currency":"EUR","value":10100},"eventCode":"AUTHORISATION","eventDate":"2015-09-11T13:53:21+02:00","merchantAccountCode":"MagentoMerchantByteShop1","merchantReference":"000000023","operations":["CANCEL","CAPTURE","REFUND"],"paymentMethod":"visa","pspReference":"test_AUTHORISATION_1","reason":"1234:7777:12\/2012","success":"true"}}]}', true); $notificationItems = json_decode('{"live":"false","notificationItems":[{"NotificationRequestItem":{"additionalData":{"expiryDate":"12\/2012"," NAME1 ":"VALUE1","authCode":"1234","cardSummary":"7777","totalFraudScore":"10","hmacSignature":"yGnVWLP+UcpqjHTJbO5IUkG4ZdIk3uHCu62QAJvbbyg=","NAME2":" VALUE2 ","fraudCheck-6-ShopperIpUsage":"10"},"amount":{"currency":"EUR","value":10500},"eventCode":"AUTHORISATION","eventDate":"2015-09-11T13:53:21+02:00","merchantAccountCode":"MagentoMerchantByteShop1","merchantReference":"000000023","operations":["CANCEL","CAPTURE","REFUND"],"paymentMethod":"visa","pspReference":"test_AUTHORISATION_1","reason":"1234:7777:12\/2012","success":"true"}}]}', true);
$notificationMode = isset($notificationItems['live']) ? $notificationItems['live'] : ""; $notificationMode = isset($notificationItems['live']) ? $notificationItems['live'] : "";
......
...@@ -224,7 +224,7 @@ class Cron ...@@ -224,7 +224,7 @@ class Cron
} }
echo 'end'; echo 'end1';
// get currenttime // get currenttime
// $date = new date(); // $date = new date();
...@@ -375,7 +375,6 @@ class Cron ...@@ -375,7 +375,6 @@ class Cron
{ {
$orderStatus = $this->_getConfigData('payment_cancelled', 'adyen_abstract', $this->_order->getStoreId()); $orderStatus = $this->_getConfigData('payment_cancelled', 'adyen_abstract', $this->_order->getStoreId());
$helper = Mage::helper('adyen');
// check if order has in invoice only cancel/hold if this is not the case // check if order has in invoice only cancel/hold if this is not the case
if ($ignoreHasInvoice || !$this->_order->hasInvoices()) { if ($ignoreHasInvoice || !$this->_order->hasInvoices()) {
...@@ -448,14 +447,14 @@ class Cron ...@@ -448,14 +447,14 @@ class Cron
case Notification::MANUAL_REVIEW_ACCEPT: case Notification::MANUAL_REVIEW_ACCEPT:
// only process this if you are on auto capture. On manual capture you will always get Capture or CancelOrRefund notification // only process this if you are on auto capture. On manual capture you will always get Capture or CancelOrRefund notification
if ($this->_isAutoCapture()) { if ($this->_isAutoCapture()) {
$this->_setPaymentAuthorized($this->_order, false); $this->_setPaymentAuthorized(false);
} }
break; break;
case Notification::CAPTURE: case Notification::CAPTURE:
if($_paymentCode != "adyen_pos") { if($_paymentCode != "adyen_pos") {
// ignore capture if you are on auto capture (this could be called if manual review is enabled and you have a capture delay) // ignore capture if you are on auto capture (this could be called if manual review is enabled and you have a capture delay)
if (!$this->_isAutoCapture()) { if (!$this->_isAutoCapture()) {
$this->_setPaymentAuthorized($this->_order, false, true); $this->_setPaymentAuthorized(false, true);
} }
} else { } else {
...@@ -495,88 +494,6 @@ class Cron ...@@ -495,88 +494,6 @@ class Cron
} }
} }
break; break;
case Notification::RECURRING_CONTRACT:
// get payment object
$payment = $this->_order->getPayment();
// storedReferenceCode
$recurringDetailReference = $this->_pspReference;
// check if there is already a BillingAgreement
$agreement = Mage::getModel('adyen/billing_agreement')->load($recurringDetailReference, 'reference_id');
if ($agreement && $agreement->getAgreementId() > 0 && $agreement->isValid()) {
$agreement->addOrderRelation($this->_order);
$agreement->setStatus($agreement::STATUS_ACTIVE);
$agreement->setIsObjectChanged(true);
$this->_order->addRelatedObject($agreement);
$message = $this->_adyenHelper->__('Used existing billing agreement #%s.', $agreement->getReferenceId());
} else {
// set billing agreement data
$payment->setBillingAgreementData(array(
'billing_agreement_id' => $recurringDetailReference,
'method_code' => $payment->getMethodCode()
));
// create billing agreement for this order
$agreement = Mage::getModel('adyen/billing_agreement');
$agreement->setStoreId($this->_order->getStoreId());
$agreement->importOrderPayment($payment);
$listRecurringContracts = Mage::getSingleton('adyen/api')->listRecurringContracts($agreement->getCustomerReference(), $agreement->getStoreId());
$contractDetail = null;
// get currenct Contract details and get list of all current ones
$recurringReferencesList = array();
foreach ($listRecurringContracts as $rc) {
$recurringReferencesList[] = $rc['recurringDetailReference'];
if (isset($rc['recurringDetailReference']) && $rc['recurringDetailReference'] == $recurringDetailReference) {
$contractDetail = $rc;
}
}
if($contractDetail != null) {
// update status of the agreements in magento
$billingAgreements = Mage::getResourceModel('adyen/billing_agreement_collection')
->addFieldToFilter('customer_id', $agreement->getCustomerReference());
foreach($billingAgreements as $billingAgreement) {
if(!in_array($billingAgreement->getReferenceId(), $recurringReferencesList)) {
$billingAgreement->setStatus(Adyen_Payment_Model_Billing_Agreement::STATUS_CANCELED);
$billingAgreement->save();
} else {
$billingAgreement->setStatus(Adyen_Payment_Model_Billing_Agreement::STATUS_ACTIVE);
$billingAgreement->save();
}
}
$agreement->parseRecurringContractData($contractDetail);
if ($agreement->isValid()) {
$message = __('Created billing agreement #%s.', $agreement->getReferenceId());
// save into sales_billing_agreement_order
$agreement->addOrderRelation($this->_order);
// add to order to save agreement
$this->_order->addRelatedObject($agreement);
} else {
$message = __('Failed to create billing agreement for this order.');
}
} else {
$this->_debugData['_processNotification error'] = 'Failed to create billing agreement for this order (listRecurringCall did not contain contract)';
$this->_debugData['_processNotification ref'] = printf('recurringDetailReference in notification is %s', $recurringDetailReference) ;
$this->_debugData['_processNotification customer ref'] = printf('CustomerReference is: %s and storeId is %s', $agreement->getCustomerReference(), $agreement->getStoreId());
$this->_debugData['_processNotification customer result'] = $listRecurringContracts;
$message = __('Failed to create billing agreement for this order (listRecurringCall did not contain contract)');
}
}
$comment = $this->_order->addStatusHistoryComment($message);
$this->_order->addRelatedObject($comment);
break;
default: default:
$this->_order->getPayment()->getMethodInstance()->writeLog('notification event not supported!'); $this->_order->getPayment()->getMethodInstance()->writeLog('notification event not supported!');
break; break;
...@@ -674,7 +591,7 @@ class Cron ...@@ -674,7 +591,7 @@ class Cron
$orderAmount = (int) $this->_adyenHelper->formatAmount($this->_order->getGrandTotal(), $orderCurrencyCode); $orderAmount = (int) $this->_adyenHelper->formatAmount($this->_order->getGrandTotal(), $orderCurrencyCode);
if($this->_isTotalAmount($orderAmount)) { if($this->_isTotalAmount($orderAmount)) {
$this->_createInvoice($this->_order); $this->_createInvoice();
} else { } else {
$this->_debugData['_prepareInvoice partial authorisation step1'] = 'This is a partial AUTHORISATION'; $this->_debugData['_prepareInvoice partial authorisation step1'] = 'This is a partial AUTHORISATION';
...@@ -692,7 +609,7 @@ class Cron ...@@ -692,7 +609,7 @@ class Cron
if($totalAuthorisationAmount == $orderAmount) { if($totalAuthorisationAmount == $orderAmount) {
$this->_debugData['_prepareInvoice partial authorisation step3'] = 'The full amount is paid. This is the latest AUTHORISATION notification. Create the invoice'; $this->_debugData['_prepareInvoice partial authorisation step3'] = 'The full amount is paid. This is the latest AUTHORISATION notification. Create the invoice';
$this->_createInvoice($this->_order); $this->_createInvoice();
} else { } else {
// this can be multiple times so use envenData as unique key // this can be multiple times so use envenData as unique key
$this->_debugData['_prepareInvoice partial authorisation step3'] = 'The full amount is not reached. Wait for the next AUTHORISATION notification. The current amount that is authorized is:' . $totalAuthorisationAmount; $this->_debugData['_prepareInvoice partial authorisation step3'] = 'The full amount is not reached. Wait for the next AUTHORISATION notification. The current amount that is authorized is:' . $totalAuthorisationAmount;
...@@ -789,6 +706,138 @@ class Cron ...@@ -789,6 +706,138 @@ class Cron
} }
protected function _createInvoice()
{
$this->_debugData['_createInvoice'] = 'Creating invoice for order';
if ($this->_order->canInvoice()) {
/* We do not use this inside a transaction because order->save() is always done on the end of the notification
* and it could result in a deadlock see https://github.com/Adyen/magento/issues/334
*/
try {
$invoice = $this->_order->prepareInvoice();
$invoice->getOrder()->setIsInProcess(true);
// set transaction id so you can do a online refund from credit memo
$invoice->setTransactionId(1);
$autoCapture = $this->_isAutoCapture($this->_order);
$createPendingInvoice = (bool) $this->_getConfigData('create_pending_invoice', 'adyen_abstract', $this->_order->getStoreId());
if((!$autoCapture) && ($createPendingInvoice)) {
// if amount is zero create a offline invoice
$value = (int)$this->_value;
if($value == 0) {
$invoice->setRequestedCaptureCase(Mage_Sales_Model_Order_Invoice::CAPTURE_OFFLINE);
} else {
$invoice->setRequestedCaptureCase(Mage_Sales_Model_Order_Invoice::NOT_CAPTURE);
}
$invoice->register();
} else {
$invoice->register()->pay();
}
$invoice->save();
$this->_debugData['_createInvoice done'] = 'Created invoice';
} catch (Exception $e) {
$this->_debugData['_createInvoice error'] = 'Error saving invoice. The error message is: ' . $e->getMessage();
throw new Exception(sprintf('Error saving invoice. The error message is:', $e->getMessage()));
}
$this->_setPaymentAuthorized();
$invoiceAutoMail = (bool) $this->_getConfigData('send_invoice_update_mail', 'adyen_abstract', $this->_order->getStoreId());
if ($invoiceAutoMail) {
$invoice->sendEmail();
}
} else {
$this->_debugData['_createInvoice error'] = 'It is not possible to create invoice for this order';
}
}
/**
*
*/
protected function _setPaymentAuthorized($manualReviewComment = true, $createInvoice = false)
{
$this->_debugData['_setPaymentAuthorized start'] = 'Set order to authorised';
// if full amount is captured create invoice
$currency = $this->_order->getOrderCurrencyCode();
$amount = $this->_value;
$orderAmount = (int) $this->_adyenHelper->formatAmount($this->_order->getGrandTotal(), $currency);
// create invoice for the capture notification if you are on manual capture
if($createInvoice == true && $amount == $orderAmount) {
$this->_debugData['_setPaymentAuthorized amount'] = 'amount notification:'.$amount . ' amount order:'.$orderAmount;
$this->_createInvoice($this->_order);
}
// if you have capture on shipment enabled don't set update the status of the payment
$captureOnShipment = $this->_getConfigData('capture_on_shipment', 'adyen_abstract', $this->_order->getStoreId());
if(!$captureOnShipment) {
$status = $this->_getConfigData('payment_authorized', 'adyen_abstract', $this->_order->getStoreId());
}
// virtual order can have different status
if($this->_order->getIsVirtual()) {
$this->_debugData['_setPaymentAuthorized virtual'] = 'Product is a virtual product';
$virtual_status = $this->_getConfigData('payment_authorized_virtual');
if($virtual_status != "") {
$status = $virtual_status;
}
}
// check for boleto if payment is totally paid
if($this->_paymentMethodCode($this->_order) == "adyen_boleto") {
// check if paid amount is the same as orginal amount
$orginalAmount = $this->_boletoOriginalAmount;
$paidAmount = $this->_boletoPaidAmount;
if($orginalAmount != $paidAmount) {
// not the full amount is paid. Check if it is underpaid or overpaid
// strip the BRL of the string
$orginalAmount = str_replace("BRL", "", $orginalAmount);
$orginalAmount = floatval(trim($orginalAmount));
$paidAmount = str_replace("BRL", "", $paidAmount);
$paidAmount = floatval(trim($paidAmount));
if($paidAmount > $orginalAmount) {
$overpaidStatus = $this->_getConfigData('order_overpaid_status', 'adyen_boleto');
// check if there is selected a status if not fall back to the default
$status = (!empty($overpaidStatus)) ? $overpaidStatus : $status;
} else {
$underpaidStatus = $this->_getConfigData('order_underpaid_status', 'adyen_boleto');
// check if there is selected a status if not fall back to the default
$status = (!empty($underpaidStatus)) ? $underpaidStatus : $status;
}
}
}
$comment = "Adyen Payment Successfully completed";
// if manual review is true use the manual review status if this is set
if($manualReviewComment == true && $this->_fraudManualReview) {
// check if different status is selected
$fraudManualReviewStatus = $this->_getFraudManualReviewStatus();
if($fraudManualReviewStatus != "") {
$status = $fraudManualReviewStatus;
$comment = "Adyen Payment is in Manual Review check the Adyen platform";
}
}
$status = (!empty($status)) ? $status : $this->_order->getStatus();
$this->_order->addStatusHistoryComment(__($comment), $status);
$this->_debugData['_setPaymentAuthorized end'] = 'Order status is changed to authorised status, status is ' . $status;
}
/** /**
* Retrieve information from payment configuration * Retrieve information from payment configuration
......
<?php
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Adyen\Payment\Model\Method;
use Magento\Framework\Object;
use Magento\Payment\Model\Method\ConfigInterface;
use Magento\Payment\Model\Method\Online\GatewayInterface;
/**
* @method \Magento\Quote\Api\Data\PaymentMethodExtensionInterface getExtensionAttributes()
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class AdyenAbstract extends \Magento\Payment\Model\Method\AbstractMethod implements GatewayInterface
{
const METHOD_CODE = 'adyen_hpp';
/**
* @var string
*/
protected $_code = self::METHOD_CODE;
protected $_isGateway = false;
protected $_canAuthorize = false;
protected $_isInitializeNeeded = false;
/**
* Post request to gateway and return response
*
* @param Object $request
* @param ConfigInterface $config
*
* @return Object
*
* @throws \Exception
*/
public function postRequest(Object $request, ConfigInterface $config)
{
// TODO: Implement postRequest() method.
}
}
\ No newline at end of file
...@@ -10,9 +10,10 @@ ...@@ -10,9 +10,10 @@
<payment> <payment>
<adyen_abstract> <adyen_abstract>
<active>0</active> <active>0</active>
<model>Adyen\Payment\Model\Method\AdyenAbstract</model>
<recurring_type>ONECLICK</recurring_type> <recurring_type>ONECLICK</recurring_type>
<order_status>pending</order_status> <order_status>pending</order_status>
<demo_mode>1</demo_mode> <demo_mode>0</demo_mode>
</adyen_abstract> </adyen_abstract>
<adyen_cc> <adyen_cc>
<active>1</active> <active>1</active>
......
...@@ -30,17 +30,16 @@ ...@@ -30,17 +30,16 @@
}, 'validation':[]}"> }, 'validation':[]}">
<fieldset data-bind="attr: {class: 'fieldset payment items ccard ' + getCode(), id: 'payment_form_' + getCode()}"> <fieldset data-bind="attr: {class: 'fieldset payment items ccard ' + getCode(), id: 'payment_form_' + getCode()}">
<!-- ko if: (isShowLegend())--> <!-- ko if: (isShowLegend())-->
<legend class="legend"> <legend class="legend">
<span><!-- ko i18n: 'Credit Card Information'--><!-- /ko --></span> <span><!-- ko text: $t('Credit Card Information')--><!-- /ko --></span>
</legend><br /> </legend><br />
<!-- /ko --> <!-- /ko -->
<div class="field type required"> <div class="field type required">
<label data-bind="attr: {for: getCode() + '_cc_type'}" class="label"> <label data-bind="attr: {for: getCode() + '_cc_type'}" class="label">
<span><!-- ko i18n: 'Credit Card Type'--><!-- /ko --></span> <span><!-- ko text: $t('Credit Card Type')--><!-- /ko --></span>
</label> </label>
<div class="control"> <div class="control">
<ul class="credit-card-types"> <ul class="credit-card-types">
...@@ -68,7 +67,7 @@ ...@@ -68,7 +67,7 @@
</div> </div>
<div class="field number required"> <div class="field number required">
<label data-bind="attr: {for: getCode() + '_cc_number'}" class="label"> <label data-bind="attr: {for: getCode() + '_cc_number'}" class="label">
<span><!-- ko i18n: 'Credit Card Number'--><!-- /ko --></span> <span><!-- ko text: $t('Credit Card Number')--><!-- /ko --></span>
</label> </label>
<div class="control"> <div class="control">
<input type="number" name="payment[cc_number]" class="input-text" value="" <input type="number" name="payment[cc_number]" class="input-text" value=""
...@@ -86,7 +85,7 @@ ...@@ -86,7 +85,7 @@
</div> </div>
<div class="field type required"> <div class="field type required">
<label data-bind="attr: {for: getCode() + '_cc_owner'}" class="label"> <label data-bind="attr: {for: getCode() + '_cc_owner'}" class="label">
<span><!-- ko i18n: 'Credit Card Owner'--><!-- /ko --></span> <span><!-- ko text: $t('Credit Card Owner')--><!-- /ko --></span>
</label> </label>
<div class="control"> <div class="control">
<input type="text" <input type="text"
...@@ -101,7 +100,7 @@ ...@@ -101,7 +100,7 @@
</div> </div>
<div class="field date required" data-bind="attr: {id: getCode() + '_cc_type_exp_div'}"> <div class="field date required" data-bind="attr: {id: getCode() + '_cc_type_exp_div'}">
<label data-bind="attr: {for: getCode() + '_expiration'}" class="label"> <label data-bind="attr: {for: getCode() + '_expiration'}" class="label">
<span><!-- ko i18n: 'Expiration Date'--><!-- /ko --></span> <span><!-- ko text: $t('Expiration Date')--><!-- /ko --></span>
</label> </label>
<div class="control"> <div class="control">
<div class="fields group group-2"> <div class="fields group group-2">
...@@ -141,7 +140,7 @@ ...@@ -141,7 +140,7 @@
<!-- ko if: (hasVerification())--> <!-- ko if: (hasVerification())-->
<div class="field cvv required" data-bind="attr: {id: getCode() + '_cc_type_cvv_div'}"> <div class="field cvv required" data-bind="attr: {id: getCode() + '_cc_type_cvv_div'}">
<label data-bind="attr: {for: getCode() + '_cc_cid'}" class="label"> <label data-bind="attr: {for: getCode() + '_cc_cid'}" class="label">
<span><!-- ko i18n: 'Card Verification Number'--><!-- /ko --></span> <span><!-- ko text: $t('Card Verification Number')--><!-- /ko --></span>
</label> </label>
<div class="control _with-tooltip"> <div class="control _with-tooltip">
<input type="number" <input type="number"
...@@ -161,7 +160,7 @@ ...@@ -161,7 +160,7 @@
tabindex="0" tabindex="0"
data-toggle="dropdown" data-toggle="dropdown"
data-bind="attr: {title: $t('What is this?')}, mageInit: {'dropdown':{'activeClass': '_active'}}"> data-bind="attr: {title: $t('What is this?')}, mageInit: {'dropdown':{'activeClass': '_active'}}">
<span><!-- ko i18n: 'What is this?'--><!-- /ko --></span> <span><!-- ko text: $t('What is this?')--><!-- /ko --></span>
</span> </span>
<div class="field-tooltip-content" <div class="field-tooltip-content"
data-target="dropdown" data-target="dropdown"
...@@ -175,12 +174,12 @@ ...@@ -175,12 +174,12 @@
<div class="nested"> <div class="nested">
<div class="field switch-solo required"> <div class="field switch-solo required">
<label data-bind="attr: {for: getCode() + '_cc_issue'}" class="label"> <label data-bind="attr: {for: getCode() + '_cc_issue'}" class="label">
<span><!-- ko i18n: 'Switch/Solo/Maestro Only'--><!-- /ko --></span> <span><!-- ko text: $t('Switch/Solo/Maestro Only')--><!-- /ko --></span>
</label> </label>
</div> </div>
<div class="field number required"> <div class="field number required">
<label data-bind="attr: {for: getCode() + '_cc_issue'}" class="label"> <label data-bind="attr: {for: getCode() + '_cc_issue'}" class="label">
<span><!-- ko i18n: 'Issue Number'--><!-- /ko --></span> <span><!-- ko text: $t('Issue Number')--><!-- /ko --></span>
</label> </label>
<div class="control"> <div class="control">
<input type="number" name="payment[cc_ss_issue]" <input type="number" name="payment[cc_ss_issue]"
...@@ -192,7 +191,7 @@ ...@@ -192,7 +191,7 @@
<div class="field date required"> <div class="field date required">
<label data-bind="attr: {for: getCode() + '_start_month'}" class="label"> <label data-bind="attr: {for: getCode() + '_start_month'}" class="label">
<span><!-- ko i18n: 'Start Date'--><!-- /ko --></span> <span><!-- ko text: $t('Start Date'--><!-- /ko --></span>
</label> </label>
<div class="control"> <div class="control">
<div class="fields group group-2"> <div class="fields group group-2">
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment