diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 62c8935..0000000
--- a/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-.idea/
\ No newline at end of file
diff --git a/Block/Adminhtml/Sales/Order/Fee.php b/Block/Adminhtml/Sales/Order/Fee.php
new file mode 100644
index 0000000..85e415b
--- /dev/null
+++ b/Block/Adminhtml/Sales/Order/Fee.php
@@ -0,0 +1,71 @@
+_config = $taxConfig;
+ parent::__construct($context, $data);
+ }
+
+ public function displayFullSummary()
+ {
+ return true;
+ }
+
+ public function getSource()
+ {
+ return $this->source;
+ }
+
+ public function getStore()
+ {
+ return $this->order->getStore();
+ }
+
+ public function getOrder()
+ {
+ return $this->order;
+ }
+
+ public function getLabelProperties()
+ {
+ return $this->getParentBlock()->getLabelProperties();
+ }
+
+ public function getValueProperties()
+ {
+ return $this->getParentBlock()->getValueProperties();
+ }
+
+ public function initTotals()
+ {
+ $parent = $this->getParentBlock();
+ $this->order = $parent->getOrder();
+ $this->source = $parent->getSource();
+ $fee = new \Magento\Framework\DataObject(
+ [
+ 'code' => 'cryptapi_fee',
+ 'strong' => false,
+ 'value' => $this->order->getData('cryptapi_fee'),
+ 'label' => __('Service Fee'),
+ ]
+ );
+ $parent->addTotal($fee, 'cryptapi_fee');
+ return $this;
+ }
+}
diff --git a/Block/Adminhtml/Sales/Order/View.php b/Block/Adminhtml/Sales/Order/View.php
index ba3f3ef..9cd845e 100644
--- a/Block/Adminhtml/Sales/Order/View.php
+++ b/Block/Adminhtml/Sales/Order/View.php
@@ -1,7 +1,9 @@
helper = $helper;
$this->payment = $payment;
$this->scopeConfig = $scopeConfig;
- $this->logger = $logger;
+ $this->request = $request;
+ $this->orderRepository = $orderRepository;
+ $this->productMetadata = $productMetadata;
}
public function getTemplateValues()
{
- $order = $this->payment->getOrder();
+ if ($this->productMetadata->getVersion() >= 2.3 && $this->productMetadata->getVersion() < 2.4) {
+ $order = $this->payment->getOrder();
+ } else {
+ $order_id = (int)$this->request->getParam('order_id');
+ $nonce = (string)$this->request->getParam('nonce');
+ $order = $this->orderRepository->get($order_id);
+ }
$total = $order->getGrandTotal();
$currencySymbol = $order->getOrderCurrencyCode();
-
$metaData = $this->helper->getPaymentResponse($order->getQuoteId());
if (empty($metaData)) {
return false;
}
+ $qrCodeSize = $this->scopeConfig->getValue('payment/cryptapi/qrcode_size', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
+
+ $branding = $this->scopeConfig->getValue('payment/cryptapi/show_branding', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
+
$metaData = json_decode($metaData, true);
+ if (!$this->productMetadata->getVersion() >= 2.3 && $this->productMetadata->getVersion() < 2.4) {
+ if ($nonce != $metaData['cryptapi_nonce']) {
+ return false;
+ }
+ }
+
$cryptoValue = $metaData['cryptapi_total'];
$cryptoCoin = $metaData['cryptapi_currency'];
if (isset($metaData['cryptapi_address']) && !empty($metaData['cryptapi_address'])) {
$addressIn = $metaData['cryptapi_address'];
} else {
-
$selected = $cryptoCoin;
$address = '';
@@ -69,37 +88,41 @@ public function getTemplateValues()
$api = new CryptAPIHelper($selected, $address, $callbackUrl, $params, true);
$addressIn = $api->get_address();
+ $qrCode = $api->get_qrcode('', $qrCodeSize);
+ $qrCodeValue = $api->get_qrcode($cryptoValue, $qrCodeSize);
+
$this->helper->updatePaymentData($order->getQuoteId(), 'cryptapi_address', $addressIn);
+ $this->helper->updatePaymentData($order->getQuoteId(), 'cryptapi_qr_code_value', $qrCodeValue['qr_code']);
+ $this->helper->updatePaymentData($order->getQuoteId(), 'cryptapi_qr_code', $qrCode['qr_code']);
}
$ajaxParams = [
- 'order_id' => $order->getId()
+ 'order_id' => $order->getId(),
];
$ajaxUrl = $this->payment->getAjaxStatusUrl($ajaxParams);
- $qrCodeSize = $this->scopeConfig->getValue('payment/cryptapi/qrcode_size', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
-
- $branding = $this->scopeConfig->getValue('payment/cryptapi/show_branding', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
-
- $qrCode = $api->get_qrcode('', $qrCodeSize);
- $qrCodeValue = $api->get_qrcode($cryptoValue, $qrCodeSize);
+ $metaData = $this->helper->getPaymentResponse($order->getQuoteId());
+ $metaData = json_decode($metaData, true);
- $values = [
- 'crypto_value' => $cryptoValue,
+ return [
+ 'crypto_value' => floatval($cryptoValue),
'currency_symbol' => $currencySymbol,
'total' => $total,
'address_in' => $addressIn,
'crypto_coin' => $cryptoCoin,
'ajax_url' => $ajaxUrl,
'qrcode_size' => $qrCodeSize,
- 'qrcode' => $qrCode['qr_code'],
- 'qrcode_value' => $qrCodeValue['qr_code'],
+ 'qrcode' => $metaData['cryptapi_qr_code'],
+ 'qrcode_value' => $metaData['cryptapi_qr_code_value'],
'qrcode_default' => $this->scopeConfig->getValue('payment/cryptapi/qrcode_default', \Magento\Store\Model\ScopeInterface::SCOPE_STORE),
- 'payment_uri' => $qrCode['uri'],
- 'show_branding' => $branding
+ 'show_branding' => $branding,
+ 'qr_code_setting' => $this->scopeConfig->getValue('payment/cryptapi/qrcode_setting', \Magento\Store\Model\ScopeInterface::SCOPE_STORE),
+ 'order_timestamp' => strtotime($order->getCreatedAt()),
+ 'order_cancelation_timeout' => $this->scopeConfig->getValue('payment/cryptapi/order_cancelation_timeout', \Magento\Store\Model\ScopeInterface::SCOPE_STORE),
+ 'refresh_value_interval' => $this->scopeConfig->getValue('payment/cryptapi/refresh_value_interval', \Magento\Store\Model\ScopeInterface::SCOPE_STORE),
+ 'last_price_update' => $metaData['cryptapi_last_price_update'],
+ 'min_tx' => $metaData['cryptapi_min'],
];
-
- return $values;
}
}
diff --git a/Controller/Index/Callback.php b/Controller/Index/Callback.php
index 16d727d..7c75d81 100644
--- a/Controller/Index/Callback.php
+++ b/Controller/Index/Callback.php
@@ -3,9 +3,9 @@
namespace Cryptapi\Cryptapi\Controller\Index;
use Cryptapi\Cryptapi\lib\CryptAPIHelper;
-use Magento\Framework\Controller\ResultFactory;
+use Magento\Framework\App\Action\HttpGetActionInterface;
-class Callback extends \Magento\Framework\App\Action\Action
+class Callback implements HttpGetActionInterface
{
protected $helper;
protected $payment;
@@ -13,65 +13,94 @@ class Callback extends \Magento\Framework\App\Action\Action
public function __construct(
\Cryptapi\Cryptapi\Helper\Data $helper,
- \Cryptapi\Cryptapi\Model\Pay $payment,
- \Magento\Sales\Model\OrderFactory $orderFactory,
+ \Cryptapi\Cryptapi\Model\Method\CryptapiPayment $payment,
+ \Magento\Sales\Api\OrderRepositoryInterface $orderRepository,
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
- \Magento\Framework\App\Action\Context $context
+ \Magento\Framework\App\Request\Http $request,
+ \Magento\Framework\App\Response\Http $response
)
{
$this->helper = $helper;
$this->payment = $payment;
- $this->orderFactory = $orderFactory;
+ $this->orderRepository = $orderRepository;
$this->scopeConfig = $scopeConfig;
- parent::__construct($context);
+ $this->request = $request;
+ $this->response = $response;
}
public function execute()
{
- $params = $this->getRequest()->getParams();
+ $params = $this->request->getParams();
$data = CryptAPIHelper::process_callback($params);
- $order = $this->orderFactory->create()->load($data['order_id']);
+ $order = $this->orderRepository->get($data['order_id']);
+ $orderId = $order->getQuoteId();
- $metaData = $this->helper->getPaymentResponse($order->getQuoteId());
+ $currencySymbol = $order->getOrderCurrencyCode();
- if (!empty($metaData)) {
- $metaData = json_decode($metaData, true);
- }
+ $metaData = json_decode($this->helper->getPaymentResponse($orderId), true);
if ($this->payment->hasBeenPaid($order) || $data['nonce'] != $metaData['cryptapi_nonce']) {
- return $this->getResponse()->setBody("*ok*");
+ return $this->response->setBody("*ok*");
}
- $alreadyPaid = 0;
+ $paid = floatval($data['value_coin']);
- if (isset($metaData['cryptapi_paid'])) {
- $alreadyPaid = $metaData['cryptapi_paid'];
- }
+ $min_tx = floatval($metaData['cryptapi_min']);
- $paid = floatval($alreadyPaid) + floatval($data['value_coin']);
+ $history = json_decode($metaData['cryptapi_history'], true);
- if (!$data['pending']) {
- $this->helper->updatePaymentData($order->getQuoteId(), 'cryptapi_paid', $paid);
+ $update_history = true;
+
+ foreach ($history as $uuid => $item) {
+ if ($uuid === $data['uuid']) {
+ $update_history = false;
+ }
}
- if ($paid >= $metaData['cryptapi_total']) {
- if ($data['pending']) {
- $this->helper->updatePaymentData($order->getQuoteId(), 'cryptapi_pending', "1");
- } else {
- $this->helper->deletePaymentData($order->getQuoteId(), 'cryptapi_pending');
+ if ($update_history) {
+ $fiat_conversion = CryptAPIHelper::get_conversion($metaData['cryptapi_currency'], $currencySymbol, $paid, $this->scopeConfig->getValue('payment/cryptapi/disable_conversion', \Magento\Store\Model\ScopeInterface::SCOPE_STORE));
+
+ $history[$data['uuid']] = [
+ 'timestamp' => time(),
+ 'value_paid' => $paid,
+ 'value_paid_fiat' => $fiat_conversion,
+ 'pending' => $data['pending']
+ ];
+ } else {
+ $history[$data['uuid']]['pending'] = $data['pending'];
+ }
+
+ $this->helper->updatePaymentData($orderId, 'cryptapi_history', json_encode($history));
+
+ $metaData = json_decode($this->helper->getPaymentResponse($orderId), true);
+ $history = json_decode($metaData['cryptapi_history'], true);
+
+ $calc = $this->payment::calcOrder($history, $metaData);
+
+ $remaining = $calc['remaining'];
+ $remaining_pending = $calc['remaining_pending'];
+
+ if ($remaining_pending <= 0) {
+ if ($remaining <= 0) {
$state = \Magento\Sales\Model\Order::STATE_PROCESSING;
$status = \Magento\Sales\Model\Order::STATE_PROCESSING;
$order->setState($state);
$order->setStatus($status);
$order->setTotalPaid($order->getGrandTotal());
$order->save();
-
- $this->helper->updatePaymentData($order->getQuoteId(), 'cryptapi_txid', $data['txid_in']);
}
+ return $this->response->setBody("*ok*");
}
- return $this->getResponse()->setBody("*ok*");
+
+ if ($remaining_pending <= $min_tx) {
+ $this->helper->updatePaymentData($orderId, 'cryptapi_qr_code_value', CryptAPIHelper::get_static_qrcode($metaData['cryptapi_address'], $metaData['cryptapi_currency'], $min_tx, $this->scopeConfig->getValue('payment/cryptapi/qrcode_size', \Magento\Store\Model\ScopeInterface::SCOPE_STORE))['qr_code']);
+ } else {
+ $this->helper->updatePaymentData($orderId, 'cryptapi_qr_code_value', CryptAPIHelper::get_static_qrcode($metaData['cryptapi_address'], $metaData['cryptapi_currency'], $remaining_pending, $this->scopeConfig->getValue('payment/cryptapi/qrcode_size', \Magento\Store\Model\ScopeInterface::SCOPE_STORE))['qr_code']);
+ }
+
+ return $this->response->setBody("*ok*");
}
}
diff --git a/Controller/Index/CartQuote.php b/Controller/Index/CartQuote.php
new file mode 100644
index 0000000..5fbdede
--- /dev/null
+++ b/Controller/Index/CartQuote.php
@@ -0,0 +1,38 @@
+checkoutSession = $checkoutSession;
+ $this->request = $request;
+ $this->response = $response;
+ }
+
+ public function execute()
+ {
+ $selected = (string)$this->request->getParam('selected');
+
+ $this->checkoutSession->setCurrency($selected);
+
+ $data = [
+ 'status' => 'done'
+ ];
+
+ $response = json_encode($data);
+ return $this->response->setBody($response);
+ }
+}
diff --git a/Controller/Index/Payment.php b/Controller/Index/Payment.php
new file mode 100644
index 0000000..8e5c910
--- /dev/null
+++ b/Controller/Index/Payment.php
@@ -0,0 +1,24 @@
+pageFactory = $pageFactory;
+ }
+
+ public function execute()
+ {
+ return $this->pageFactory->create();
+ }
+}
+
diff --git a/Controller/Index/Status.php b/Controller/Index/Status.php
index df7e074..93c5e7d 100644
--- a/Controller/Index/Status.php
+++ b/Controller/Index/Status.php
@@ -1,52 +1,98 @@
helper = $helper;
$this->payment = $payment;
- $this->orderFactory = $orderFactory;
- parent::__construct($context);
+ $this->orderRepository = $orderRepository;
+ $this->scopeConfig = $scopeConfig;
+ $this->cronjob = $cronjob;
+ $this->request = $request;
+ $this->response = $response;
+ $this->priceHelper = $priceHelper;
+ $this->logger = $logger;
}
public function execute()
{
- $order_id = (int)$this->getRequest()->getParam('order_id');
-
- try {
- $order = $this->orderFactory->create()->load($order_id);
- $metaData = $this->helper->getPaymentResponse($order->getQuoteId());
- if (!empty($metaData)) {
- $metaData = json_decode($metaData, true);
- }
-
- $cryptapi_pending = 0;
- if (isset($metaData['cryptapi_pending'])) {
- $cryptapi_pending = $metaData['cryptapi_pending'];
- }
-
- $data = [
- 'is_paid' => $this->payment->hasBeenPaid($order),
- 'is_pending' => (int)($cryptapi_pending),
- ];
-
- $response = json_encode($data);
- return $this->getResponse()->setBody($response);
- } catch (\Exception $e) {
- ;
+ $orderId = (int)$this->request->getParam('order_id');
+
+ $order = $this->orderRepository->get($orderId);
+ $metaData = $this->helper->getPaymentResponse($order->getQuoteId());
+
+ if (!empty($metaData)) {
+ $metaData = json_decode($metaData, true);
}
- $response = json_encode(['status' => 'error', 'error' => 'Not a valid order id']);
+
+ $showMinFee = '0';
+
+ $history = json_decode($metaData['cryptapi_history'], true);
+
+ $calc = $this->payment::calcOrder($history, $metaData);
+
+ $already_paid = $calc['already_paid'];
+ $already_paid_fiat = $calc['already_paid_fiat'] <= 0 ? 0 : $calc['already_paid_fiat'];
+
+ $min_tx = floatval($metaData['cryptapi_min']);
+
+ // $remaining = $calc['remaining'];
+ $remaining_pending = $calc['remaining_pending'];
+ $remaining_fiat = $calc['remaining_fiat'];
+
+ $cryptapi_pending = '0';
+ if ($remaining_pending <= 0 && !$this->payment->hasBeenPaid($order)) {
+ $cryptapi_pending = '1';
+ }
+
+ $counter_calc = (int)$metaData['cryptapi_last_price_update'] + (int)$this->scopeConfig->getValue('payment/cryptapi/refresh_value_interval', \Magento\Store\Model\ScopeInterface::SCOPE_STORE) - time();
+ if (!$this->payment->hasBeenPaid($order) && $counter_calc <= 0) {
+ $this->cronjob->execute();
+ }
+
+ if ($remaining_pending <= $min_tx && $remaining_pending > 0) {
+ $remaining_pending = $min_tx;
+ $showMinFee = '1';
+ }
+
+ $data = [
+ 'is_paid' => $this->payment->hasBeenPaid($order),
+ 'is_pending' => (int)($cryptapi_pending),
+ 'crypto_total' => floatval($metaData['cryptapi_total']),
+ 'qr_code_value' => $metaData['cryptapi_qr_code_value'],
+ 'cancelled' => $metaData['cryptapi_cancelled'],
+ 'remaining' => $remaining_pending <= 0 ? 0 : $remaining_pending,
+ 'fiat_remaining' => $this->priceHelper->currency($remaining_fiat, true, false),
+ 'coin' => strtoupper($metaData['cryptapi_currency']),
+ 'show_min_fee' => $showMinFee,
+ 'order_history' => $history,
+ 'already_paid' => $already_paid,
+ 'already_paid_fiat' => $this->priceHelper->currency($remaining_pending <= 0 ? 0 : floatval($already_paid_fiat), true, false),
+ 'counter' => (string)$counter_calc,
+ 'fiat_symbol' => $order->getOrderCurrencyCode()
+ ];
+
$response = json_encode($data);
- return $this->getResponse()->setBody($response);
+ return $this->response->setBody($response);
}
}
diff --git a/Cron/CryptapiCronjob.php b/Cron/CryptapiCronjob.php
new file mode 100644
index 0000000..b6d7324
--- /dev/null
+++ b/Cron/CryptapiCronjob.php
@@ -0,0 +1,121 @@
+scopeConfig = $scopeConfig;
+ $this->orderCollectionFactory = $orderCollectionFactory;
+ $this->helper = $helper;
+ $this->orderRepository = $orderRepository;
+ $this->payment = $payment;
+ $this->logger = $logger;
+ }
+
+ public function execute()
+ {
+ $order_timeout = (int)$this->scopeConfig->getValue('payment/cryptapi/order_cancelation_timeout');
+ $value_refresh = (int)$this->scopeConfig->getValue('payment/cryptapi/refresh_value_interval');
+
+ if ($order_timeout === 0 && $value_refresh === 0) {
+ return;
+ }
+
+ $orders = $this->getOrderCollectionPaymentMethod();
+
+ if (empty($orders)) {
+ return;
+ }
+
+ $disable_conversion = $this->scopeConfig->getValue('payment/cryptapi/disable_conversion');
+
+ foreach ($orders as $order) {
+ $orderQuoteId = $order->getQuoteId();
+
+ $metaData = json_decode($this->helper->getPaymentResponse($order->getQuoteId()), true);
+
+ $history = json_decode($metaData['cryptapi_history'], true);
+
+ $min_tx = floatval($metaData['cryptapi_min']);
+
+ $calc = $this->payment::calcOrder($history, $metaData);
+
+ $remaining = $calc['remaining'];
+ $remaining_pending = $calc['remaining_pending'];
+ $remaining_fiat = $calc['remaining_fiat'];
+
+ if (!empty($metaData['cryptapi_address']) && $value_refresh !== 0 && $metaData['cryptapi_cancelled'] !== '1' && (int)$metaData['cryptapi_last_price_update'] + $value_refresh <= time() && $remaining_pending > 0) {
+
+ if ($remaining === $remaining_pending) {
+ $cryptapi_coin = $metaData['cryptapi_currency'];
+
+ $crypto_total = CryptAPIHelper::get_conversion($order->getOrderCurrencyCode(), $cryptapi_coin, $metaData['cryptapi_total_fiat'], $disable_conversion);
+ $this->helper->updatePaymentData($orderQuoteId, 'cryptapi_total', $crypto_total);
+
+ $calc_cron = $this->payment::calcOrder($history, $metaData);
+ $crypto_remaining_total = $calc_cron['remaining_pending'];
+
+ if ($remaining_pending <= $min_tx && !$remaining_pending <= 0) {
+ $qr_code_data_value = CryptAPIHelper::get_static_qrcode($metaData['cryptapi_address'], $cryptapi_coin, $min_tx, $this->scopeConfig->getValue('payment/cryptapi/qrcode_size'));
+ } else {
+ $qr_code_data_value = CryptAPIHelper::get_static_qrcode($metaData['cryptapi_address'], $cryptapi_coin, $crypto_remaining_total, $this->scopeConfig->getValue('payment/cryptapi/qrcode_size'));
+ }
+
+ $this->helper->updatePaymentData($orderQuoteId, 'cryptapi_qr_code_value', $qr_code_data_value['qr_code']);
+
+ }
+
+ $this->helper->updatePaymentData($orderQuoteId, 'cryptapi_last_price_update', time());
+ }
+
+ if ($order_timeout !== 0 && ((int)strtotime($order->getCreatedAt()) + $order_timeout) <= time() && empty($metaData['cryptapi_pending']) && $remaining_fiat <= $order->getGrandTotal() && (string)$metaData['cryptapi_cancelled'] === '0') {
+ $state = \Magento\Sales\Model\Order::STATE_CANCELED;
+ $status = \Magento\Sales\Model\Order::STATE_CANCELED;
+ $order->setState($state);
+ $order->setStatus($status);
+ $this->helper->updatePaymentData($orderQuoteId, 'cryptapi_cancelled', '1');
+ $order->save();
+ }
+ }
+ }
+
+ private function getOrderCollectionPaymentMethod()
+ {
+ $orders = $this->orderCollectionFactory->create()
+ ->addFieldToSelect('*')
+ ->addFieldToFilter('status',
+ ['in' => ['pending']]
+ );
+
+ $orders->getSelect()
+ ->join(
+ ["sop" => "sales_order_payment"],
+ 'main_table.entity_id = sop.parent_id',
+ array('method')
+ )
+ ->where('sop.method = ?', 'cryptapi');
+
+ $orders->setOrder(
+ 'created_at',
+ 'desc'
+ );
+
+ return $orders;
+ }
+}
diff --git a/Helper/Decimal.php b/Helper/Decimal.php
new file mode 100644
index 0000000..f54e113
--- /dev/null
+++ b/Helper/Decimal.php
@@ -0,0 +1,53 @@
+precision;
+ }
+
+ private function maybe_reduce_precision($new_val) {
+ while ($new_val >= PHP_INT_MAX) {
+ $new_val = ($new_val / 10 ** $this->precision) * 10 ** ($this->precision - 1);
+ $this->precision -= 1;
+ }
+
+ $this->val = intval($new_val);
+ }
+
+ function __construct($float_val) {
+ $this->sum($float_val);
+ }
+
+ function mult($float_val) {
+ $new_val = $this->val * $this->to_int($float_val);
+ $this->maybe_reduce_precision($new_val);
+ return $this;
+ }
+
+ function div($float_val) {
+ $new_val = $this->val / $this->to_int($float_val);
+ $this->maybe_reduce_precision($new_val);
+ return $this;
+ }
+
+ function sum($float_val) {
+ $new_val = $this->val + $this->to_int($float_val);
+ $this->maybe_reduce_precision($new_val);
+ return $this;
+ }
+
+ function sub($float_val) {
+ $new_val = $this->val - $this->to_int($float_val);
+ $this->maybe_reduce_precision($new_val);
+ return $this;
+ }
+
+ function result() {
+ return $this->val / 10 ** $this->precision;
+ }
+}
diff --git a/Model/ConfigPlugin.php b/Model/Config/ConfigPlugin.php
similarity index 94%
rename from Model/ConfigPlugin.php
rename to Model/Config/ConfigPlugin.php
index ca549bc..f14f3ee 100644
--- a/Model/ConfigPlugin.php
+++ b/Model/Config/ConfigPlugin.php
@@ -1,8 +1,6 @@
'Never',
+ '3600' => '1 Hour',
+ '21600' => '6 Hours',
+ '43200' => '12 Hours',
+ '64800' => '18 Hours',
+ '86400' => '24 Hours',
+ ];
+ }
+}
diff --git a/Model/Config/Source/FeesList.php b/Model/Config/Source/FeesList.php
new file mode 100644
index 0000000..9edc0a6
--- /dev/null
+++ b/Model/Config/Source/FeesList.php
@@ -0,0 +1,42 @@
+ '5%',
+ '0.048' => '4.8%',
+ '0.045' => '4.5%',
+ '0.042' => '4.2%',
+ '0.04' => '4%',
+ '0.038' => '3.8%',
+ '0.035' => '3.5%',
+ '0.032' => '3.2%',
+ '0.03' => '3%',
+ '0.028' => '2.8%',
+ '0.025' => '2.5%',
+ '0.022' => '2.2%',
+ '0.02' => '2%',
+ '0.018' => '1.8%',
+ '0.015' => '1.5%',
+ '0.012' => '1.2%',
+ '0.01' => '1%',
+ '0.0090' => '0.90%',
+ '0.0085' => '0.85%',
+ '0.0080' => '0.80%',
+ '0.0075' => '0.75%',
+ '0.0070' => '0.70%',
+ '0.0065' => '0.65%',
+ '0.0060' => '0.60%',
+ '0.0055' => '0.55%',
+ '0.0050' => '0.50%',
+ '0.0040' => '0.40%',
+ '0.0030' => '0.30%',
+ '0.0025' => '0.25%',
+ 'none' => '0%',
+ ];
+ }
+}
diff --git a/Model/Config/Source/QrcodeOptions.php b/Model/Config/Source/QrcodeOptions.php
new file mode 100644
index 0000000..487a6a4
--- /dev/null
+++ b/Model/Config/Source/QrcodeOptions.php
@@ -0,0 +1,16 @@
+ 'Default Without Ammount',
+ 'ammount' => 'Default Ammount',
+ 'hide_ammount' => 'Hide Ammount',
+ 'hide_without_ammount' => 'Hide Without Ammount',
+ ];
+ }
+}
diff --git a/Model/Config/Source/RefreshList.php b/Model/Config/Source/RefreshList.php
new file mode 100644
index 0000000..fb86c0d
--- /dev/null
+++ b/Model/Config/Source/RefreshList.php
@@ -0,0 +1,19 @@
+ 'Never',
+ '300' => 'Every 5 Minutes',
+ '600' => 'Every 10 Minutes',
+ '900' => 'Every 15 Minutes',
+ '1800' => 'Every 30 Minutes',
+ '2700' => 'Every 45 Minutes',
+ '3600' => 'Every 60 Minutes',
+ ];
+ }
+}
diff --git a/Model/Config/Source/SchemeList.php b/Model/Config/Source/SchemeList.php
new file mode 100644
index 0000000..6e991ac
--- /dev/null
+++ b/Model/Config/Source/SchemeList.php
@@ -0,0 +1,15 @@
+ 'Light',
+ 'dark' => 'Dark',
+ 'auto' => 'Auto',
+ ];
+ }
+}
diff --git a/Model/Pay.php b/Model/Method/CryptapiPayment.php
similarity index 76%
rename from Model/Pay.php
rename to Model/Method/CryptapiPayment.php
index d86bfdb..0c23f75 100644
--- a/Model/Pay.php
+++ b/Model/Method/CryptapiPayment.php
@@ -1,12 +1,14 @@
getAdditionalInformation('cryptapi_coin');
if (empty($selected)) {
- throw new \Magento\Framework\Exception\LocalizedException(
- __('Please select a cryptocurrency.')
- );
+ return $this;
}
$nonce = $this->generateNonce();
@@ -135,9 +135,9 @@ public function validate()
$total = $quote->getGrandTotal();
$cryptoTotal = CryptAPIHelper::get_conversion(
+ $currencyCode,
$selected,
$total,
- $currencyCode,
$this->scopeConfig->getValue('payment/cryptapi/disable_conversion', \Magento\Store\Model\ScopeInterface::SCOPE_STORE)
);
@@ -153,7 +153,14 @@ public function validate()
'cryptapi_nonce' => $nonce,
'cryptapi_address' => '',
'cryptapi_total' => $cryptoTotal,
+ 'cryptapi_total_fiat' => $total,
'cryptapi_currency' => $selected,
+ 'cryptapi_history' => json_encode([]),
+ 'cryptapi_cancelled' => '0',
+ 'cryptapi_last_price_update' => time(),
+ 'cryptapi_min' => $minTx,
+ 'cryptapi_qr_code_value' => '',
+ 'cryptapi_qr_code' => '',
];
$paymentData = json_encode($paymentData);
@@ -197,6 +204,37 @@ public function hasBeenPaid($order)
}
}
+ public static function calcOrder($history, $meta)
+ {
+ $already_paid = 0;
+ $already_paid_fiat = 0;
+ $remaining = $meta['cryptapi_total'];
+ $remaining_pending = $meta['cryptapi_total'];
+ $remaining_fiat = $meta['cryptapi_total_fiat'];
+
+ if (!empty($history)) {
+ foreach ($history as $uuid => $item) {
+ if ((int)$item['pending'] === 0) {
+ $remaining = bcsub(CryptAPIHelper::sig_fig($remaining, 6), $item['value_paid'], 8);
+ }
+
+ $remaining_pending = bcsub(CryptAPIHelper::sig_fig($remaining_pending, 6), $item['value_paid'], 8);
+ $remaining_fiat = bcsub(CryptAPIHelper::sig_fig($remaining_fiat, 6), $item['value_paid_fiat'], 8);
+
+ $already_paid = bcadd(CryptAPIHelper::sig_fig($already_paid, 6), $item['value_paid'], 8);
+ $already_paid_fiat = bcadd(CryptAPIHelper::sig_fig($already_paid_fiat, 6), $item['value_paid_fiat'], 8);
+ }
+ }
+
+ return [
+ 'already_paid' => floatval($already_paid),
+ 'already_paid_fiat' => floatval($already_paid_fiat),
+ 'remaining' => floatval($remaining),
+ 'remaining_pending' => floatval($remaining_pending),
+ 'remaining_fiat' => floatval($remaining_fiat)
+ ];
+ }
+
public function generateNonce($len = 32)
{
$data = str_split('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789');
diff --git a/Model/Total/Fee.php b/Model/Total/Fee.php
new file mode 100644
index 0000000..c137cfd
--- /dev/null
+++ b/Model/Total/Fee.php
@@ -0,0 +1,116 @@
+checkoutSession = $checkoutSession;
+ $this->scopeConfig = $scopeConfig;
+ $this->totals = $orderTotals;
+ $this->logger = $logger;
+ }
+
+ public function collect(
+ Quote $quote,
+ ShippingAssignmentInterface $shippingAssignment,
+ Total $total
+ )
+ {
+ parent::collect($quote, $shippingAssignment, $total);
+
+ if (!count($shippingAssignment->getItems())) {
+ return $this;
+ }
+
+ $fee = $this->calculateFee($quote);
+
+ $total->setTotalAmount('fee', $fee);
+ $total->setBaseTotalAmount('fee', $fee);
+ $total->setFee($fee);
+ $total->setBaseFee($fee);
+ $total->setGrandTotal($total->getGrandTotal());
+ $total->setBaseGrandTotal($total->getBaseGrandTotal());
+
+ $quote->setFee($fee);
+
+ return $this;
+ }
+
+ protected function clearValues(Total $total)
+ {
+ $total->setTotalAmount('subtotal', 0);
+ $total->setBaseTotalAmount('subtotal', 0);
+ $total->setTotalAmount('tax', 0);
+ $total->setBaseTotalAmount('tax', 0);
+ $total->setTotalAmount('discount_tax_compensation', 0);
+ $total->setBaseTotalAmount('discount_tax_compensation', 0);
+ $total->setTotalAmount('shipping_discount_tax_compensation', 0);
+ $total->setBaseTotalAmount('shipping_discount_tax_compensation', 0);
+ $total->setSubtotalInclTax(0);
+ $total->setBaseSubtotalInclTax(0);
+ }
+
+ public function fetch(Quote $quote, Total $total)
+ {
+ return [
+ 'code' => 'fee',
+ 'title' => __('Service Fee'),
+ 'value' => $this->calculateFee($quote),
+ ];
+ }
+
+ private function calculateFee(Quote $quote)
+ {
+
+ try {
+ $paymentMethod = $quote->getPayment()->getMethodInstance()->getCode();
+
+ if ($paymentMethod === 'cryptapi') {
+ $conv = 0;
+ $totalPrice = 0;
+
+ $feePercentage = $this->scopeConfig->getValue('payment/cryptapi/fee_order_percentage', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
+ $estimateBlockchain = $this->scopeConfig->getValue('payment/cryptapi/add_blockchain_fee', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
+ $coin = $this->checkoutSession->getCurrency();
+
+ if ($feePercentage !== 'none') {
+ $totalPrice = $quote->getGrandTotal() * $feePercentage;
+ }
+
+ if (!empty($coin) && $estimateBlockchain) {
+ $conv = CryptAPIHelper::get_estimate($coin)->{$quote->getQuoteCurrencyCode()};
+ }
+
+ return $totalPrice + $conv;
+ }
+ } catch (\Exception $ex) {
+ return 0;
+ }
+
+ return 0;
+ }
+}
diff --git a/Model/ConfigProvider.php b/Model/Ui/CryptapiConfigProvider.php
similarity index 80%
rename from Model/ConfigProvider.php
rename to Model/Ui/CryptapiConfigProvider.php
index 2cf8c4a..d801f9f 100644
--- a/Model/ConfigProvider.php
+++ b/Model/Ui/CryptapiConfigProvider.php
@@ -1,20 +1,16 @@
$coin) {
- foreach ($selected as $uid => $data) {
- if ($ticker == $data['cryptocurrency'])
- $output[] = [
- 'value' => $data['cryptocurrency'],
- 'type' => $coin,
- ];
+ if (!empty($selected)) {
+ foreach (json_decode($available_cryptos) as $ticker => $coin) {
+ foreach ($selected as $uuid => $data) {
+ if ($ticker == $data['cryptocurrency'])
+ $output[] = [
+ 'value' => $data['cryptocurrency'],
+ 'type' => $coin,
+ ];
+ }
}
}
diff --git a/Observer/AfterSuccess.php b/Observer/AfterSuccess.php
new file mode 100644
index 0000000..064a1f8
--- /dev/null
+++ b/Observer/AfterSuccess.php
@@ -0,0 +1,59 @@
+helper = $helper;
+ $this->payment = $payment;
+ $this->url = $url;
+ $this->responseFactory = $responseFactory;
+ $this->logger = $logger;
+ $this->productMetadata = $productMetadata;
+ $this->redirect = $redirect;
+ }
+
+ public function execute(Observer $observer)
+ {
+ $version_check = 1;
+
+ if ($this->productMetadata->getVersion() >= 2.3 && $this->productMetadata->getVersion() < 2.4) {
+ $version_check = 0;
+ }
+
+ if (empty($version_check)) {
+ return false;
+ }
+
+ $order = $this->payment->getOrder();
+ $paymentMethod = $order->getPayment()->getMethodInstance()->getCode();
+
+ if ($paymentMethod === 'cryptapi') {
+ $metaData = json_decode($this->helper->getPaymentResponse($order->getQuoteId()), true);
+
+ $params = [
+ 'order_id' => $order->getId(),
+ 'nonce' => $metaData['cryptapi_nonce']
+ ];
+
+ $redirectOrder = $this->url->getUrl('cryptapi/index/payment', $params);
+ $this->responseFactory->create()->setRedirect($redirectOrder)->sendResponse();
+ return $this->redirect->setRedirect($redirectOrder);
+ }
+ }
+}
diff --git a/Observer/QuoteSubmitBefore.php b/Observer/QuoteSubmitBefore.php
new file mode 100644
index 0000000..6df7214
--- /dev/null
+++ b/Observer/QuoteSubmitBefore.php
@@ -0,0 +1,41 @@
+orderResourceModel = $orderResourceModel;
+ $this->orderRepository = $orderRepository;
+ $this->payment = $payment;
+ $this->objectCopyService = $objectCopyService;
+ $this->logger = $logger;
+ }
+
+ public function execute(Observer $observer)
+ {
+
+ $quote = $observer->getQuote();
+ $order = $observer->getOrder();
+ $paymentMethod = $order->getPayment()->getMethodInstance()->getCode();
+
+ if ($paymentMethod === 'cryptapi') {
+ $order =$observer->getOrder();
+ $order->setData('cryptapi_fee', (float)$quote->getData('fee'));
+ }
+
+ }
+}
diff --git a/README.md b/README.md
index 5fd3244..b24937f 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,8 @@ Accept cryptocurrency payments on your Magento store
### Requirements:
```
-Magento >= 2.3
+Magento >= 2.4
+Magento >= 2.3.5
```
### Description
@@ -18,19 +19,21 @@ All you need is to provide your crypto address.
The CryptAPI extension enables your Magento store to get receive payments in cryptocurrency, with a simple setup and no sign-ups required.
-Currently accepted cryptocurrencies are:
+#### Accepted cryptocurrencies & tokens include:
* (BTC) Bitcoin
+* (ETH) Ethereum
* (BCH) Bitcoin Cash
* (LTC) Litecoin
-* (ETH) Ethereum
* (XMR) Monero
-* (IOTA) IOTA
+* (TRX) Tron
+* (BNB) Binance Coin
+* (USDT) USDT
-CryptAPI will attempt to automatically convert the value you set on your store to the cryptocurrency your customer chose.
-Exchange rates are fetched hourly from CoinMarketCap.
+CryptAPI plugin will attempt to automatically convert the value you set on your store to the cryptocurrency your customer chose.
+Exchange rates are fetched every 5 minutes.
-Supported currencies for automatic exchange rates are:
+### Supported currencies for automatic exchange rates are:
* (USD) United States Dollar
* (EUR) Euro
@@ -58,12 +61,15 @@ For more info on our fees [click here](https://cryptapi.io/get_started/#fees)
### Installation
-1. Upload code to folder app/code/Cryptapi/Cryptapi
+1. Upload code to the folder app/code/Cryptapi/Cryptapi
2. Enter following commands to install module:
```bash
-php bin/magento setup:upgrade
-php bin/magento setup:static-content:deploy
+php bin/magento module:enable Cryptapi_Cryptapi
+php bin/magento setup:upgrade
+php bin/magento setup:di:compile
+php bin/magento setup:static-content:deploy -f
+php bin/magento cache:flush
php bin/magento cache:enable cryptapi_cryptocurrencies
```
@@ -118,5 +124,25 @@ The easiest and fastest way is via our live chat on our [website](https://crypta
* UI Improvements
* Minor Bug Fixes
+#### 3.0
+* New settings and color schemes to fit dark mode
+* New settings to add CryptAPI's services fees to the checkout
+* New settings to add blockchain fees to the checkout
+* Upgrade the settings
+* Added a history of transactions to the order payment page
+* Better handling of partial payments
+* Disable QR Code with value in certain currencies due to some wallets not supporting it
+* Minor fixes
+* UI Improvements
+
+#### 3.0.1
+* Minor fixes
+
+#### 3.0.2
+* Minor fixes
+
+#### 3.0.3
+* Minor fixes
+
### Upgrade Notice
* No breaking changes.
diff --git a/Setup/InstallSchema.php b/Setup/InstallSchema.php
deleted file mode 100644
index e317e8b..0000000
--- a/Setup/InstallSchema.php
+++ /dev/null
@@ -1,36 +0,0 @@
-startSetup();
-
- $table = $installer->getConnection()->newTable($installer->getTable('cryptapi'))
- ->addColumn(
- 'order_id',
- \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
- null,
- ['unsigned' => true],
- 'Order Id'
- )->addColumn(
- 'response',
- \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
- null,
- [],
- 'Response'
- )->setComment(
- 'Cryptapi Table'
- );
-
- $installer->getConnection()->createTable($table);
-
- $installer->endSetup();
- }
-}
diff --git a/composer.json b/composer.json
index 786a492..70177f0 100644
--- a/composer.json
+++ b/composer.json
@@ -2,11 +2,12 @@
"name": "cryptapi/cryptapi",
"description": "CryptAPI's Magento extension",
"type": "magento2-module",
- "version": "2.0.0",
+ "version": "3.0.3",
"require": {
"magento/module-payment": "100.1.*",
"magento/module-checkout": "100.1.*",
"magento/module-sales": "100.1.*",
+ "ext-bcmath": "*",
"ext-curl": "*",
"ext-json": "*"
},
diff --git a/etc/adminhtml/di.xml b/etc/adminhtml/di.xml
index 0fe12a6..3ea2313 100644
--- a/etc/adminhtml/di.xml
+++ b/etc/adminhtml/di.xml
@@ -2,6 +2,6 @@
+
+
+
+
+
+
= __('Waiting for payment') ?>
+= __('Waiting for network confirmation') ?>
+= __('Payment confirmed') ?>
+= __('Can\'t find this order'); ?>
+ +Waiting for payment
-Waiting for network confirmation
-Waiting for network confirmation
-