Commit ab1b5e67 authored by Tuan's avatar Tuan

First commit

parents
<?php
namespace MR\Zip\Api;
/**
* Payment method management interface for guest carts.
* @api
*/
interface GuestZipManagementInterface
{
/**
* Add a specified payment method to a specified shopping cart.
*
* @param string $cartId The cart ID.
* @param string $email
* @param \Magento\Quote\Api\Data\PaymentInterface $method The payment method.
* @param \Magento\Quote\Api\Data\AddressInterface $billingAddress
* @return string
* @throws \Magento\Framework\Exception\NoSuchEntityException The specified cart does not exist.
* @throws \Magento\Framework\Exception\State\InvalidTransitionException The billing or shipping address
* is not set, or the specified payment method is not available.
*/
public function set($cartId, $email, \Magento\Quote\Api\Data\PaymentInterface $method, \Magento\Quote\Api\Data\AddressInterface $billingAddress = null);
}
<?php
namespace MR\Zip\Api;
interface ZipManagementInterface
{
/**
* Add a specified payment method to a specified shopping cart.
*
* @param string $cartId The cart ID.
* @param \Magento\Quote\Api\Data\PaymentInterface $method The payment method.
* @return string
* @throws \Magento\Framework\Exception\NoSuchEntityException The specified cart does not exist.
* @throws \Magento\Framework\Exception\State\InvalidTransitionException The billing or shipping address
* is not set, or the specified payment method is not available.
*/
public function set($cartId, \Magento\Quote\Api\Data\PaymentInterface $method, \Magento\Quote\Api\Data\AddressInterface $billingAddress = null);
}
<?php
namespace MR\Zip\Block;
use Magento\Framework\View\Element\Template\Context;
class Error extends \Magento\Framework\View\Element\Template
{
public function __construct(Context $context, array $data = [])
{
parent::__construct($context, $data);
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$this->_logger = $objectManager->get("\MR\Zip\Logger\ZipLogger");
$this->_logger->info(__METHOD__);
}
protected function _prepareLayout()
{
$this->setShowContinueButton(true);
$error = $this->getRequest()->getParam("error");
$this->_logger->info(__METHOD__ . " error:{$error}");
$this->setError($error);
return $this;
}
}
<?php
namespace MR\Zip\Block;
use Magento\Framework\View\Element\Template\Context;
class Info extends \Magento\Payment\Block\Info
{
/**
*
* @var string
*/
protected $_template = 'MR_Zip::info/default.phtml';
public function __construct(Context $context, array $data = [])
{
parent::__construct($context, $data);
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$this->_logger = $objectManager->get("\MR\Zip\Logger\ZipLogger");
$this->_logger->info(__METHOD__);
}
protected function _prepareSpecificInformation($transport = null)
{
$this->_logger->info(__METHOD__);
if (null !== $this->_paymentSpecificInformation) {
return $this->_paymentSpecificInformation;
}
$data = $this->getInfo()->getAdditionalInformation();
$decodedData = [];
foreach ($data as $key => $value) {
if (in_array($key, ['items', 'billing', 'shipping', 'merchant'])) {
continue;
}
if (strtotime($key)) {
$decodedValue = json_decode($value, true);
if (!$decodedValue) {
$decodedData[$key] = $this->getValueAsArray($value, true);
} else {
$decodedData[$key] = $decodedValue;
}
}
else {
$decodedData[$key] = $value;
}
}
$transport = parent::_prepareSpecificInformation($transport);
$this->_paymentSpecificInformation = $transport->setData(array_merge($decodedData, $transport->getData()));
return $this->_paymentSpecificInformation;
}
}
<?php
namespace MR\Zip\Block;
class Processed extends \Magento\Framework\View\Element\Template
{
}
<?php
namespace MR\Zip\Block\Widget;
use Magento\Framework\View\Element\Template\Context;
class Cart extends \Magento\Framework\View\Element\Template
{
/**
* @var $_paymentUtil \MR\Zip\Helper\PaymentUtil
*/
protected $_paymentUtil;
/**
* @var $_checkoutSession \Magento\Checkout\Model\Session
*/
protected $_checkoutSession;
public function __construct(
Context $context,
\Magento\Checkout\Model\Session $checkoutSession,
array $data = [])
{
parent::__construct($context, $data);
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$this->_logger = $objectManager->get("\MR\Zip\Logger\ZipLogger");
$this->_paymentUtil = $objectManager->get("\MR\Zip\Helper\PaymentUtil");
$this->_checkoutSession = $checkoutSession;
$this->_logger->info(__METHOD__);
}
public function getCartWidgetHtml()
{
$quote = $this->_checkoutSession->getQuote();
return $this->_paymentUtil->getWidgetHtml($quote->getGrandTotal());
}
}
<?php
namespace MR\Zip\Block\Widget;
use Magento\Framework\View\Element\Template\Context;
class Product extends \Magento\Framework\View\Element\Template
{
/**
* @var $_paymentUtil \MR\Zip\Helper\PaymentUtil
*/
protected $_paymentUtil;
/**
* @var \Magento\Framework\Registry
*/
protected $_coreRegistry;
/**
* @var \Magento\Catalog\Api\ProductRepositoryInterface
*/
protected $_productRepository;
public function __construct(
Context $context,
\Magento\Framework\Registry $registry,
\Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
array $data = []
){
parent::__construct($context, $data);
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$this->_logger = $objectManager->get("\MR\Zip\Logger\ZipLogger");
$this->_paymentUtil = $objectManager->get("\MR\Zip\Helper\PaymentUtil");
$this->_coreRegistry = $registry;
$this->_productRepository = $productRepository;
$this->_logger->info(__METHOD__);
}
public function getProductWidgetHtml(\Magento\Catalog\Model\Product $product = null)
{
if (!$product){
if (!($product = $this->_coreRegistry->registry('product'))) {
$productId = (int) $this->getRequest()->getParam('id');
$product = $this->_productRepository->getById($productId);
$this->_coreRegistry->register('product', $product);
}
}
return $this->_paymentUtil->getWidgetHtml($product->getFinalPrice());
}
}
<?php
namespace MR\Zip\Controller\Order;
use Magento\Framework\App\Action\Context;
// use Symfony\Component\Filesystem\LockHandler;
abstract class CommonAction extends \Magento\Framework\App\Action\Action
{
/**
*
* @var \Magento\Quote\Model\QuoteManagement
*/
private $_quoteManagement;
/**
*
* @var \Magento\Quote\Model\GuestCart\GuestCartManagement
*/
private $_guestCartManagement;
/**
*
* @var \Magento\Checkout\Model\Session
*/
private $_checkoutSession;
/**
*
* @var \MR\Zip\Helper\Communication
*/
private $_communication;
/**
*
* @var \MR\Zip\Helper\Configuration
*/
private $_configuration;
/**
*
* @var \Magento\Framework\Message\ManagerInterface
*/
private $_messageManager;
/**
*
* @var \MR\Zip\Logger\ZipLogger
*/
private $_logger;
public function __construct(Context $context)
{
parent::__construct($context);
$this->_logger = $this->_objectManager->get("\MR\Zip\Logger\ZipLogger");
$this->_communication = $this->_objectManager->get("\MR\Zip\Helper\Communication");
$this->_configuration = $this->_objectManager->get("\MR\Zip\Helper\Configuration");
$this->_quoteManagement = $this->_objectManager->get("\Magento\Quote\Model\QuoteManagement");
$this->_guestCartManagement = $this->_objectManager->get("\Magento\Quote\Model\GuestCart\GuestCartManagement");
$this->_checkoutSession = $this->_objectManager->get("\Magento\Checkout\Model\Session");
$this->_messageManager = $this->_objectManager->get("\Magento\Framework\Message\ManagerInterface");
$this->_logger->info(__METHOD__);
}
public function success()
{
$this->_logger->info(__METHOD__);
$this->_handlePaymentResponse(true);
}
public function fail()
{
$this->_logger->info(__METHOD__);
$this->_handlePaymentResponse(false);
return;
}
protected function _validateToken($zipId, $orderToken){
$requestTokenManager = $this->_objectManager->create("\MR\Zip\Model\RequestToken");
$requestToken = $requestTokenManager->load($zipId, "zip_id");
return $requestToken->getId() && $requestToken->getToken() == $orderToken;
}
private function _handlePaymentResponse($success)
{
$orderIncrementId = $this->getRequest()->getParam('mage_order_id');
$orderToken = $this->getRequest()->getParam('token');
$zipId = $this->getRequest()->getParam('orderId');
if(!$this->_validateToken($zipId, $orderToken)) {
$error = "The token and payment ID do not match at Zip side.";
$this->_logger->info($error);
$this->_redirectToCartPageWithError($error);
return;
}
$this->_logger->info(__METHOD__ . " order:{$orderIncrementId} token:{$orderToken} success:{$success}");
/**
* @var \Symfony\Component\Filesystem\LockHandler
*/
$lockHandler = null;
try {
// $lockHandler = new LockHandler($orderToken, BP . "/var/locks");
// if (!$lockHandler->lock(false)) {
// $action = $this->getRequest()->getActionName();
// $params = $this->getRequest()->getParams();
// $triedTime = 0;
// if (array_key_exists('TriedTime', $params)) {
// $triedTime = $params['TriedTime'];
// }
// if ($triedTime > 40) { // 40 seconds should be enough
// $this->_redirectToCartPageWithError("Failed to process the order, please contact support.");
// $this->_logger->critical(__METHOD__ . " lock timeout. order:{$orderIncrementId} token:{$orderToken} success:{$success} triedTime:{$triedTime}");
// return;
// }
// $params['TriedTime'] = $triedTime + 1;
// $this->_logger->info( __METHOD__ . " redirecting to self, wait for lock release. order:{$orderIncrementId} token:{$orderToken} success:{$success} triedTime:{$triedTime}");
// sleep(1); // wait for sometime about lock release
// return $this->_forward($action, null, null, $params);
// }
$this->_handlePaymentResponseWithoutLock($success, $orderIncrementId, $zipId);
// $lockHandler->release();
} catch (\Exception $e) {
// if (isset($lockHandler)) {
// $lockHandler->release();
// }
$this->_logger->critical(__METHOD__ . " " . "\n" . $e->getMessage() . $e->getTraceAsString());
$this->_redirectToCartPageWithError("Failed to process the order, please contact support.");
}
}
private function _handlePaymentResponseWithoutLock($success, $orderIncrementId, $zipId)
{
$this->_logger->info(__METHOD__ . " order:{$orderIncrementId} zipId:{$zipId} success:{$success}");
if (!$orderIncrementId) {
$error = "The Zip response does not contain an order ID. Order failed.";
$this->_logger->info($error);
$this->_redirectToCartPageWithError($error);
return;
}
$response = $this->_getTransactionStatus($zipId);
if (!$response) {
return;
}
/**
* @var \Magento\Quote\Model\Quote $quote
*/
$quote = $this->_loadQuote($orderIncrementId);
if ($quote == null) {
$error = "Failed to load quote from order: {$orderIncrementId}";
$this->_logger->critical($error);
$this->_redirectToCartPageWithError($error);
return;
}
// $this->_savePaymentResult($orderIncrementId, $orderToken, $quote, $response);
if (!$success || in_array($response['orderStatus'], ['Declined', 'Abandoned'])) {
$payment = $quote->getPayment();
$this->_savePaymentInfoForFailedPayment($payment);
$error = "Payment failed. Error: ";
$this->_logger->info($error);
$this->_redirectToCartPageWithError($error);
return;
}
return $this->_placeOrder($orderIncrementId, $quote, $response);
}
private function _loadQuote($orderIncrementId)
{
$this->_logger->info(__METHOD__ . " reserved_order_id:{$orderIncrementId}");
$quoteManager = $this->_objectManager->create("\Magento\Quote\Model\Quote");
/**
* @var \Magento\Quote\Model\Quote $quote
*/
$quote = $quoteManager->load($orderIncrementId, "reserved_order_id");
if (!$quote->getId()) {
$error = "Failed to load quote from order:{$orderIncrementId}";
$this->_logger->critical($error);
$this->_redirectToCartPageWithError($error);
return null;
}
return $quote;
}
private function _placeOrder($orderIncrementId, \Magento\Quote\Model\Quote $quote, $response)
{
$this->_logger->info(__METHOD__ . " orderIncrementId:{$orderIncrementId}");
$quoteId = $quote->getId();
$payment = $quote->getPayment();
if (!isset($response['orderStatus']) || $response['orderStatus'] != 'Approved') {
throw new \Magento\Framework\Exception\PaymentException(__('Payment failed. Order was not placed.'));
}
$info = $payment->getAdditionalInformation();
$this->_logger->info(__METHOD__ . " info:" . var_export($info, true));
$this->_savePaymentInfoForSuccessfulPayment($payment, $response);
$isRegisteredCustomer = !empty($quote->getCustomerId());
if ($isRegisteredCustomer) {
$quote->setPayment($payment); // looks like $payment is copy by reference. ensure the $payment data of order is exactly same with the quote.
$this->_logger->info(__METHOD__ . " placing order for logged in customer. quoteId:{$quoteId}");
// create order, and redirect to success page.
$orderId = $this->_quoteManagement->placeOrder($quoteId);
} else {
// Guest:
$cartId = $info["cartId"];
$this->_logger->info(__METHOD__ . " placing order for guest. quoteId:{$quoteId} cartId:{$cartId}");
$orderId = $this->_guestCartManagement->placeOrder($cartId);
}
$this->_checkoutSession->setLoadInactive(false);
$this->_checkoutSession->replaceQuote($this->_checkoutSession->getQuote()->save());
$this->_logger->info(__METHOD__ . " placing order done lastSuccessQuoteId:". $this->_checkoutSession->getLastSuccessQuoteId().
" lastQuoteId:".$this->_checkoutSession->getLastQuoteId().
" lastOrderId:".$this->_checkoutSession->getLastOrderId().
" lastRealOrderId:" . $this->_checkoutSession->getLastRealOrderId());
$this->_redirect("checkout/onepage/success", [
"_secure" => true
]);
return;
}
private function _savePaymentInfoForSuccessfulPayment($payment, $response)
{
$this->_logger->info(__METHOD__);
$info = $payment->getAdditionalInformation();
$info = $this->_clearPaymentParameters($info);
$info = array_merge($info, $response);
$payment->unsAdditionalInformation();
$payment->setAdditionalInformation($info);
$info = $payment->getAdditionalInformation();
$this->_logger->info(__METHOD__ . " info: ".var_export($info, true));
$payment->save();
}
private function _savePaymentInfoForFailedPayment($payment)
{
$this->_logger->info(__METHOD__);
$info = $payment->getAdditionalInformation();
$info = $this->_clearPaymentParameters($info);
$payment->unsAdditionalInformation();
$payment->setAdditionalInformation($info);
$payment->save();
}
private function _clearPaymentParameters($info)
{
$this->_logger->info(__METHOD__);
unset($info["cartId"]);
unset($info["guestEmail"]);
unset($info["method_title"]);
$this->_logger->info(__METHOD__ . " info: ".var_export($info, true));
return $info;
}
private function _getTransactionStatus($zipId)
{
try{
if(!$zipId){
throw new \Magento\Framework\Exception\NotFoundException(__('Can\'t find the initial Zip request ID.'));
}
$response = $this->_communication->getTransactionStatus($zipId);
if (!$response) { // defensive code. should never happen
throw new \Magento\Framework\Exception\NotFoundException(__('Transaction status checking response format is incorrect.'));
}
} catch (\Exception $ex) {
$this->_logger->critical(__METHOD__ . " zipId:{$zipId} response format is incorrect");
$this->_redirectToCartPageWithError("Failed to connect to Zip checking transaction status. Please try again later.");
return false;
}
return $response;
}
private function _redirectToCartPageWithError($error)
{
$this->_logger->info(__METHOD__ . " error:{$error}");
$this->_messageManager->addErrorMessage($error);
$this->_redirect("checkout/cart");
}
}
<?php
namespace MR\Zip\Controller\Order;
class Error extends \Magento\Framework\App\Action\Action
{
/**
*
* @var \Magento\Framework\View\Result\PageFactory
*/
private $resultPageFactory;
/**
*
* @var \MR\Zip\Logger\ZipLogger
*/
private $_logger;
public function __construct(
\Magento\Framework\App\Action\Context $context,
\Magento\Framework\View\Result\PageFactory $resultPageFactory
)
{
$this->resultPageFactory = $resultPageFactory;
parent::__construct($context);
$this->_logger = $this->_objectManager->get("\MR\Zip\Logger\ZipLogger");
$this->_logger->info(__METHOD__);
}
public function execute()
{
$this->_logger->info(__METHOD__);
$resultPage = $this->resultPageFactory->create();
$resultPage->getLayout()->initMessages();
return $resultPage;
}
}
<?php
namespace MR\Zip\Controller\Order;
use \Magento\Framework\App\Action\Context;
class Fail extends CommonAction
{
/**
*
* @var \MR\Zip\Logger\ZipLogger
*/
private $_logger;
public function __construct(Context $context)
{
parent::__construct($context);
$this->_logger = $this->_objectManager->get("\MR\Zip\Logger\ZipLogger");
$this->_logger->info(__METHOD__);
}
public function execute()
{
$this->_logger->info(__METHOD__);
$this->fail();
}
}
<?php
namespace MR\Zip\Controller\Order;
class Processed extends \Magento\Framework\App\Action\Action
{
/**
*
* @var \Magento\Framework\View\Result\PageFactory
*/
private $resultPageFactory;
/**
*
* @var \MR\Zip\Logger\ZipLogger
*/
private $_logger;
public function __construct(
\Magento\Framework\App\Action\Context $context,
\Magento\Framework\View\Result\PageFactory $resultPageFactory
)
{
$this->resultPageFactory = $resultPageFactory;
parent::__construct($context);
$this->_logger = $this->_objectManager->get("\MR\Zip\Logger\ZipLogger");
$this->_logger->info(__METHOD__);
}
public function execute()
{
$this->_logger->info(__METHOD__);
$resultPage = $this->resultPageFactory->create();
$resultPage->getLayout()->initMessages();
return $resultPage;
}
}
<?php
// reference:
// https://www.ashsmith.io/2014/12/simple-magento2-controller-module/
// http://www.webmull.com/magento-2-create-simple-hello-world-module/
// http://www.clounce.com/magento/a-very-basic-magento-2-module
// http://www.clounce.com/magento/a-very-basic-magento-2-module-with-parameterized-template
// custom module: http://magento.stackexchange.com/questions/54609/custom-module-not-working-in-magento-2
// http://devdocs.magento.com/guides/v2.0/frontend-dev-guide/bk-frontend-dev-guide.html
// http://stackoverflow.com/questions/32356635/blank-page-in-a-custom-module-magento-2-beta-merchant-version-1-0-0
namespace MR\Zip\Controller\Order;
class Redirect extends \Magento\Framework\App\Action\Action
{
/**
*
* @var \Magento\Framework\View\Result\PageFactory
*/
private $_resultPageFactory;
/**
*
* @var \MR\Zip\Logger\ZipLogger
*/
private $_logger;
public function __construct(
\Magento\Framework\App\Action\Context $context,
\Magento\Framework\View\Result\PageFactory $resultPageFactory
)
{
$this->_resultPageFactory = $resultPageFactory;
parent::__construct($context);
$this->_logger = $this->_objectManager->get("\MR\Zip\Logger\ZipLogger");
$this->_logger->info(__METHOD__);
}
public function execute()
{
$this->_logger->info(__METHOD__);
$resultPage = $this->_resultPageFactory->create();
$resultPage->getLayout()->initMessages();
return $resultPage;
}
}
<?php
namespace MR\Zip\Controller\Order;
use Magento\Framework\App\Action\Context;
class Success extends CommonAction
{
/**
*
* @var \MR\Zip\Logger\ZipLogger
*/
private $_logger;
public function __construct(Context $context)
{
parent::__construct($context);
$this->_logger = $this->_objectManager->get("\MR\Zip\Logger\ZipLogger");
$this->_logger->info(__METHOD__);
}
public function execute()
{
$this->_logger->info(__METHOD__);
$this->success();
}
}
<?php
namespace MR\Zip\Cron;
class MerchantConfiguration
{
/**
*
* @var \Magento\Framework\App\ObjectManager
*/
protected $_objectManager;
/**
* @var \Magento\Store\Model\StoreManagerInterface
*/
protected $_storeManager;
/**
* @var $_paymentUtil \MR\Zip\Helper\PaymentUtil
*/
protected $_paymentUtil;
/**
* MerchantConfiguration Cron constructor.
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
*/
public function __construct(
\Magento\Store\Model\StoreManagerInterface $storeManager
) {
$this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$this->_storeManager = $storeManager;
$this->_paymentUtil = $this->_objectManager->get("\MR\Zip\Helper\PaymentUtil");
}
public function execute()
{
$stores = $this->_storeManager->getStores();
foreach (array_keys($stores) as $storeId){
$merchantConfigurationManager = $this->_objectManager->create("\MR\Zip\Model\Configuration");
$configurationModel = $merchantConfigurationManager->load($storeId, "store_id");
$this->_paymentUtil->refreshMerchantConfiguration($configurationModel, $storeId);
}
}
}
<?php
namespace MR\Zip\Helper;
use Magento\Framework\App\Helper\AbstractHelper;
use Magento\Framework\App\Helper\Context;
class Communication extends AbstractHelper
{
private $_accessToken;
private $_date;
/**
*
* @var \MR\Zip\Helper\Configuration
*/
private $_configuration;
public function __construct(Context $context, \Magento\Framework\Stdlib\DateTime\DateTime $date)
{
parent::__construct($context);
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$this->_logger = $objectManager->get("\MR\Zip\Logger\ZipLogger");
$this->_configuration = $objectManager->get("\MR\Zip\Helper\Configuration");
$this->_logger->info(__METHOD__);
$this->_accessToken = null;
$this->_date = $date;
}
public function getZipPage($requestData, $storeId = null)
{
$this->_logger->info(__METHOD__);
$orderIncrementId = $requestData['merchantReference'];
$requestData['merchant']['redirectConfirmUrl'] = $this->_getUrl('zip/order/success', ['_secure' => true, '_nosid' => true, 'mage_order_id' => $orderIncrementId]);
$requestData['merchant']['redirectCancelUrl'] = $this->_getUrl('zip/order/fail', ['_secure' => true, '_nosid' => true, 'mage_order_id' => $orderIncrementId]);
$requestData = json_encode($requestData);
$this->_logger->info(__METHOD__ . " request: ". $requestData);
$url = $this->_getApiUrl('order', $storeId);
$header = ['Content-Type: application/json', 'Authorization: Bearer ' . $this->_getAccessToken($storeId)];
$result = $this->_sendRequest($url, $header, [], \Magento\Framework\HTTP\ZendClient::POST, $requestData);
return json_decode($result['response'], true);
}
public function getTransactionStatus($zipId, $storeId = null)
{
$this->_logger->info(__METHOD__ . " zipId:{$zipId} storeId:{$storeId}");
$zipUrl = $this->_getApiUrl('/order/'. $zipId, $storeId);
$header = ['Authorization: Bearer ' . $this->_getAccessToken($storeId)];
$result = $this->_sendRequest($zipUrl, $header);
return json_decode($result['response'], true);
}
public function refund($orderIncrementId, $zipId, $amount, $storeId = null)
{
$this->_logger->info(__METHOD__ . "order:{$orderIncrementId} zipId:{$zipId} storeId:{$storeId}");
$requestData = json_encode([
'amount'=> $amount,
'merchantRefundReference' => $orderIncrementId.'-'.$amount.' '.$this->_date->date(),
]);
$this->_logger->info(__METHOD__ . " request: ". $requestData);
$zipUrl = $this->_getApiUrl('/order/' . $zipId . '/refund/', $storeId);
$header = ['Content-Type: application/json', 'Authorization: Bearer ' . $this->_getAccessToken($storeId)];
$result = $this->_sendRequest($zipUrl, $header, [],\Magento\Framework\HTTP\ZendClient::POST, $requestData);
return $result;
}
public function getMerchantConfiguration($storeId)
{
$this->_logger->info(__METHOD__ . "storeId:{$storeId}");
$zipUrl = $this->_getApiUrl('/configuration', $storeId);
$header = ['Content-Type: application/json', 'Authorization: Bearer ' . $this->_getAccessToken($storeId)];
$result = $this->_sendRequest($zipUrl, $header);
return json_decode($result['response'], true);
}
protected function _getAccessToken($storeId = null)
{
if (!$this->_accessToken) {
$accessTokenParam = [
'grant_type' => 'client_credentials',
'client_id' => $this->_configuration->getZipClientId($storeId),
'client_secret' => $this->_configuration->getZipClientSecret($storeId),
'audience' => $this->_configuration->getZipApiAudience($storeId),
];
$headers = [
'Content-Type: application/json'
];
$url = $this->_configuration->getZipAuthTokenEndpoint($storeId);
try {
$accessTokenResult = $this->_sendRequest($url, $headers, [], \Magento\Framework\HTTP\ZendClient::POST, json_encode($accessTokenParam));
$response = json_decode($accessTokenResult['response'], true);
} catch (\Exception $ex) {
$this->_logger->error($ex->getMessage());
return false;
}
if (!$response || !isset($response['access_token'])) {
$errorMessage = 'Can\'t get Zip AccessToken with the credential.';
throw new \Magento\Framework\Exception\PaymentException(__($errorMessage));
}
$this->_accessToken = $response['access_token'];
}
return $this->_accessToken;
}
protected function _getApiUrl($path, $storeId = null)
{
$baseUrl = $this->_configuration->getZipApiEndpoint($storeId);
$apiUrl = rtrim($baseUrl, '/') . '/' . trim($path, '/');
return $apiUrl;
}
private function _sendRequest($url, $header = [], $params = [], $method = \Magento\Framework\HTTP\ZendClient::GET, $postBody = null)
{
$this->_logger->info(__METHOD__ . " postUrl: {$url}");
$ch = curl_init();
switch ($method) {
case "POST":
curl_setopt($ch, CURLOPT_POST, 1);
if ($postBody)
curl_setopt($ch, CURLOPT_POSTFIELDS, $postBody);
break;
case "PUT":
curl_setopt($ch, CURLOPT_PUT, 1);
break;
default:
if (!empty($params))
$url = sprintf("%s?%s", $url, http_build_query($params));
}
curl_setopt($ch, CURLOPT_URL, $url);
if (!empty($header)) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
}
curl_setopt($ch, CURLOPT_TIMEOUT, 180);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($ch);
$errorNo = curl_errno($ch);
$errorMessage = '';
if($errorNo){
$errorMessage = " Error:" . curl_error($ch) . " Error Code:" . curl_errno($ch);
$this->_logger->critical(__METHOD__ . $errorMessage);
}
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($httpcode && substr($httpcode, 0, 2) != "20") {
$errorMessage = " HTTP CODE: {$httpcode} for URL: {$url}";
$this->_logger->critical(__METHOD__ . $errorMessage);
}
$result = [
'httpcode' => $httpcode,
'response' => $response,
'errmsg' => $errorMessage,
];
curl_close($ch);
$this->_logger->info(__METHOD__ . " response from Zip - HttpCode:{$httpcode} Body:{$response}");
return $result;
}
}
<?php
namespace MR\Zip\Helper;
use Magento\Framework\App\Helper\AbstractHelper;
use Magento\Framework\App\Helper\Context;
class Configuration extends AbstractHelper
{
const ZIP_PATH = "payment/mr_zip/";
const MODULE_NAME = "MR_Zip";
/**
*
* @var \Magento\Framework\Module\ModuleListInterface
*/
private $_moduleList;
public function __construct(Context $context)
{
parent::__construct($context);
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$this->_moduleList = $objectManager->get("Magento\Framework\Module\ModuleListInterface");
$this->_logger = $objectManager->get("MR\Zip\Logger\ZipLogger");
}
public function getPaymentType($storeId = null)
{
return 'Purchase';
}
public function getModuleVersion()
{
if ($this->_moduleList == null)
return "M2-unknown";
return "M2-" . $this->_moduleList->getOne(self::MODULE_NAME)['setup_version'];
}
public function getZipClientId($storeId = null)
{
return $this->_getZipStoreConfig("client_id", $storeId);
}
public function getZipClientSecret($storeId = null)
{
return $this->_getZipStoreConfig("client_secret", $storeId, true);
}
public function getZipApiEndpoint($storeId = null)
{
return $this->_getZipStoreConfig("api_endpoint", $storeId);
}
public function getZipAuthTokenEndpoint($storeId = null)
{
return $this->_getZipStoreConfig("auth_token_endpoint", $storeId);
}
public function getZipApiAudience($storeId = null)
{
return $this->_getZipStoreConfig("api_audience", $storeId);
}
public function getEnabled($storeId = null)
{
return filter_var($this->_getZipStoreConfig("active", $storeId), FILTER_VALIDATE_BOOLEAN);
}
public function getDebugFlag($storeId = null)
{
return filter_var($this->_getZipStoreConfig("debug_flag", $storeId), FILTER_VALIDATE_BOOLEAN);
}
public function getMerchantName($storeId = null)
{
return $this->_getZipStoreConfig("merchant_name", $storeId);
}
private function _getZipStoreConfig($configName, $storeId = null, $isSensitiveData = false)
{
$this->_logger->info("Configuration::_getZipStoreConfig storeId argument:" . $storeId);
$value = $this->scopeConfig->getValue(self::ZIP_PATH . $configName, \Magento\Store\Model\ScopeInterface::SCOPE_STORE, $storeId);
if (!$isSensitiveData) {
$this->_logger->info(__METHOD__ . " configName:{$configName} storeId:{$storeId} value:{$value}");
} else {
$this->_logger->info(__METHOD__ . " configName:{$configName} storeId:{$storeId} value:*****");
}
return $value;
}
}
<?php
namespace MR\Zip\Helper;
use Magento\Framework\App\Helper\AbstractHelper;
use Magento\Framework\App\Helper\Context;
class PaymentUtil extends AbstractHelper
{
/**
*
* @var \Magento\Framework\App\ObjectManager
*/
private $_objectManager;
/**
* Asset service
*
* @var \Magento\Framework\View\Asset\Repository
*/
private $_assetRepo;
/**
* @var \MR\Zip\Helper\Communication
*/
protected $_communicationHelper;
/**
* @var $_storeManager \Magento\Store\Model\StoreManagerInterface
*/
protected $_storeManager;
/**
* @var $_configHelper \MR\Zip\Helper\Configuration
*/
protected $_configHelper;
public function __construct(
Context $context,
\Magento\Store\Model\StoreManagerInterface $storeManager
)
{
parent::__construct($context);
$this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$this->_logger = $this->_objectManager->get("\MR\Zip\Logger\ZipLogger");
$this->_assetRepo = $this->_objectManager->get("\Magento\Framework\View\Asset\Repository");
$this->_communicationHelper = $this->_objectManager->get("\MR\Zip\Helper\Communication");
$this->_configHelper = $this->_objectManager->get("\MR\Zip\Helper\Configuration");
$this->_storeManager = $storeManager;
$this->_logger->info(__METHOD__);
}
public function buildRedirectUrl()
{
$this->_logger->info(__METHOD__);
$urlManager = $this->_objectManager->get('\Magento\Framework\Url');
$url = $urlManager->getUrl('zip/order/redirect', ['_secure' => true]);
$this->_logger->info(__METHOD__ . " url: {$url} ");
return $url;
}
public function saveInvalidRefundResponse($payment, $responseText)
{
$this->_logger->info(__METHOD__ . " responseText:{$responseText}");
$info = [
"Error" => $responseText,
];
$payment->setAdditionalInformation(date("Y-m-d H:i:s"), json_encode($info));
$payment->save();
return $info;
}
public function saveZipRefundResponse($payment, $responseBody)
{
$this->_logger->info(__METHOD__ . " responseBody:{$responseBody}");
$response = json_decode($responseBody, true);
if (isset($response['id'])) {
$payment->setTransactionId($response['id']);
}
$payment->setAdditionalInformation(date("Y-m-d H:i:s"), $responseBody);
$payment->save();
return $response;
}
public function loadOrderById($orderId)
{
$this->_logger->info(__METHOD__ . " orderId:{$orderId}");
$orderManager = $this->_objectManager->get('Magento\Sales\Model\Order');
$order = $orderManager->loadByAttribute("entity_id", $orderId);
$orderIncrementId = $order->getIncrementId();
$this->_logger->info(__METHOD__ . " orderIncrementId:{$orderIncrementId}");
if (!isset($orderIncrementId)) {
return null;
}
return $order;
}
public function loadCustomerInfo($order)
{
$customerId = $order->getCustomerId();
$this->_logger->info(__METHOD__ . " customerId:{$customerId}");
$customerInfo = $this->_objectManager->create("\Magento\Framework\DataObject");
$customerInfo->setId($customerId);
$customerInfo->setName($order->getCustomerName());
$customerInfo->setEmail($order->getCustomerEmail());
try {
$address = $order->getBillingAddress();
if ($address) {
$customerInfo->setPhoneNumber($address->getTelephone());
$streetFull = implode(" ", $address->getStreet()) . " " . $address->getCity() . ", " . $address->getRegion() . " " . $address->getPostcode() . " " . $address->getCountryId();
$customerInfo->setAddress($streetFull);
}
} catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
$this->_logger->critical($e->_toString());
}
return $customerInfo;
}
public function findZipOrderForRefund($orderIncrementId, $info)
{
$this->_logger->info(__METHOD__);
$zipId = "";
if (isset($info["orderId"])) {
$zipId = $info["orderId"];
$this->_logger->info(__METHOD__ . "order:{$orderIncrementId} ZipID: {$zipId}");
return $zipId;
}
$this->_logger->info(__METHOD__ . " ZipID not found");
return $zipId;
}
public function getWidgetHtml($totalAmount)
{
$storeId = $this->_storeManager->getStore()->getId();
$merchantConfigurationManager = $this->_objectManager->create("\MR\Zip\Model\Configuration");
$configurationModel = $merchantConfigurationManager->load($storeId, "store_id");
if ($configurationModel && !$configurationModel->getId()) {
$configurationModel = $this->refreshMerchantConfiguration($configurationModel, $storeId);
}
if ($configurationModel->getMin() && $configurationModel->getMax()) {
$merchantName = $this->_configHelper->getMerchantName($storeId) ?: 'your-merchant-name';
$merchantName = urlencode(str_replace(' ', '-', $merchantName));
return '<script async src="https://widgets.partpay.co.nz/' . $merchantName . '/partpay-widget-0.1.1.js?type=calculator&min=' . $configurationModel->getMin() . '&max=' . $configurationModel->getMax() . '&amount=' . $totalAmount . '" type="application/javascript"></script>';
}
return false;
}
public function refreshMerchantConfiguration($merchantConfigurationModel, $storeId)
{
$apiData = $this->_communicationHelper->getMerchantConfiguration($storeId);
$merchantConfigurationModel->addData(
array(
"store_id" => $storeId,
"min" => $apiData['minimumAmount'] ? $apiData['minimumAmount'] : '',
"max" => $apiData['maximumAmount'] ? $apiData['maximumAmount'] : '',
));
$merchantConfigurationModel->save();
return $merchantConfigurationModel;
}
}
<?php
namespace MR\Zip\Helper\Zip;
class UrlCreator
{
/**
*
* @var \Magento\Framework\App\ObjectManager
*/
private $_objectManager;
/**
*
* @var \MR\Zip\Logger\ZipLogger
*/
private $_logger;
/**
*
* @var \MR\Zip\Helper\Configuration
*/
protected $_configuration;
/**
*
* @var \MR\Zip\Helper\Communication
*/
protected $_communication;
public function __construct()
{
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$this->_objectManager = $objectManager;
$this->_communication = $objectManager->get("\MR\Zip\Helper\Communication");
$this->_logger = $objectManager->get("\MR\Zip\Logger\ZipLogger");
$this->_configuration = $objectManager->get("\MR\Zip\Helper\Configuration");
$this->_logger->info(__METHOD__);
}
public function CreateUrl(\Magento\Quote\Model\Quote $quote)
{
$this->_logger->info(__METHOD__);
$requestData = $this->_buildZipRequestData($quote);
try {
$response = $this->_communication->getZipPage($requestData);
}catch (\Exception $ex) {
$this->_logger->error($ex->getMessage());
return false;
}
if (!$response || empty($response['redirectUrl'])) {
$error = "Invalid response from Zip: " . $response;
$this->_logger->critical(__METHOD__ . " " . $error);
return false;
}
$requestTokenModel = $this->_objectManager->create("\MR\Zip\Model\RequestToken");
$requestTokenModel->setData(
array(
"token" => $response['token'],
"url" => $response['redirectUrl'],
"expire" => $response['expiryDateTime'],
"order_id" => $quote->getReservedOrderId(),
"zip_id" => $response['orderId'],
));
$requestTokenModel->save();
$session = $this->_objectManager->get('\Magento\Checkout\Model\Session');
$session->setZipQuoteId($session->getQuote()->getId());
return (string)$response['redirectUrl'];
}
private function _buildZipRequestData(\Magento\Quote\Model\Quote $quote)
{
$orderIncrementId = $quote->getReservedOrderId();
$this->_logger->info(__METHOD__ . " orderIncrementId:{$orderIncrementId}");
$customerInfo = $this->_loadCustomerInfo($quote);
//format order
$param = array();
$param['amount'] = $quote->getBaseGrandTotal();
$param['consumer']['phoneNumber'] = $customerInfo->getPhoneNumber();
$param['consumer']['surname'] = $customerInfo->getSurname();
$param['consumer']['email'] = $quote->getBillingAddress()->getEmail();
$param['billing']['addressLine1'] = $customerInfo->getBillingStreet1();
$param['billing']['addressLine2'] = $customerInfo->getBillingStreet2();
$param['billing']['suburb'] = '';
$param['billing']['city'] = $quote->getBillingAddress()->getCity();
$param['billing']['postcode'] = $quote->getBillingAddress()->getPostcode();
$param['billing']['state'] = $quote->getBillingAddress()->getRegion() ? $quote->getBillingAddress()->getRegion() : '';
$param['billing']['country'] = $quote->getBillingAddress()->getCountry();
$param['shipping']['addressLine1'] = $customerInfo->getShippingStreet1();
$param['shipping']['addressLine2'] = $customerInfo->getShippingStreet2();
$param['shipping']['suburb'] = '';
$param['shipping']['city'] = $quote->getShippingAddress()->getCity();
$param['shipping']['postcode'] = $quote->getShippingAddress()->getPostcode();
$param['shipping']['state'] = $quote->getShippingAddress()->getRegion();
$param['shipping']['country'] = $quote->getShippingAddress()->getCountry();
$param['description'] = '';
$productManager = $this->_objectManager->create("\Magento\Catalog\Model\Product");
//format all items in cart
foreach ( $quote->getAllVisibleItems() as $item){
/**
* @var \Magento\Catalog\Model\Product $product
*/
$product = $productManager->load($item->getProductId());
$param['items'][] = array(
'description' => $product->getDescription(),
'name' => $item->getName(),
'sku' => $item->getSku(),
'quantity' => $item->getQty(),
'price' => $item->getBaseRowTotalInclTax(),
);
}
$param['merchantReference'] = $orderIncrementId;
$param['taxAmount'] = $quote->getShippingAddress()->getBaseTaxAmount();
$param['shippingAmount'] = $quote->getShippingAddress()->getBaseShippingAmount();
$this->_logger->info(__METHOD__ . " param:" . var_export($param, true));
return $param;
}
private function _loadCustomerInfo(\Magento\Quote\Model\Quote $quote)
{
$customerId = $quote->getCustomerId();
$this->_logger->info(__METHOD__ . " customerId:{$customerId}");
$customerInfo = $this->_objectManager->create("\Magento\Framework\DataObject");
$customerInfo->setId($customerId);
$customerInfo->setSurname($this->_getCustomerSurname($quote));
$customerInfo->setEmail($quote->getCustomerEmail());
try {
$billingAddress = $quote->getBillingAddress();
if ($billingAddress) {
$customerInfo->setPhoneNumber($billingAddress->getTelephone());
$billingStreetData = $billingAddress->getStreet();
$streetFull = implode(" ", $billingStreetData) . " " . $billingAddress->getCity() . ", " .
$billingAddress->getRegion() . " " . $billingAddress->getPostcode() . " " . $billingAddress->getCountryId();
if (isset($billingStreetData[0])) {
$customerInfo->setBillingStreet1($billingStreetData[0]);
}
if (isset($billingStreetData[1])) {
$customerInfo->setBillingStreet2($billingStreetData[1]);
}
$customerInfo->setFullAddress($streetFull);
}
if ($shippingAddress = $quote->getShippingAddress()) {
$shippingStreetData = $shippingAddress->getStreet();
if (isset($shippingStreetData[0])) {
$customerInfo->setShippingStreet1($shippingStreetData[0]);
}
if (isset($shippingStreetData[1])) {
$customerInfo->setShippingStreet2($shippingStreetData[1]);
}
}
} catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
$this->_logger->critical($e->_toString());
}
return $customerInfo;
}
/**
* Retrieve customer name
*
* @return string
*/
private function _getCustomerSurname(\Magento\Quote\Model\Quote $quote)
{
if ($quote->getCustomerLastname()) {
$customerName = $quote->getCustomerLastname();
} else {
$customerName = $quote->getBillingAddress()->getLastname();
}
$this->_logger->info(__METHOD__ . " customerSurname:{$customerName}");
return $customerName;
}
}
<?php
namespace MR\Zip\Logger\Handler;
use \Magento\Framework\Filesystem\DriverInterface;
use \Magento\Framework\Logger\Handler\Base;
use \Monolog\Logger;
class All extends Base
{
protected $level = Logger::DEBUG;
public function __construct(DriverInterface $filesystem, $filePath = null)
{
$now = new \DateTime('now');
$strToday = $now->format('Y-m-d');
$this->fileName = "/var/log/mr_zip_{$strToday}.log";
parent::__construct($filesystem, $filePath);
}
}
<?php
namespace MR\Zip\Logger;
// Refer to vendor\monolog\monolog\src\Monolog\Logger.php
// Log to separate file
class ZipLogger extends \Monolog\Logger
{
public function __construct($name, array $handlers = [], array $processors = [])
{
parent::__construct($name, $handlers, $processors);
try {
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$productMetadata = $objectManager->get('\Magento\Framework\App\ProductMetadataInterface');
$version = $productMetadata->getVersion();
$this->pushProcessor(function ($record) use ($version) {
$record['extra']['magentoVersion'] = $version;
return $record;
});
} catch (\Exception $e) {
// print 'Caught exception: ', $e->getMessage(), "\n";
}
}
}
<?php
namespace MR\Zip\Model\Api;
class ApiCommonHelper
{
// http://devdocs.magento.com/guides/v2.0/extension-dev-guide/service-contracts/service-to-web-service.html
/**
*
* @var /Magento\Quote\Model\QuoteIdMaskFactory
*/
private $_quoteIdMaskFactory;
/**
*
* @var \Magento\Quote\Model\QuoteRepository
*/
private $_quoteRepository;
/**
*
* @var \Magento\Quote\Model\PaymentMethodManagement
*/
private $_paymentMethodManagement;
/**
* @var \Magento\Quote\Model\QuoteValidator
*/
private $_quoteValidator;
/**
*
* @var \MR\Zip\Logger\ZipLogger
*/
private $_logger;
public function __construct()
{
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$this->_quoteIdMaskFactory = $objectManager->get("\Magento\Quote\Model\QuoteIdMaskFactory");
$this->_paymentMethodManagement = $objectManager->get("\Magento\Quote\Model\PaymentMethodManagement");
$this->_quoteRepository = $objectManager->get("\Magento\Quote\Model\QuoteRepository");
$this->_quoteValidator = $objectManager->get("\Magento\Quote\Model\QuoteValidator");
$this->_logger = $objectManager->get("\MR\Zip\Logger\ZipLogger");
$this->_logger->info(__METHOD__);
}
public function setPaymentForLoggedinCustomer($quoteId, \Magento\Quote\Api\Data\PaymentInterface $method)
{
$this->_logger->info(__METHOD__. " quoteId:{$quoteId}");
$this->_paymentMethodManagement->set($quoteId, $method);
$quote = $this->_quoteRepository->get($quoteId);
$this->_quoteValidator->validateBeforeSubmit($quote); // ensure all the data is correct
$quote->reserveOrderId();
$this->_quoteRepository->save($quote);
return $quote;
}
public function setPaymentForGuest($cartId, $email, \Magento\Quote\Api\Data\PaymentInterface $method)
{
$this->_logger->info(__METHOD__. " cartId:{$cartId}");
$quoteIdMask = $this->_quoteIdMaskFactory->create()->load($cartId, 'masked_id');
$quoteId = $quoteIdMask->getQuoteId();
$this->_logger->info(__METHOD__. " cartId:{$cartId} quoteId:{$quoteId}");
$this->_paymentMethodManagement->set($quoteId, $method);
$quote = $this->_quoteRepository->get($quoteId);
$quote->getBillingAddress()->setEmail($email);
$this->_quoteValidator->validateBeforeSubmit($quote); // ensure all the data is correct
$quote->setCustomerIsGuest(true);
$quote->reserveOrderId();
$this->_quoteRepository->save($quote);
$payment = $quote->getPayment();
$info = $payment->getAdditionalInformation();
if ($info["cartId"] != $cartId) {
// Maybe merchant do not use the default implementation of PaymentInterface, leads the $method->getData() not return the data from js?
$this->_logger->info(__METHOD__ . " Unexpected behavior! cartId set incorrectly. PaymentInterface.class:" . get_class($method) ." payment.info:" . var_export($info, true));
$info["cartId"] = $cartId;
$info["guestEmail"] = $email;
$payment->setAdditionalInformation($info);
$payment->save();
}
$info = $payment->getAdditionalInformation();
$this->_logger->info(__METHOD__ . " PaymentInterface.class:" . get_class($method) . " info: " . var_export($info, true));
return $quote;
}
}
<?php
namespace MR\Zip\Model\Api;
use \Magento\Framework\Exception\State\InvalidTransitionException;
class ApiZipHelper
{
// http://devdocs.magento.com/guides/v2.0/extension-dev-guide/service-contracts/service-to-web-service.html
/**
*
* @var \MR\Zip\Model\Api\ApiCommonHelper
*/
private $_apiCommonHelper;
/**
*
* @var \MR\Zip\Helper\Zip\UrlCreator
*/
private $_zipUrlCreator;
/**
*
* @var \MR\Zip\Logger\ZipLogger
*/
private $_logger;
public function __construct()
{
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$this->_zipUrlCreator = $objectManager->get("\MR\Zip\Helper\Zip\UrlCreator");
$this->_apiCommonHelper = $objectManager->get("\MR\Zip\Model\Api\ApiCommonHelper");
$this->_logger = $objectManager->get("\MR\Zip\Logger\ZipLogger");
$this->_logger->info(__METHOD__);
}
public function createUrlForCustomer($quoteId, \Magento\Quote\Api\Data\PaymentInterface $method)
{
$this->_logger->info(__METHOD__. " quoteId:{$quoteId}");
/** @var \Magento\Quote\Model\Quote $quote */
$quote = $this->_apiCommonHelper->setPaymentForLoggedinCustomer($quoteId, $method);
return $this->_createUrl($quote);
}
public function createUrlForGuest($cartId, $email, \Magento\Quote\Api\Data\PaymentInterface $method)
{
$this->_logger->info(__METHOD__. " cartId:{$cartId}");
/** @var \Magento\Quote\Model\Quote $quote */
$quote = $this->_apiCommonHelper->setPaymentForGuest($cartId, $email, $method);
return $this->_createUrl($quote);
}
private function _createUrl(\Magento\Quote\Model\Quote $quote)
{
// Create zip redirect url.
$url = $this->_zipUrlCreator->CreateUrl($quote);
if (!isset($url) || empty($url)){
$quoteId = $quote->getId();
$this->_logger->critical(__METHOD__ . " Failed to create transaction quoteId:{$quoteId}");
throw new InvalidTransitionException(__('Failed to create transaction.'));
}
$this->_logger->info(__METHOD__. " redirectUrl:{$url}");
return $url;
}
}
<?php
namespace MR\Zip\Model\Api;
class GuestZipManagement implements \MR\Zip\Api\GuestZipManagementInterface
{
// http://devdocs.magento.com/guides/v2.0/extension-dev-guide/service-contracts/service-to-web-service.html
/**
*
* @var \MR\Zip\Model\Api\ApiZipHelper
*/
private $_apiHelper;
/**
*
* @var \MR\Zip\Logger\ZipLogger
*/
private $_logger;
/**
* @var \Magento\Quote\Api\CartRepositoryInterface
*/
private $_cartRepository;
/**
* @var \Magento\Quote\Model\QuoteIdMaskFactory
*/
private $_quoteIdMaskFactory;
/**
* @var \Magento\Quote\Api\GuestBillingAddressManagementInterface
*/
private $billingAddressManagement;
public function __construct(
\Magento\Quote\Api\CartRepositoryInterface $quoteRepository,
\Magento\Quote\Model\QuoteIdMaskFactory $quoteIdMaskFactory,
\Magento\Quote\Api\GuestBillingAddressManagementInterface $billingAddressManagement
) {
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$this->_apiHelper = $objectManager->get("\MR\Zip\Model\Api\ApiZipHelper");
$this->_logger = $objectManager->get("\MR\Zip\Logger\ZipLogger");
$this->_logger->info(__METHOD__);
$this->_cartRepository = $quoteRepository;
$this->_quoteIdMaskFactory = $quoteIdMaskFactory;
$this->billingAddressManagement = $billingAddressManagement;
}
/**
* {@inheritDoc}
*/
public function set(
$cartId,
$email,
\Magento\Quote\Api\Data\PaymentInterface $method,
\Magento\Quote\Api\Data\AddressInterface $billingAddress = null
) {
$this->_logger->info(__METHOD__. " cartId:{$cartId} guestEmail:{$email}");
// Create zip redirect url.
if ($billingAddress) {
$this->_logger->info(__METHOD__. " assigning billing address.");
$billingAddress->setEmail($email);
$this->billingAddressManagement->assign($cartId, $billingAddress);
} else {
$quoteIdMask = $this->_quoteIdMaskFactory->create()->load($cartId, 'masked_id');
$quoteId = $quoteIdMask->getQuoteId();
$this->_cartRepository->getActive($quoteId)->getBillingAddress()->setEmail($email);
}
$url = $this->_apiHelper->createUrlForGuest($cartId, $email, $method);
$this->_logger->info(__METHOD__. " redirectUrl:{$url}");
return $url;
}
}
<?php
namespace MR\Zip\Model\Api;
class ZipManagement implements \MR\Zip\Api\ZipManagementInterface
{
// http://devdocs.magento.com/guides/v2.0/extension-dev-guide/service-contracts/service-to-web-service.html
/**
*
* @var \MR\Zip\Model\Api\ApiZipHelper
*/
private $_apiHelper;
/**
*
* @var \MR\Zip\Logger\ZipLogger
*/
private $_logger;
/**
*
* @var \Magento\Quote\Api\BillingAddressManagementInterface
*/
private $_billingAddressManagement;
public function __construct(\Magento\Quote\Api\BillingAddressManagementInterface $billingAddressManagement)
{
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$this->_billingAddressManagement = $billingAddressManagement;
$this->_apiHelper = $objectManager->get("\MR\Zip\Model\Api\ApiZipHelper");
$this->_logger = $objectManager->get("\MR\Zip\Logger\ZipLogger");
$this->_logger->info(__METHOD__);
}
/**
* {@inheritDoc}
*/
public function set($cartId, \Magento\Quote\Api\Data\PaymentInterface $method, \Magento\Quote\Api\Data\AddressInterface $billingAddress = null)
{
$this->_logger->info(__METHOD__. " cartId:{$cartId}");
if ($billingAddress) {
$this->_logger->info(__METHOD__. " assigning billing address");
$this->_billingAddressManagement->assign($cartId, $billingAddress);
}
$url = $this->_apiHelper->createUrlForCustomer($cartId, $method);
$this->_logger->info(__METHOD__. " redirectUrl:{$url}");
return $url;
}
}
<?php
// http://www.mage-world.com/blog/how-to-use-model-and-collection-in-magento-2.html
// http://stackoverflow.com/questions/31983546/in-magento-2-what-is-the-correct-way-for-getmodel/31984198
// http://stackoverflow.com/questions/31920769/how-to-save-data-using-model-in-magento2
namespace MR\Zip\Model;
use \Magento\Framework\Model\AbstractModel;
class Configuration extends AbstractModel
{
public function __construct(
\Magento\Framework\Model\Context $context,
\Magento\Framework\Registry $registry,
\Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
\Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
array $data = []
)
{
$this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance();
parent::__construct($context, $registry, $resource, $resourceCollection, $data);
$this->_logger = $this->_objectManager->get("\MR\Zip\Logger\ZipLogger");
$this->_logger->info(__METHOD__);
}
protected function _construct()
{
$this->_logger->info(__METHOD__);
$this->_init('MR\Zip\Model\ResourceModel\Configuration');
}
}
<?php
// Magento\Framework\DataObject implements the magic call function
// Create payment module http://www.josephmcdermott.co.uk/basics-creating-magento2-payment-method
// https://github.com/magento/magento2-samples/tree/master/sample-module-payment-provider
namespace MR\Zip\Model;
class Payment extends \Magento\Payment\Model\Method\AbstractMethod
{
/**
*
* @var \Magento\Framework\App\ObjectManager
*/
private $_objectManager;
protected $_code;
protected $_infoBlockType = 'MR\Zip\Block\Info';
protected $_isGateway = true;
protected $_canCapture = true;
protected $_canUseInternal = false;
protected $_canUseCheckout = true;
protected $_canUseForMultishipping = false;
protected $_canRefund = true;
protected $_canCapturePartial = true;
protected $_canRefundInvoicePartial = true;
/**
*
* @var \MR\Zip\Model\PaymentHelper
*/
private $_paymentHelper;
const MR_ZIP_CODE = "mr_zip";
public function __construct(
\Magento\Framework\Model\Context $context,
\Magento\Framework\Registry $registry,
\Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory,
\Magento\Framework\Api\AttributeValueFactory $customAttributeFactory,
\Magento\Payment\Helper\Data $paymentData,
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
\Magento\Payment\Model\Method\Logger $logger,
\Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
\Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
array $data = []
)
{
parent::__construct(
$context,
$registry,
$extensionFactory,
$customAttributeFactory,
$paymentData,
$scopeConfig,
$logger,
$resource,
$resourceCollection,
$data
);
$this->_code = self::MR_ZIP_CODE;
$this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$this->_logger = $this->_objectManager->get("\MR\Zip\Logger\ZipLogger");
/** @var \MR\Zip\Helper\Configuration $configuration*/
$configuration = $this->_objectManager->get("\MR\Zip\Helper\Configuration");
/** @var \MR\Zip\Helper\Communication $communication*/
$communication = $this->_objectManager->get("\MR\Zip\Helper\Communication");
$this->_paymentHelper = $this->_objectManager->create("\MR\Zip\Model\PaymentHelper");
$this->_paymentHelper->init($configuration, $communication);
$this->_logger->info(__METHOD__);
}
// invoked by Magento\Quote\Model\PaymentMethodManagement::set
public function assignData(\Magento\Framework\DataObject $data)
{
$this->_logger->info(__METHOD__ . " data:" . var_export($data, true));
$infoInstance = $this->getInfoInstance();
$source = $data;
if (isset($data['additional_data'])){
$source = $this->_objectManager->create("\Magento\Framework\DataObject");
$source->setData($data['additional_data']);
}
$info = [];
$info["cartId"] = $source->getData("cartId");
$info["guestEmail"] = $source->getData("guestEmail");
$infoInstance->setAdditionalInformation($info);
$infoInstance->save();
$this->_logger->info(__METHOD__ . " info:" . var_export($info, true));
return $this;
}
public function getConfigPaymentAction()
{
return $this->_paymentHelper->getConfigPaymentAction($this->getStore());
}
// Invoked by Mage_Sales_Model_Order_Payment::capture
public function capture(\Magento\Payment\Model\InfoInterface $payment, $amount)
{
$this->_logger->info(__METHOD__ . " payment amount:" . $amount);
$this->_paymentHelper->capture($payment, $amount, $this->getStore());
return $this;
}
// Mage_Sales_Model_Order_Payment::refund
// use getInfoInstance to get object of Mage_Payment_Model_Info (Mage_Payment_Model_Info::getMethodInstance Mage_Sales_Model_Order_Payment is sub class of Mage_Payment_Model_Info)
public function refund(\Magento\Payment\Model\InfoInterface $payment, $amount)
{
$this->_logger->info(__METHOD__);
$this->_paymentHelper->refund($payment, $amount, $this->getStore());
return $this;
}
public function isAvailable(\Magento\Quote\Api\Data\CartInterface $quote = null)
{
$this->_logger->info(__METHOD__);
return $this->_paymentHelper->isAvailable($quote);
}
}
<?php
// Magento\Framework\DataObject implements the magic call function
// Create payment module http://www.josephmcdermott.co.uk/basics-creating-magento2-payment-method
// https://github.com/magento/magento2-samples/tree/master/sample-module-payment-provider
namespace MR\Zip\Model;
class PaymentHelper
{
/**
*
* @var \MR\Zip\Helper\PaymentUtil
*/
protected $_paymentUtil;
/**
*
* @var \MR\Zip\Helper\Configuration
*/
protected $_configuration;
/**
*
* @var \MR\Zip\Helper\Communication
*/
protected $_communication;
public function __construct()
{
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$this->_logger = $objectManager->get("\MR\Zip\Logger\ZipLogger");
$this->_paymentUtil = $objectManager->get("\MR\Zip\Helper\PaymentUtil");
$this->_communication = $objectManager->get("\MR\Zip\Helper\Communication");
$this->_logger->info(__METHOD__);
}
public function init($configuration, $communication)
{
$this->_logger->info(__METHOD__);
$this->_configuration = $configuration;
$this->_communication = $communication;
}
public function isAvailable(\Magento\Quote\Api\Data\CartInterface $quote = null)
{
$this->_logger->info(__METHOD__);
if ($quote != null){
$enabled = $this->_configuration->getEnabled($quote->getStoreId());
}
else {
$enabled = $this->_configuration->getEnabled();
}
$this->_logger->info(__METHOD__ . " enabled:" . $enabled);
return $enabled;
}
public function getConfigPaymentAction($storeId)
{
// invoked by Magento\Sales\Model\Order\Payment::place
$this->_logger->info(__METHOD__);
$paymentAction = \Magento\Payment\Model\Method\AbstractMethod::ACTION_AUTHORIZE_CAPTURE;
$this->_logger->info(__METHOD__ . " paymentAction: {$paymentAction}");
return $paymentAction;
}
public function capture(\Magento\Payment\Model\InfoInterface $payment, $amount, $storeId)
{
// refer to Magento\Sales\Model\Order\Payment\Transaction\Builder::build for which fields should be set.
$this->_logger->info(__METHOD__);
$orderId = "unknown";
$order = $payment->getOrder();
if ($order) {
$orderId = $order->getIncrementId();
}
if (!$payment->hasAdditionalInformation()) {
$this->_logger->info(__METHOD__ . " orderId:{$orderId} additional_information is empty");
}
$info = $payment->getAdditionalInformation();
$transactionId = $info["orderId"]; // ensure it is unique
$payment->setTransactionId($transactionId);
$payment->setIsTransactionClosed(1);
unset($info['items']);
unset($info['billing']);
unset($info['shipping']);
unset($info['merchant']);
$payment->setTransactionAdditionalInfo(\Magento\Sales\Model\Order\Payment\Transaction::RAW_DETAILS, $info);
}
// Mage_Sales_Model_Order_Payment::refund
// use getInfoInstance to get object of Mage_Payment_Model_Info (Mage_Payment_Model_Info::getMethodInstance Mage_Sales_Model_Order_Payment is sub class of Mage_Payment_Model_Info)
public function refund(\Magento\Payment\Model\InfoInterface $payment, $amount, $storeId)
{
$this->_logger->info(__METHOD__);
$info = $payment->getAdditionalInformation();
$orderIncrementId = $payment->getOrder()->getIncrementId();
$zipId = $this->_paymentUtil->findZipOrderForRefund($orderIncrementId, $info);
$apiResult = $this->_communication->refund($orderIncrementId, $zipId, $amount, $storeId);
$orderId = "unknown";
$order = $payment->getOrder();
if ($order) {
$orderId = $order->getIncrementId();
}
$this->_logger->info(__METHOD__ . " orderId:{$orderId}");
$response = $apiResult['response'];
if ($apiResult['errmsg']) {
$errorMessage = " Failed to refund order:{$orderId}, {$apiResult['errmsg']}, response from Zip: " . $response;
$this->_paymentUtil->saveInvalidRefundResponse($payment, $errorMessage);
$this->_logger->critical(__METHOD__ . $errorMessage);
throw new \Magento\Framework\Exception\PaymentException(__($errorMessage));
}
$this->_paymentUtil->saveZipRefundResponse($payment, $response);
}
}
<?php
// http://www.mage-world.com/blog/how-to-use-model-and-collection-in-magento-2.html
// http://stackoverflow.com/questions/31983546/in-magento-2-what-is-the-correct-way-for-getmodel/31984198
// http://stackoverflow.com/questions/31920769/how-to-save-data-using-model-in-magento2
namespace MR\Zip\Model;
use \Magento\Framework\Model\AbstractModel;
class RequestToken extends AbstractModel
{
public function __construct(
\Magento\Framework\Model\Context $context,
\Magento\Framework\Registry $registry,
\Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
\Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
array $data = []
)
{
$this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance();
parent::__construct($context, $registry, $resource, $resourceCollection, $data);
$this->_logger = $this->_objectManager->get("\MR\Zip\Logger\ZipLogger");
$this->_logger->info(__METHOD__);
}
protected function _construct()
{
$this->_logger->info(__METHOD__);
$this->_init('MR\Zip\Model\ResourceModel\RequestToken');
}
}
<?php
namespace MR\Zip\Model\ResourceModel;
use \Magento\Framework\Model\ResourceModel\Db\AbstractDb;
class Configuration extends AbstractDb
{
protected function _construct()
{
$this->_init('mr_zip_configuration', 'id');
}
}
<?php
namespace MR\Zip\Model\ResourceModel\Configuration;
use \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;
class Collection extends AbstractCollection
{
protected function _construct()
{
$this->_init('MR\Zip\Model\Configuration', 'MR\Zip\Model\ResourceModel\Configuration');
}
}
<?php
namespace MR\Zip\Model\ResourceModel;
use \Magento\Framework\Model\ResourceModel\Db\AbstractDb;
class RequestToken extends AbstractDb
{
protected function _construct()
{
$this->_init('mr_zip', 'id');
}
}
<?php
namespace MR\Zip\Model\ResourceModel\RequestToken;
use \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;
class Collection extends AbstractCollection
{
protected function _construct()
{
$this->_init('MR\Zip\Model\RequestToken', 'MR\Zip\Model\ResourceModel\RequestToken');
}
}
<?php
namespace MR\Zip\Model;
use \Magento\Checkout\Model\ConfigProviderInterface;
// Invoked by Magento\Checkout\Block\Onepage::getCheckoutConfig
class ZipConfigProvider implements ConfigProviderInterface
{
/**
*
* @var \MR\Zip\Logger\ZipLogger
*/
private $_logger;
/**
*
* @var \Magento\Framework\App\ObjectManager
*/
private $_objectManager;
/**
*
* @var \MR\Zip\Helper\Configuration
*/
private $_configuration;
public function __construct(\Magento\Framework\ObjectManagerInterface $objectManager)
{
$this->_objectManager = $objectManager;
$this->_configuration = $this->_objectManager->get("\MR\Zip\Helper\Configuration");
$this->_logger = $this->_objectManager->get("\MR\Zip\Logger\ZipLogger");
$this->_logger->info(__METHOD__);
}
public function getConfig()
{
$this->_logger->info(__METHOD__);
$session = $this->_objectManager->get('\Magento\Checkout\Model\Session');
$quote = $session->getQuote();
$quoteId = $quote->getId();
// $customerSession = $this->_objectManager->get("\Magento\Customer\Model\Session");
$paymentUtil = $this->_objectManager->get("\MR\Zip\Helper\PaymentUtil");
return [
'payment' => [
'zip' => [
'redirectUrl' => $paymentUtil->buildRedirectUrl($quoteId),
'method' => \MR\Zip\Model\Payment::MR_ZIP_CODE
]
]
];
}
}
<?php
namespace MR\Zip\Setup;
use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Framework\DB\Ddl\Table;
use Magento\Framework\DB\Adapter\AdapterInterface;
class InstallSchema implements InstallSchemaInterface
{
/**
* @param SchemaSetupInterface $setup
* @param ModuleContextInterface $context
* @throws \Zend_Db_Exception
*/
public function install(SchemaSetupInterface $setup, ModuleContextInterface $context)
{
$installer = $setup;
$installer->startSetup();
$mrZipTableName = $installer->getTable('mr_zip');
// if exists, then this module should be installed before, just skip it. Use upgrade command to updata the table.
if ($installer->getConnection()->isTableExists($mrZipTableName) != true) {
$mrZipTable = $installer->getConnection()
->newTable($mrZipTableName)
->addColumn(
'id',
Table::TYPE_INTEGER,
11,
[
'identity' => true,
'unsigned' => true,
'nullable' => false,
'primary' => true
],
'ID'
)
->addColumn(
'token',
Table::TYPE_TEXT,
255,
[],
'Token'
)
->addColumn(
'url',
Table::TYPE_TEXT,
255,
[],
'URL'
)
->addColumn(
'expire',
Table::TYPE_TEXT,
255,
[],
'Expire'
)
->addColumn(
'order_id',
Table::TYPE_TEXT,
255,
[],
'Order ID'
)
->addColumn(
'zip_id',
Table::TYPE_TEXT,
255,
[],
'Zip ID'
)
->addIndex('token', 'token')
->addIndex('order_id', 'order_id')
->addIndex('zip_id', 'zip_id')
->setComment('Zip Orders Token Info etc.');
$installer->getConnection()->createTable($mrZipTable);
}
$configurationTableName = $installer->getTable('mr_zip_configuration');
// if exists, then this module should be installed before, just skip it. Use upgrade command to updata the table.
if ($installer->getConnection()->isTableExists($configurationTableName) != true) {
$configurationTable = $installer->getConnection()
->newTable($configurationTableName)
->addColumn(
'id',
Table::TYPE_INTEGER,
11,
[
'identity' => true,
'unsigned' => true,
'nullable' => false,
'primary' => true
],
'ID'
)
->addColumn(
'store_id',
Table::TYPE_INTEGER,
11,
[],
'Store ID'
)
->addColumn(
'min',
Table::TYPE_TEXT,
255,
[],
'Min'
)
->addColumn(
'max',
Table::TYPE_TEXT,
255,
[],
'Max'
)
->setComment('Zip Configuration Table');
$installer->getConnection()->createTable($configurationTable);
}
$installer->endSetup();
}
}
{
"name": "mr/zip",
"description": "Zip",
"require": {
"php": "~5.6.0|7.0.2|~7.0.6",
"magento/module-store": "0.74.0-beta4",
"magento/module-theme": "0.74.0-beta4",
"magento/module-widget": "0.74.0-beta4",
"magento/module-backend": "0.74.0-beta4",
"magento/module-catalog": "0.74.0-beta4",
"magento/module-email": "0.74.0-beta4",
"magento/module-ui": "0.74.0-beta4",
"magento/module-variable": "0.74.0-beta4",
"magento/module-media-storage": "0.74.0-beta4",
"magento/framework": "0.74.0-beta4",
"magento/magento-composer-installer": "*"
},
"type": "magento2-module",
"version": "0.74.0-beta4",
"license": [
"OSL-3.0",
"AFL-3.0"
],
"extra": {
"map": [
[
"*",
"MR/Zip"
]
]
}
}
\ No newline at end of file
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
<system>
<section id="payment">
<group id="mr_zip" translate="label" type="text"
sortOrder="120" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Zip</label>
<field id="active" translate="label" type="select" sortOrder="100"
showInDefault="1" showInWebsite="1" showInStore="1">
<label>Enabled</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
</field>
<field id="client_id" translate="label" type="text"
sortOrder="200" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Client ID</label>
</field>
<field id="client_secret" translate="label" type="password"
sortOrder="300" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Client Secret</label>
</field>
<field id="api_endpoint" translate="label" type="text" sortOrder="400"
showInDefault="1" showInWebsite="1" showInStore="1">
<label>API Endpoint</label>
</field>
<field id="auth_token_endpoint" translate="label" type="text" sortOrder="500"
showInDefault="1" showInWebsite="1" showInStore="1">
<label>Auth Token Endpoint</label>
</field>
<field id="api_audience" translate="label" type="text"
sortOrder="600" showInDefault="1" showInWebsite="1" showInStore="1">
<label>API Audience</label>
</field>
<field id="debug_flag" translate="label" type="select" sortOrder="700"
showInDefault="1" showInWebsite="1" showInStore="1">
<label>Debug Mode</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
</field>
<field id="merchant_name" translate="label" type="text"
sortOrder="800" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Merchant Name</label>
</field>
</group>
</section>
</system>
</config>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
<default>
<payment>
<mr_zip>
<model>MR\Zip\Model\Payment</model>
<active>1</active>
<payment_action>order</payment_action>
<order_status>pending_zip</order_status>
<title>Zip</title>
<allowspecific>0</allowspecific>
<api_endpoint>https://zip.co/nz/api</api_endpoint>
<auth_token_endpoint>login.nz.zip.co/oauth/token</auth_token_endpoint>
<api_audience>https://auth.nz.zip.co</api_audience>
<min>10</min>
<max>1000</max>
<debug_flag>1</debug_flag>
<sort_order>200</sort_order>
</mr_zip>
</payment>
</default>
</config>
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Cron:etc/crontab.xsd">
<group id="default">
<job name="mr_zip_update_merchant_configuration" instance="MR\Zip\Cron\MerchantConfiguration" method="execute">
<schedule>0 0 * * *</schedule>
</job>
</group>
</config>
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="MR\Zip\Logger\ZipLogger">
<arguments>
<argument name="name" xsi:type="string">Zip</argument>
<argument name="handlers" xsi:type="array">
<item name="system" xsi:type="object">MR\Zip\Logger\Handler\All</item>
</argument>
</arguments>
</type>
<preference for="MR\Zip\Api\ZipManagementInterface" type="MR\Zip\Model\Api\ZipManagement" />
<preference for="MR\Zip\Api\GuestZipManagementInterface" type="MR\Zip\Model\Api\GuestZipManagement" />
</config>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Checkout\Model\CompositeConfigProvider">
<arguments>
<argument name="configProviders" xsi:type="array"><item name="mr_zip_config_provider" xsi:type="object">MR\Zip\Model\ZipConfigProvider</item>
</argument>
</arguments>
</type>
</config>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/App/etc/routes.xsd">
<router id="standard">
<route id="zip" frontName="zip">
<module name="MR_Zip" />
</route>
</router>
</config>
\ No newline at end of file
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
<module name="MR_Zip" setup_version="1.0.0"></module>
<sequence>
<module name="Magento_Store" />
<module name="Magento_Backend"/>
<module name="Magento_Sales"/>
<module name="Magento_Quote"/>
<module name="Magento_Checkout"/>
</sequence>
</config>
<?xml version="1.0"?>
<payment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../Magento/Payment/etc/payment.xsd">
<methods>
<method name="mr_zip">
<allow_multiple_address>1</allow_multiple_address>
</method>
</methods>
</payment>
<?xml version="1.0"?>
<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Webapi:etc/webapi.xsd">
<!-- Managing Guest Cart Payment -->
<route url="/V1/guest-carts/:cartId/zip/selected-payment-method" method="PUT">
<service class="MR\Zip\Api\GuestZipManagementInterface" method="set"/>
<resources>
<resource ref="anonymous" />
</resources>
</route>
<!-- Managing my Cart Payment -->
<route url="/V1/carts/mine/zip/selected-payment-method" method="PUT">
<service class="MR\Zip\Api\ZipManagementInterface" method="set"/>
<resources>
<resource ref="self" />
</resources>
<data>
<parameter name="cartId" force="true">%cart_id%</parameter>
</data>
</route>
</routes>
<?php
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'MR_Zip',
__DIR__
);
\ No newline at end of file
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
<head>
<title>Backend Page Title</title>
<!--
demo
<css src="MR_Zip::css/css.css"/>
<script src="MR_Zip::js/js.js"/>
<css src="jquery/fileUploader/css/jquery.fileupload-ui.css"/>
<script src="path/file.js" defer="defer"/>
<link src="http://url.com" src_type="url"/>
<remove src="path/remove/file.css"/>
-->
</head>
<body>
<referenceContainer name="content">
<block class="MR\Zip\Block\Adminhtml\Index\Index" name="zip_block_adminhtml_index_index" template="MR_Zip::zip_index_index.phtml" />
</referenceContainer>
</body>
</page>
\ No newline at end of file
<?php echo $block->escapeHtml($block->getMethod()->getTitle())?>
<?php if ($_specificInfo = $block->getSpecificInformation()):?>
<table>
<?php foreach ($_specificInfo as $_label => $_value):?>
<?php if(strtotime($_label)):?>
<tr>
<td colspan="3"><?php echo $block->escapeHtml($_label)?>:</td>
</tr>
<?php foreach ($_value as $_subKey => $_subValue):?>
<tr>
<td></td>
<td><?php echo $block->escapeHtml($_subKey)?>:</td>
<td><?php echo nl2br(implode($block->getValueAsArray($_subValue, true), "\n"))?></td>
</tr>
<?php endforeach; ?>
<?php else: ?>
<tr>
<td><?php echo $block->escapeHtml($_label)?>:</td>
<td colspan="2"><?php echo nl2br(implode($block->getValueAsArray($_value, true), "\n"))?></td>
</tr>
<?php endif;?>
<?php endforeach; ?>
</table>
<?php endif;?>
<?php echo $block->getChildHtml()?>
Demo Backend Page Content
\ No newline at end of file
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="product.info.main">
<block name="mrzip.widget.product" before="alert.urls" class="MR\Zip\Block\Widget\Product" template="MR_Zip::widget/product.phtml"/>
</referenceContainer>
</body>
</page>
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="checkout.cart.items">
<block name="mrzip.widget.cart" after="checkout.cart.container" class="MR\Zip\Block\Widget\Cart" template="MR_Zip::widget/cart.phtml"/>
</referenceContainer>
</body>
</page>
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column"
xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
<head>
<css src="MR_Zip::css/zipCheckout.css" />
</head>
<body>
<referenceBlock name="checkout.root">
<arguments>
<argument name="jsLayout" xsi:type="array">
<item name="components" xsi:type="array">
<item name="checkout" xsi:type="array">
<item name="children" xsi:type="array">
<item name="steps" xsi:type="array">
<item name="children" xsi:type="array">
<item name="billing-step" xsi:type="array">
<item name="component" xsi:type="string">uiComponent</item>
<item name="children" xsi:type="array">
<item name="payment" xsi:type="array">
<item name="children" xsi:type="array">
<item name="renders" xsi:type="array">
<!-- merge payment method renders here -->
<item name="children" xsi:type="array">
<item name="mr_zip_methods"
xsi:type="array">
<item name="component" xsi:type="string">MR_Zip/js/view/payment/method-renderer</item>
<item name="methods" xsi:type="array">
<item name="mr_zip" xsi:type="array">
<item name="isBillingAddressRequired" xsi:type="boolean">true</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</argument>
</arguments>
</referenceBlock>
</body>
</page>
<?xml version="1.0" encoding="UTF-8"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column"
xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="content">
<block class="MR\Zip\Block\Error" name="error"
template="error.phtml" cacheable="false" />
</referenceContainer>
</body>
</page>
<?xml version="1.0" encoding="UTF-8"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column"
xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="content">
<block class="MR\Zip\Block\Processed" name="processed"
template="processed.phtml" cacheable="false" />
</referenceContainer>
</body>
</page>
<?xml version="1.0" encoding="UTF-8"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column"
xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="content">
<block class="MR\Zip\Block\Redirect" name="redirect"
template="redirect.phtml" cacheable="false" />
</referenceContainer>
</body>
</page>
<?php /** @var $block \MR\Zip\Block\Error */ ?>
<p>Error: <?php echo htmlentities($block->getError()) ?> </p>
<?php if($block->getShowContinueButton()) :?>
<div class="actions-toolbar">
<div class="primary">
<a class="action primary continue"
href="<?php /* @escapeNotVerified */ echo $block->getUrl() ?>"><span><?php /* @escapeNotVerified */ echo __('Continue Shopping') ?></span></a>
</div>
</div>
<?php endif;?>
<?php
/**
* @see MR_Zip_Block_Zip_Info
*/
?>
<?php echo $block->escapeHtml($block->getMethod()->getTitle())?>
<?php $_displayKeys = array("CardName");
$_nameMapping = [
"CardName" => "Payment Type"
];
?>
<?php if ($_specificInfo = $block->getSpecificInformation()):?>
<table>
<?php foreach ($_specificInfo as $_label => $_value):?>
<?php if(strtotime($_label)):?>
<tr>
<td colspan="3"><?php echo $block->escapeHtml($_label)?>:</td>
</tr>
<?php foreach ($_value as $_subKey => $_subValue):?>
<?php if(!in_array($_subKey, $_displayKeys)):?>
<?php continue;?>
<?php endif;?>
<tr>
<td></td>
<td><?php echo $block->escapeHtml($_nameMapping[$_subKey])?>:</td>
<td><?php echo nl2br(implode($block->getValueAsArray($_subValue, true), "\n"))?></td>
</tr>
<?php endforeach; ?>
<?php else: ?>
<?php if(!in_array($_label, $_displayKeys)):?>
<?php continue;?>
<?php endif;?>
<tr>
<td><?php echo $block->escapeHtml($_nameMapping[$_label])?>:</td>
<td colspan="2"><?php echo nl2br(implode($block->getValueAsArray($_value, true), "\n"))?></td>
</tr>
<?php endif;?>
<?php endforeach; ?>
</table>
<?php endif;?>
<?php echo $block->getChildHtml()?>
<?php
// @codingStandardsIgnoreFile
?>
<?php echo $block->getChildHtml()?>
<?php /** @var $block \MR\Zip\Block\Processed */ ?>
<div class="checkout-success">
<p>The order is processed</p>
<div class="actions-toolbar">
<div class="primary">
<a class="action primary continue"
href="<?php /* @escapeNotVerified */ echo $block->getUrl() ?>"><span><?php /* @escapeNotVerified */ echo __('Continue Shopping') ?></span></a>
</div>
</div>
</div>
<?php /** @var $block \MR\Zip\Block\Redirect */ ?>
<?php if($block->getSuccess()) :?>
<p>You will be redirected to the Zip website in a few seconds</p>
<form action="<?php echo $block->getRedirectUrl() ?>" method="get"
id="zip_redirect_form">
<input id="zip_redirect" type="submit"
value="Click here if you are not redirected within 10 seconds..." />
</form>
<script type="text/javascript">
document.getElementById("zip_redirect_form").submit();
</script>
<?php else: ?>
<p><?php echo htmlentities($block->getError()) ?> </p>
<?php if($block->getShowContinueButton()) :?>
<div class="actions-toolbar">
<div class="primary">
<a class="action primary continue"
href="<?php /* @escapeNotVerified */ echo $block->getUrl() ?>"><span><?php /* @escapeNotVerified */ echo __('Continue Shopping') ?></span></a>
</div>
</div>
<?php endif;?>
<?php endif;?>
<?php
/**
* @see \MR\Zip\Block\Widget\Cart
*/
?>
<?php echo $block->getCartWidgetHtml()?>
<?php
/**
* @see \MR\Zip\Block\Widget\Product
*/
?>
<?php echo $block->getProductWidgetHtml()?>
.cvv{
width:200px;
}
.clear{
clear: both;
}
define([ 'jquery',
'Magento_Checkout/js/model/quote',
'Magento_Checkout/js/model/url-builder',
'mage/storage',
'Magento_Checkout/js/model/error-processor',
'Magento_Customer/js/model/customer',
'Magento_Checkout/js/model/full-screen-loader',
'Magento_Customer/js/customer-data',
'Magento_Ui/js/modal/modal'],
function($, quote, urlBuilder, storage, errorProcessor, customer, fullScreenLoader, customerData, modal){
'use strict';
return function(messageContainer, module, paymentData, successAction, successActionParameters){
var serviceUrl, payload;
/**
* Checkout for guest and registered customer.
*/
if (!customer.isLoggedIn()) {
serviceUrl = urlBuilder.createUrl('/guest-carts/:cartId/:module/selected-payment-method', {
cartId : quote.getQuoteId(),
module : module
});
payload = {
cartId : quote.getQuoteId(),
email: quote.guestEmail,
method : paymentData,
billingAddress: quote.billingAddress()
};
} else {
serviceUrl = urlBuilder.createUrl('/carts/mine/:module/selected-payment-method', {module : module});
payload = {
cartId : quote.getQuoteId(),
method : paymentData,
billingAddress: quote.billingAddress()
};
}
fullScreenLoader.startLoader();
console.log("payload:" + JSON.stringify(payload));
return storage.put(serviceUrl, JSON.stringify(payload)).done(
function(response){
console.log("response from server:" + response);
successActionParameters.sessionId = response;
successAction(successActionParameters);
}).fail(
function(response){
console.log("response from server:" + response);
fullScreenLoader.stopLoader();
try {
errorProcessor.process(response, messageContainer);
}
catch (e) {
var errorResponse = { status: 500, responseText: JSON.stringify({ message: "Internal server error" }) };
errorProcessor.process(errorResponse, messageContainer);
var options = {
type: 'popup',
responsive: true,
innerScroll: true,
title: 'Internal server error.',
buttons: [{
text: $.mage.__('Continue'),
class: '',
click: function () {
this.closeModal();
}
}]
};
$('<div></div>').html('Please contact support.').modal(options).modal('openModal');
}
}).always(
function () {
customerData.invalidate(['cart']);
}
);
};
});
define(
[
'uiComponent',
'Magento_Checkout/js/model/payment/renderer-list'
],
function (
Component,
rendererList
) {
'use strict';
rendererList.push(
{
type: 'mr_zip',
component: 'MR_Zip/js/view/payment/method-renderer/zip-payment'
}
);
return Component.extend({});
}
);
/*browser:true*/
/*global define*/
define(
[
'jquery',
'ko',
'Magento_Checkout/js/view/payment/default',
'MR_Zip/js/action/set-payment',
'Magento_Checkout/js/model/payment/additional-validators',
'Magento_Customer/js/model/customer',
'Magento_Checkout/js/model/quote',
],
function ($, ko, Component, setPaymentMethodAction, additionalValidators, customer, quote) {
var zipConfig = window.checkoutConfig.payment.zip;
return Component.extend(
{
redirectToZip: function (parameters) {
window.location.replace(parameters.sessionId);
},
defaults: {
template: 'MR_Zip/payment/zip-payment'
},
getPaymentData: function () {
var additionalData = {};
if (!customer.isLoggedIn()){
additionalData["cartId"] = quote.getQuoteId();
additionalData["guestEmail"] = quote.guestEmail;
}
var data = {
'method': zipConfig.method,
'additional_data' : additionalData
};
return data;
},
continueToZip: function() {
var isValid = jQuery('#co-payment-form').validate({
errorClass: 'mage-error',
errorElement: 'div',
meta: 'validate',
errorPlacement: function (error, element) {
var errorPlacement = element;
if (element.is(':checkbox') || element.is(':radio')) {
errorPlacement = element.siblings('label').last();
}
errorPlacement.after(error);
}
}).form();
if (isValid && additionalValidators.validate()) {
setPaymentMethodAction(this.messageContainer, "zip", this.getPaymentData(), this.redirectToZip, {});
}
},
}
);
}
);
<div class="payment-method"
data-bind="css: {'_active': (getCode() == isChecked())}">
<div class="payment-method-title field choice">
<input type="radio" name="payment[method]" class="radio"
data-bind="attr: {'id': getCode()}, value: getCode(), checked: isChecked, click: selectPaymentMethod, visible: isRadioButtonVisible()" />
<label data-bind="attr: {'for': getCode()}" class="label">
<!-- zipMoney Logo -->
<img style="height:26px" src="https://static.zipmoney.com.au/logo/25px/zip.png" alt="zipMoney Acceptance Mark"
class="payment-icon"/>
<!-- zipMoney Logo -->
<span data-bind="text: getTitle()"></span>
</label>
</div>
<div class="payment-method-content">
<div class="payment-method-billing-address">
<!-- ko foreach: $parent.getRegion(getBillingAddressFormName()) -->
<!-- ko template: getTemplate() -->
<!-- /ko -->
<!--/ko-->
</div>
<div class="checkout-agreements-block">
<!-- ko foreach: $parent.getRegion('before-place-order') -->
<!-- ko template: getTemplate() -->
<!-- /ko -->
<!--/ko-->
</div>
<div class="form-alt" style="padding-top: 2em;">Zip – Own it now</div>
<!-- PaymentInformationManagement::savePaymentInformationAndPlaceOrder -->
<!-- QuoteManagement::placeOrder -->
<!-- OrderService::place -->
<div class="actions-toolbar">
<div class="primary">
<button class="action primary checkout" type="submit"
data-bind="
click: continueToZip,
attr: {title: $t('Continue to Zip')},
enable: (getCode() == isChecked())
"
disabled>
<span data-bind="i18n: 'Continue to Zip'"></span>
</button>
</div>
</div>
</div>
</div>
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