Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9e87e5e124 | ||
|
|
8d27778ced | ||
|
|
7aa226468f | ||
|
|
f47aaccb43 | ||
|
|
9677c828a4 | ||
|
|
5d7a2d4d1b | ||
|
|
422296840d | ||
|
|
3d5c6ccfb2 | ||
|
|
9b81bc6e2a | ||
|
|
0aeba289b9 | ||
|
|
9633b63b1f | ||
|
|
552a5de37a | ||
|
|
bdeb8cc931 | ||
|
|
b77bcd8740 |
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@ -24,7 +24,7 @@ jobs:
|
||||
with:
|
||||
type: 'zip'
|
||||
filename: 'btcpay.ocmod.zip'
|
||||
exclusions: '*.git* *.github* composer.*'
|
||||
exclusions: '*.git* *.github* composer.* README.md'
|
||||
- name: Upload artifact to release page.
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
|
||||
19
README.md
Normal file
19
README.md
Normal file
@ -0,0 +1,19 @@
|
||||
# BTCPay for OpenCart extension
|
||||
|
||||
This free extension can be used with [OpenCart](https://www.opencart.com) version 3 or 4. You can also find this extension on the OpenCart [marketplace](https://www.opencart.com/index.php?route=marketplace/extension/info&extension_id=44269).
|
||||
|
||||
## Installation
|
||||
|
||||
You can find a detailed installation guide on how to setup the extension on our [OpenCart documentation](https://docs.btcpayserver.org/OpenCart/).
|
||||
|
||||
## Feedback
|
||||
|
||||
If you have issues or feature requests feel free to open an [issue](https://github.com/btcpayserver/opencart/issues) or join us on our [chat](https://chat.btcpayserver.org) or [telegram channel](https://t.me/btcpayserver).
|
||||
|
||||
Please let us always know your OpenCart, BTCPay extension, PHP versions. You can find them on the extension configuration page.
|
||||
|
||||
## Development
|
||||
|
||||
OpenCart 4 development happens on the `master` branch and OpenCart 3 is maintained on the `3.x` branch but is mostly in maintenance mode.
|
||||
|
||||
|
||||
280
admin/controller/payment/btcpay.php
Normal file
280
admin/controller/payment/btcpay.php
Normal file
@ -0,0 +1,280 @@
|
||||
<?php
|
||||
namespace Opencart\Admin\Controller\Extension\Btcpay\Payment;
|
||||
|
||||
use BTCPayServer\Client\Store;
|
||||
use BTCPayServer\Client\Webhook;
|
||||
|
||||
require_once DIR_EXTENSION . 'btcpay/system/library/btcpay/autoload.php';
|
||||
require_once DIR_EXTENSION . 'btcpay/system/library/btcpay/version.php';
|
||||
|
||||
class Btcpay extends \Opencart\System\Engine\Controller {
|
||||
private $error = [];
|
||||
|
||||
public function index(): void {
|
||||
$this->load->language('extension/btcpay/payment/btcpay');
|
||||
$this->document->setTitle($this->language->get('heading_title'));
|
||||
|
||||
$this->load->model('setting/setting');
|
||||
$this->load->model('localisation/order_status');
|
||||
$this->load->model('localisation/geo_zone');
|
||||
|
||||
$data['save'] = $this->url->link('extension/btcpay/payment/btcpay|save', 'user_token=' . $this->session->data['user_token']);
|
||||
$data['back'] = $this->url->link('marketplace/extension', 'user_token=' . $this->session->data['user_token'] . '&type=payment');
|
||||
$data['cancel'] = $this->url->link('marketplace/extension', 'user_token=' . $this->session->data['user_token'] . '&type=payment', true);
|
||||
$data['order_statuses'] = $this->model_localisation_order_status->getOrderStatuses();
|
||||
|
||||
$data['geo_zones'] = $this->model_localisation_geo_zone->getGeoZones();
|
||||
|
||||
if (isset($this->error['warning'])) {
|
||||
$data['error_warning'] = $this->error['warning'];
|
||||
} else {
|
||||
$data['error_warning'] = '';
|
||||
}
|
||||
|
||||
if (isset($this->session->data['success'])) {
|
||||
$data['success'] = $this->session->data['success'];
|
||||
unset($this->session->data['success']);
|
||||
} else {
|
||||
$data['success'] = '';
|
||||
}
|
||||
|
||||
$data['breadcrumbs'] = [];
|
||||
$data['breadcrumbs'][] = array(
|
||||
'text' => $this->language->get('text_home'),
|
||||
'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token'], true)
|
||||
);
|
||||
$data['breadcrumbs'][] = array(
|
||||
'text' => $this->language->get('text_extension'),
|
||||
'href' => $this->url->link('marketplace/extension', 'user_token=' . $this->session->data['user_token'] . '&type=payment', true)
|
||||
);
|
||||
$data['breadcrumbs'][] = array(
|
||||
'text' => $this->language->get('heading_title'),
|
||||
'href' => $this->url->link('extension/btcpay/payment/btcpay', 'user_token=' . $this->session->data['user_token'], true)
|
||||
);
|
||||
|
||||
$fields = [
|
||||
'payment_btcpay_status',
|
||||
'payment_btcpay_url',
|
||||
'payment_btcpay_api_auth_token',
|
||||
'payment_btcpay_btcpay_storeid',
|
||||
'payment_btcpay_webhook',
|
||||
'payment_btcpay_webhook_delete',
|
||||
'payment_btcpay_modal_mode',
|
||||
'payment_btcpay_new_status_id',
|
||||
'payment_btcpay_paid_status_id',
|
||||
'payment_btcpay_settled_status_id',
|
||||
'payment_btcpay_settled_paidover_status_id',
|
||||
'payment_btcpay_invalid_status_id',
|
||||
'payment_btcpay_expired_status_id',
|
||||
'payment_btcpay_expired_partialpayment_status_id',
|
||||
'payment_btcpay_expired_paidlate_status_id',
|
||||
'payment_btcpay_refunded_status_id',
|
||||
'payment_btcpay_total',
|
||||
'payment_btcpay_geo_zone_id',
|
||||
'payment_btcpay_debug_mode',
|
||||
];
|
||||
|
||||
// Process our fields to be sure they are displayed.
|
||||
foreach ($fields as $field) {
|
||||
if (isset($this->request->post[$field])) {
|
||||
$data[$field] = $this->request->post[$field];
|
||||
} else {
|
||||
$data[$field] = $this->config->get($field);
|
||||
}
|
||||
}
|
||||
|
||||
$data['payment_btcpay_sort_order'] = isset($this->request->post['payment_btcpay_sort_order']) ?
|
||||
$this->request->post['payment_btcpay_sort_order'] : $this->config->get('payment_btcpay_sort_order');
|
||||
|
||||
$data['header'] = $this->load->controller('common/header');
|
||||
$data['column_left'] = $this->load->controller('common/column_left');
|
||||
$data['footer'] = $this->load->controller('common/footer');
|
||||
|
||||
$this->response->setOutput($this->load->view('extension/btcpay/payment/btcpay', $data));
|
||||
}
|
||||
|
||||
protected function validate($messages): array {
|
||||
|
||||
$this->load->language('extension/btcpay/payment/btcpay');
|
||||
if (!$this->user->hasPermission('modify', 'extension/btcpay/payment/btcpay')) {
|
||||
$messages['error'] = $this->language->get('error_permission');
|
||||
}
|
||||
|
||||
if (!class_exists('BTCPayServer\Client\Health')) {
|
||||
$messages['error'] = $this->language->get('error_composer');
|
||||
}
|
||||
|
||||
if (!isset($messages['error'])) {
|
||||
$host = $this->request->post['payment_btcpay_url'];
|
||||
$apiKey = $this->request->post['payment_btcpay_api_auth_token'];
|
||||
$storeId = $this->request->post['payment_btcpay_btcpay_storeid'];
|
||||
|
||||
try {
|
||||
$client = new Store($host, $apiKey);
|
||||
$store = $client->getStore($storeId);
|
||||
if (empty($store->getId())) {
|
||||
$messages['error'] = $this->language->get('error_store_not_found');
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
$messages['error'] = $this->language->get('error_connect_to_btcpay');
|
||||
$this->log->write($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
public function save(): void {
|
||||
$this->load->language('extension/btcpay/payment/btcpay');
|
||||
$this->load->model('setting/setting');
|
||||
|
||||
$json = [];
|
||||
$redirect = false;
|
||||
|
||||
$json = $this->validate($json);
|
||||
|
||||
if (empty($json['error'])) {
|
||||
$host = $this->request->post['payment_btcpay_url'];
|
||||
$apiKey = $this->request->post['payment_btcpay_api_auth_token'];
|
||||
$storeId = $this->request->post['payment_btcpay_btcpay_storeid'];
|
||||
|
||||
// On saving we create a webhook if there is none yet.
|
||||
if ($this->webhookExists() === false) {
|
||||
if ($whData = $this->webhookSetup($host, $apiKey, $storeId)) {
|
||||
$this->request->post['payment_btcpay_webhook'] = $whData;
|
||||
$json['success'] = $this->language->get('notice_success_create_webhook');
|
||||
$redirect = true;
|
||||
} else {
|
||||
$json['error'] = $this->language->get('error_creating_webhook');
|
||||
}
|
||||
} else {
|
||||
// Check if the user wants to delete an existing webhook.
|
||||
if (isset($this->request->post['payment_btcpay_webhook_delete']) &&
|
||||
$this->request->post['payment_btcpay_webhook_delete'] === '1'
|
||||
) {
|
||||
// Try to delete the webhook on the provided host.
|
||||
$this->webhookDelete($host, $apiKey, $storeId);
|
||||
unset($this->request->post['payment_btcpay_webhook']);
|
||||
unset($this->request->post['payment_btcpay_webhook_delete']);
|
||||
$json['success'] = $this->language->get('notice_success_delete_webhook');
|
||||
$redirect = true;
|
||||
} else {
|
||||
// Need to convert existing webhook values back to array for storage.
|
||||
if (isset($this->request->post['payment_btcpay_webhook'])) {
|
||||
$whString = $this->request->post['payment_btcpay_webhook'];
|
||||
$whString = str_replace(['ID: ', 'SECRET: ', 'URL: '], '', $whString);
|
||||
$whArr = explode(' | ', $whString);
|
||||
if (count($whArr) === 3) {
|
||||
$whData = [
|
||||
'id' => $whArr[0],
|
||||
'secret' => $whArr[1],
|
||||
'url' => $whArr[2]
|
||||
];
|
||||
$this->request->post['payment_btcpay_webhook'] = $whData;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($json['error'])) {
|
||||
if (!empty($json['success'])) {
|
||||
$json['success'] = $this->language->get('notice_success') . ' ' . $json['success'];
|
||||
} else {
|
||||
$json['success'] = $this->language->get('notice_success');
|
||||
}
|
||||
$this->model_setting_setting->editSetting('payment_btcpay', $this->request->post);
|
||||
}
|
||||
|
||||
if ($redirect) {
|
||||
$this->session->data['success'] = $json['success'];
|
||||
unset($json['success']);
|
||||
$json['redirect'] = $this->url->link('extension/btcpay/payment/btcpay', 'user_token=' . $this->session->data['user_token'], true);
|
||||
}
|
||||
|
||||
$this->response->addHeader('Content-Type: application/json');
|
||||
$this->response->setOutput(json_encode($json));
|
||||
}
|
||||
|
||||
public function install(): void {
|
||||
$this->load->model('extension/btcpay/payment/btcpay');
|
||||
$this->model_extension_btcpay_payment_btcpay->install();
|
||||
}
|
||||
|
||||
public function uninstall(): void {
|
||||
$this->load->model('extension/btcpay/payment/btcpay');
|
||||
$this->model_extension_btcpay_payment_btcpay->uninstall();
|
||||
}
|
||||
|
||||
private function webhookExists(): bool {
|
||||
// Check if the config is any value set at all.
|
||||
$data = $this->config->get('payment_btcpay_webhook');
|
||||
if (empty($data) || !is_array($data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// todo: load webhook form BTCPay to check if the callback url domain is the same
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function webhookSetup($host, $apiKey, $storeId): ?array {
|
||||
$whEvents = [
|
||||
'InvoiceReceivedPayment',
|
||||
'InvoicePaymentSettled',
|
||||
'InvoiceProcessing',
|
||||
'InvoiceExpired',
|
||||
'InvoiceSettled',
|
||||
'InvoiceInvalid'
|
||||
];
|
||||
|
||||
try {
|
||||
$whClient = new Webhook( $host, $apiKey );
|
||||
$webhook = $whClient->createWebhook(
|
||||
$storeId,
|
||||
$this->webhookCallbackUrl(),
|
||||
$whEvents,
|
||||
null
|
||||
);
|
||||
|
||||
// Prepare data for settings storage.
|
||||
$whData = [
|
||||
'id' => $webhook->getData()['id'],
|
||||
'secret' => $webhook->getData()['secret'],
|
||||
'url' => $webhook->getData()['url']
|
||||
];
|
||||
|
||||
return $whData;
|
||||
} catch (\Throwable $e) {
|
||||
$this->log->write($e->getMessage());
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
private function webhookDelete($host, $apiKey, $storeId): void {
|
||||
$data = $this->config->get('payment_btcpay_webhook');
|
||||
|
||||
$client = new \BTCPayServer\Client\Webhook($host, $apiKey);
|
||||
try {
|
||||
$client->deleteWebhook($storeId, $data['id']);
|
||||
} catch (\Throwable $e) {
|
||||
$this->log->write('Error deleting webhook: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private function webhookCallbackUrl(): string {
|
||||
$url = $this->url->link('extension/btcpay/payment/btcpay|callback', '', true);
|
||||
|
||||
// As we are in admin controller context we need to strip out the admin
|
||||
// path to receive the correct frontend callback url.
|
||||
$adminPathParts = explode('/', DIR_APPLICATION);
|
||||
end($adminPathParts); // Last array item is empty.
|
||||
$adminPath = prev($adminPathParts);
|
||||
if (!empty($adminPath)) {
|
||||
$url = str_replace($adminPath . '/', '', $url);
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
}
|
||||
@ -1,12 +1,11 @@
|
||||
<?php
|
||||
|
||||
require_once DIR_SYSTEM . 'library/btcpay/version.php';
|
||||
require_once DIR_EXTENSION . '/btcpay/system/library/btcpay/version.php';
|
||||
|
||||
$_['heading_title'] = 'BTCPay Server';
|
||||
$_['text_edit'] = 'Edit BTCPay Settings';
|
||||
$_['text_version_info'] = 'Debug info: OpenCart ' . VERSION . ' with BTCPay Extension ' . BTCPAY_OPENCART_EXTENSION_VERSION . ' on PHP ' . phpversion();
|
||||
$_['text_support_info'] = 'For setup instructions follow our <a href="https://docs.btcpayserver.org/OpenCart" target="_blank" rel="noopener">setup guide</a>. If you run into any problems feel free to <a href="https://github.com/btcpayserver/opencart" target="_blank" rel="noopener">open an issue on Github</a> or come to our <a href="https://chat.btcpayserver.org/" target="_blank" rel="noopener">Mattermost chat</a>.';
|
||||
|
||||
$_['text_extension'] = 'Extensions';
|
||||
|
||||
$_['entry_status'] = 'Payment Method Enabled';
|
||||
@ -34,17 +33,20 @@ $_['entry_debug_mode'] = 'Debug mode';
|
||||
|
||||
$_['help_btcpay_url'] = 'The public URL of your BTCPay Server instance. e.g. https://demo.mainnet.btcpayserver.org. You need to have a BTCPay Server instance running, see "Requirements" for several options of deployment on our <a href="https://docs.btcpayserver.org/OpenCart" target="_blank" rel="noopener">setup guide</a>.';
|
||||
$_['help_webhook'] = 'The webhook will get created automatically after you entered BTCPay Server URL, API Key and Store ID. If you see this field filled with data (after you saved the form) all went well.';
|
||||
$_['help_modal_mode'] = 'If enabled the invoice will be shown in a modal/overlay (iFrame). Default behaviour is that the user will get redirected to BTCPay Server invoice page.';
|
||||
$_['help_webhook_delete'] = 'This is useful if you switch hosts or have problems with webhooks. When checked this will delete the webhook on OpenCart (and BTCPay Server if possible). Make sure to delete the webhook on BTCPay Server Store settings too if not done automatically. <strong>ATTENTION:</strong> You need to edit and <strong>save</strong> this settings page again so a new webhook gets created on BTCPay Server.';
|
||||
$_['help_modal_mode'] = 'If enabled the invoice will be shown in a modal/overlay (iFrame). Default behaviour is that the user will get redirected to BTCPay Server invoice page.';
|
||||
$_['help_total'] = 'The checkout total the order must reach before this payment method becomes active.';
|
||||
$_['help_debug_mode'] = 'If enabled debug output will be saved to the error logs found in System -> Maintenance -> Error logs. Should be disabled after debugging.';
|
||||
|
||||
$_['notice_success'] = 'BTCPay Server Payment details have been successfully updated.';
|
||||
$_['notice_success_webhook_renew'] = 'BTCPay Server Payment details have been successfully updated and successfully deleted webhook data.';
|
||||
$_['notice_success'] = 'BTCPay Server Payment details have been updated.';
|
||||
$_['notice_success_delete_webhook'] = 'Successfully deleted webhook. Please save again to create a new one, make sure that on BTCPay Server it does not exist twice.';
|
||||
$_['notice_success_create_webhook'] = 'Successfully created a webhook on the BTCPay instance.';
|
||||
|
||||
$_['error_permission'] = 'Warning: You do not have permission to modify BTCPay Server!';
|
||||
$_['error_composer'] = 'Unable to load btcpayserver-greenfield-php. Please download a compiled vendor folder or run composer.';
|
||||
$_['error_store_not_found'] = 'Successfully connected to BTCPay Server but no store with that ID found. Make sure you entered the correct store ID on that corresponding BTCPay Server URL.';
|
||||
$_['error_connect_to_btcpay'] = 'Error connecting to BTCPay Server instance. Make sure you provided the correct URL, API key.';
|
||||
$_['error_creating_webhook'] = 'Error creating webhook. Make sure you have a correct store and api key combination with the required permissions. Check OpenCart error logs.';
|
||||
|
||||
$_['text_btcpay'] = '<a href="https://btcpayserver.org/" target="_blank" rel="noopener"><img src="view/image/payment/btcpay.png" alt="BTCPay Server" title="BTCPay Server" style="border: 1px solid #EEEEEE;" /></a>';
|
||||
|
||||
$_['text_btcpay'] = '<a href="https://btcpayserver.org/" target="_blank" rel="noopener"><img src="/extension/btcpay/admin/view/image/payment/btcpay.png" alt="BTCPay Server" title="BTCPay Server" style="border: 1px solid #EEEEEE;" /></a>';
|
||||
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
class ModelExtensionPaymentBTCPay extends Model {
|
||||
public function install() {
|
||||
namespace Opencart\Admin\Model\Extension\Btcpay\Payment;
|
||||
class Btcpay extends \Opencart\System\Engine\Model {
|
||||
public function install(): void {
|
||||
$this->db->query("
|
||||
CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "btcpay_order` (
|
||||
`btcpay_order_id` INT(11) NOT NULL AUTO_INCREMENT,
|
||||
@ -30,7 +30,7 @@ class ModelExtensionPaymentBTCPay extends Model {
|
||||
$this->model_setting_setting->editSetting('payment_btcpay', $defaults);
|
||||
}
|
||||
|
||||
public function uninstall() {
|
||||
public function uninstall(): void {
|
||||
$this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "btcpay_order`;");
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
301
admin/view/template/payment/btcpay.twig
Normal file
301
admin/view/template/payment/btcpay.twig
Normal file
@ -0,0 +1,301 @@
|
||||
{{ header }}{{ column_left }}
|
||||
<div id="content">
|
||||
<div class="page-header">
|
||||
<div class="container-fluid">
|
||||
<div class="float-end">
|
||||
<button type="submit" form="form_payment" data-bs-toggle="tooltip" title="{{ button_save }}" class="btn btn-primary"><i class="fas fa-save"></i></button>
|
||||
<a href="{{ back }}" data-bs-toggle="tooltip" title="{{ button_back }}" class="btn btn-light"><i class="fas fa-reply"></i></a>
|
||||
</div>
|
||||
<h1>{{ heading_title }}</h1>
|
||||
<ul class="breadcrumb">
|
||||
{% for breadcrumb in breadcrumbs %}
|
||||
<li class="breadcrumb-item"><a href="{{ breadcrumb['href'] }}">{{ breadcrumb['text'] }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container-fluid">
|
||||
{% if error %}
|
||||
<div class="alert alert-danger alert-dismissible"><i class="fas fa-exclamation-circle"></i> {{ error_warning }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if success %}
|
||||
<div class="alert alert-success">
|
||||
{{ success }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="alert alert-info" style="overflow: hidden;">
|
||||
<div class="row">
|
||||
<div class="col-sm-12">{{ text_version_info }}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">{{ text_support_info }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header"><i class="fas fa-pencil-alt"></i> {{ text_edit }}</div>
|
||||
<div class="card-body">
|
||||
<form action="{{ save }}" method="post" id="form_payment" data-oc-toggle="ajax">
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 col-form-label" for="input-status">{{ entry_status }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select name="payment_btcpay_status" id="input-status" class="form-select">
|
||||
{% if payment_btcpay_status %}
|
||||
<option value="1" selected="selected">{{ text_enabled }}</option>
|
||||
<option value="0">{{ text_disabled }}</option>
|
||||
{% else %}
|
||||
<option value="1">{{ text_enabled }}</option>
|
||||
<option value="0" selected="selected">{{ text_disabled }}</option>
|
||||
{% endif %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 col-form-label" for="input-btcpay-url">{{ entry_btcpay_url }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" name="payment_btcpay_url" value="{{ payment_btcpay_url }}" placeholder="{{ entry_btcpay_url }}" id="input-btcpay-url" class="form-control" />
|
||||
<div class="help-block mt-1">
|
||||
{{ help_btcpay_url }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 col-form-label" for="input-api-auth-token">{{ entry_api_auth_token }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" name="payment_btcpay_api_auth_token" value="{{ payment_btcpay_api_auth_token }}" placeholder="{{ entry_api_auth_token }}" id="input-api-auth-token" class="form-control" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 col-form-label" for="input-btcpay-storeid">{{ entry_btcpay_storeid }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" name="payment_btcpay_btcpay_storeid" value="{{ payment_btcpay_btcpay_storeid }}" placeholder="{{ entry_btcpay_btcpay_storeid }}" id="input-btcpay-storeid" class="form-control" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 col-form-label" for="input-webhook">{{ entry_webhook }}</label>
|
||||
<div class="col-sm-10">
|
||||
{% if payment_btcpay_webhook.id %}
|
||||
{% set whData = 'ID: ' ~ payment_btcpay_webhook.id ~ ' | SECRET: ' ~ payment_btcpay_webhook.secret ~ ' | URL: ' ~ payment_btcpay_webhook.url %}
|
||||
{% else %}
|
||||
{% set whData = '-- webhook not configured yet --' %}
|
||||
{% endif %}
|
||||
<input readonly="readonly" type="text" name="payment_btcpay_webhook" value="{{ whData }}" placeholder="{{ entry_webhook }}" id="input-webhook" class="form-control" />
|
||||
<div class="help-block">
|
||||
{{ help_webhook }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<label class="col-sm-2 col-form-label" for="input-webhook-delete">{{ entry_webhook_delete }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="checkbox" name="payment_btcpay_webhook_delete" value="1" id="input-webhook-delete" class="form-check mt-2" {% if payment_btcpay_webhook_delete %} checked="checked" {% endif %} {% if not payment_btcpay_webhook.id %}disabled="disabled"{% endif %}/>
|
||||
<div class="help-block mt-1">
|
||||
{{ help_webhook_delete }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 col-form-label" for="input-modal-mode">{{ entry_modal_mode }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="checkbox" name="payment_btcpay_modal_mode" value="1" id="input-modal-mode" class="form-check mt-2" {% if payment_btcpay_modal_mode %} checked="checked" {% endif %} />
|
||||
<div class="help-block mt-1">
|
||||
{{ help_modal_mode }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 col-form-label" for="input-new-status">{{ entry_new_status }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select name="payment_btcpay_new_status_id" id="input-new-status" class="form-select">
|
||||
{% for order_status in order_statuses %}
|
||||
{% if order_status.order_status_id == payment_btcpay_new_status_id %}
|
||||
<option value="{{ order_status.order_status_id }}" selected="selected">{{ order_status.name }}</option>
|
||||
{% else %}
|
||||
<option value="{{ order_status.order_status_id }}">{{ order_status.name }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 col-form-label" for="input-paid-status">{{ entry_paid_status }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select name="payment_btcpay_paid_status_id" id="input-paid-status" class="form-select">
|
||||
{% for order_status in order_statuses %}
|
||||
{% if order_status.order_status_id == payment_btcpay_paid_status_id %}
|
||||
<option value="{{ order_status.order_status_id }}" selected="selected">{{ order_status.name }}</option>
|
||||
{% else %}
|
||||
<option value="{{ order_status.order_status_id }}">{{ order_status.name }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 col-form-label" for="input-settled-status">{{ entry_settled_status }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select name="payment_btcpay_settled_status_id" id="input-settled-status" class="form-select">
|
||||
{% for order_status in order_statuses %}
|
||||
{% if order_status.order_status_id == payment_btcpay_settled_status_id %}
|
||||
<option value="{{ order_status.order_status_id }}" selected="selected">{{ order_status.name }}</option>
|
||||
{% else %}
|
||||
<option value="{{ order_status.order_status_id }}">{{ order_status.name }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 col-form-label" for="input-settled-paidover-status">{{ entry_settled_paidover_status }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select name="payment_btcpay_settled_paidover_status_id" id="input-settled-paidover-status" class="form-select">
|
||||
{% for order_status in order_statuses %}
|
||||
{% if order_status.order_status_id == payment_btcpay_settled_paidover_status_id %}
|
||||
<option value="{{ order_status.order_status_id }}" selected="selected">{{ order_status.name }}</option>
|
||||
{% else %}
|
||||
<option value="{{ order_status.order_status_id }}">{{ order_status.name }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 col-form-label" for="input-invalid-status">{{ entry_invalid_status }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select name="payment_btcpay_invalid_status_id" id="input-invalid-status" class="form-select">
|
||||
{% for order_status in order_statuses %}
|
||||
{% if order_status.order_status_id == payment_btcpay_invalid_status_id %}
|
||||
<option value="{{ order_status.order_status_id }}" selected="selected">{{ order_status.name }}</option>
|
||||
{% else %}
|
||||
<option value="{{ order_status.order_status_id }}">{{ order_status.name }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 col-form-label" for="input-expired-status">{{ entry_expired_status }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select name="payment_btcpay_expired_status_id" id="input-expired-status" class="form-select">
|
||||
{% for order_status in order_statuses %}
|
||||
{% if order_status.order_status_id == payment_btcpay_expired_status_id %}
|
||||
<option value="{{ order_status.order_status_id }}" selected="selected">{{ order_status.name }}</option>
|
||||
{% else %}
|
||||
<option value="{{ order_status.order_status_id }}">{{ order_status.name }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 col-form-label" for="input-expired-partialpayment-status">{{ entry_expired_partialpayment_status }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select name="payment_btcpay_expired_partialpayment_status_id" id="input-expired-partialpayment-status" class="form-select">
|
||||
{% for order_status in order_statuses %}
|
||||
{% if order_status.order_status_id == payment_btcpay_expired_partialpayment_status_id %}
|
||||
<option value="{{ order_status.order_status_id }}" selected="selected">{{ order_status.name }}</option>
|
||||
{% else %}
|
||||
<option value="{{ order_status.order_status_id }}">{{ order_status.name }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 col-form-label" for="input-expired-paidlate-status">{{ entry_expired_paidlate_status }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select name="payment_btcpay_expired_paidlate_status_id" id="input-expired-paidlate-status" class="form-select">
|
||||
{% for order_status in order_statuses %}
|
||||
{% if order_status.order_status_id == payment_btcpay_expired_partialpayment_status_id %}
|
||||
<option value="{{ order_status.order_status_id }}" selected="selected">{{ order_status.name }}</option>
|
||||
{% else %}
|
||||
<option value="{{ order_status.order_status_id }}">{{ order_status.name }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 col-form-label" for="input-refunded-status">{{ entry_refunded_status }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select name="payment_btcpay_refunded_status_id" id="input-refunded-status" class="form-select">
|
||||
{% for order_status in order_statuses %}
|
||||
{% if order_status.order_status_id == payment_btcpay_refunded_status_id %}
|
||||
<option value="{{ order_status.order_status_id }}" selected="selected">{{ order_status.name }}</option>
|
||||
{% else %}
|
||||
<option value="{{ order_status.order_status_id }}">{{ order_status.name }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 col-form-label" for="input-total"><span data-toggle="tooltip" title="{{ help_total }}">{{ entry_total }}</span></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" name="payment_btcpay_total" value="{{ payment_btcpay_total }}" placeholder="{{ entry_total }}" id="input-total" class="form-control" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 col-form-label" for="input-geo-zone">{{ entry_geo_zone }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select name="payment_btcpay_geo_zone_id" id="input-geo-zone" class="form-select">
|
||||
<option value="0">{{ text_all_zones }}</option>
|
||||
{% for geo_zone in geo_zones %}
|
||||
{% if geo_zone.geo_zone_id == payment_btcpay_geo_zone_id %}
|
||||
<option value="{{ geo_zone.geo_zone_id }}" selected="selected">{{ geo_zone.name }}</option>
|
||||
{% else %}
|
||||
<option value="{{ geo_zone.geo_zone_id }}">{{ geo_zone.name }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 col-form-label" for="input-sort-order">{{ entry_sort_order }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" name="payment_btcpay_sort_order" value="{{ payment_btcpay_sort_order }}" placeholder="{{ entry_sort_order }}" id="input-sort-order" class="form-control" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 col-form-label" for="input-debug-mode">{{ entry_debug_mode }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="checkbox" name="payment_btcpay_debug_mode" value="1" id="input-debug-mode" class="form-check" {% if payment_btcpay_debug_mode %} checked="checked" {% endif %} />
|
||||
<div class="help-block mt-1">
|
||||
{{ help_debug_mode }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ footer }}
|
||||
@ -1,29 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Opencart\Catalog\Controller\Extension\Btcpay\Payment;
|
||||
use BTCPayServer\Client\Invoice;
|
||||
use BTCPayServer\Client\InvoiceCheckoutOptions;
|
||||
use BTCPayServer\Client\Webhook;
|
||||
use BTCPayServer\Util\PreciseNumber;
|
||||
|
||||
require DIR_SYSTEM . 'library/btcpay/autoload.php';
|
||||
require DIR_SYSTEM . 'library/btcpay/version.php';
|
||||
require_once DIR_EXTENSION . 'btcpay/system/library/btcpay/autoload.php';
|
||||
require_once DIR_EXTENSION . 'btcpay/system/library/btcpay/version.php';
|
||||
|
||||
class ControllerExtensionPaymentBTCPay extends Controller
|
||||
class Btcpay extends \Opencart\System\Engine\Controller
|
||||
{
|
||||
|
||||
public function index()
|
||||
public function index(): string
|
||||
{
|
||||
$this->load->language('extension/payment/btcpay');
|
||||
$this->load->language('extension/btcpay/payment/btcpay');
|
||||
$this->load->model('checkout/order');
|
||||
|
||||
$useModal = $this->config->get('payment_btcpay_modal_mode');
|
||||
|
||||
$data['button_confirm'] = $this->language->get('button_confirm');
|
||||
$data['action'] = $this->url->link(
|
||||
'extension/payment/btcpay/checkout',
|
||||
'extension/btcpay/payment/btcpay|checkout',
|
||||
'',
|
||||
true
|
||||
);
|
||||
|
||||
if (isset($this->session->data['error_warning'])) {
|
||||
$data['error_warning'] = $this->session->data['error_warning'];
|
||||
unset($this->session->data['error_warning']);
|
||||
} else {
|
||||
$data['error_warning'] = '';
|
||||
}
|
||||
|
||||
if ($useModal) {
|
||||
$host = $this->config->get('payment_btcpay_url');
|
||||
$data['btcpay_host'] = $host;
|
||||
@ -31,17 +39,18 @@ class ControllerExtensionPaymentBTCPay extends Controller
|
||||
$data['success_link'] = $this->url->link('checkout/success', '', true);
|
||||
$data['invoice_expired_text'] = $this->language->get('invoice_expired_text');
|
||||
|
||||
return $this->load->view('extension/payment/btcpay_modal', $data);
|
||||
return $this->load->view('extension/btcpay/payment/btcpay_modal', $data);
|
||||
} else {
|
||||
// Redirect.
|
||||
return $this->load->view('extension/payment/btcpay', $data);
|
||||
return $this->load->view('extension/btcpay/payment/btcpay', $data);
|
||||
}
|
||||
}
|
||||
|
||||
public function checkout()
|
||||
public function checkout(): void
|
||||
{
|
||||
$this->load->model('checkout/order');
|
||||
$this->load->model('extension/payment/btcpay');
|
||||
$this->load->model('extension/btcpay/payment/btcpay');
|
||||
$this->load->language('extension/btcpay/payment/btcpay');
|
||||
|
||||
$debug = $this->config->get('payment_btcpay_debug_mode');
|
||||
$useModal = $this->config->get('payment_btcpay_modal_mode');
|
||||
@ -54,13 +63,23 @@ class ControllerExtensionPaymentBTCPay extends Controller
|
||||
|
||||
if (!isset($this->session->data['order_id'])) {
|
||||
$this->log->write('No session data order_id present, aborting.');
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
$order_info = $this->model_checkout_order->getOrder(
|
||||
$this->session->data['order_id']
|
||||
);
|
||||
|
||||
if (empty($order_info)) {
|
||||
if ($debug) {
|
||||
$this->log->write('Could not load order passed by session, order id: ' . $this->session->data['order_id']);
|
||||
}
|
||||
$this->session->data['error_warning'] = $this->language->get('session_checkout_order_error');
|
||||
$this->response->redirect(
|
||||
$this->url->link('checkout/checkout', '', true)
|
||||
);
|
||||
}
|
||||
|
||||
$invoiceId = '';
|
||||
$checkoutLink = '';
|
||||
|
||||
@ -68,7 +87,6 @@ class ControllerExtensionPaymentBTCPay extends Controller
|
||||
if ($existingInvoice = $this->orderHasExistingInvoice($order_info)) {
|
||||
$invoiceId = $existingInvoice->getId();
|
||||
$checkoutLink = $existingInvoice->getCheckoutLink();
|
||||
|
||||
if ($debug) {
|
||||
$this->log->write('Found existing and not yet expired invoice: ' . $invoiceId);
|
||||
}
|
||||
@ -80,11 +98,30 @@ class ControllerExtensionPaymentBTCPay extends Controller
|
||||
$checkoutLink = $newInvoice->getCheckoutLink();
|
||||
|
||||
// Add invoiceId to the btcpay order table.
|
||||
$this->model_extension_payment_btcpay->addOrder([
|
||||
'order_id' => $order_info['order_id'],
|
||||
'token' => $token,
|
||||
'invoice_id' => $invoiceId,
|
||||
]);
|
||||
$this->model_extension_btcpay_payment_btcpay->addOrder([
|
||||
'order_id' => $order_info['order_id'],
|
||||
'token' => $token,
|
||||
'invoice_id' => $invoiceId,
|
||||
]);
|
||||
|
||||
$this->model_checkout_order->addHistory(
|
||||
$order_info['order_id'],
|
||||
$this->config->get('payment_btcpay_new_status_id'),
|
||||
'BTCPay invoice id: ' . $newInvoice->getId()
|
||||
);
|
||||
|
||||
/* TODO: wip have BTCPay Server invoice link in customer comments, needs option.
|
||||
// Add user facing comment with a link to BTCPay Server invoice:
|
||||
$this->model_checkout_order->addHistory(
|
||||
$order_info['order_id'],
|
||||
$this->config->get('payment_btcpay_new_status_id'),
|
||||
$this->language->get(
|
||||
'order_payment_link'
|
||||
) . '<a href="' . $newInvoice->getCheckoutLink() . '" target="_blank">' . $newInvoice->getCheckoutLink() . '</a>',
|
||||
true
|
||||
);
|
||||
*/
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,25 +146,27 @@ class ControllerExtensionPaymentBTCPay extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
public function cancel()
|
||||
public function cancel(): void
|
||||
{
|
||||
$this->response->redirect($this->url->link('checkout/cart', ''));
|
||||
}
|
||||
|
||||
public function success()
|
||||
public function success(): void
|
||||
{
|
||||
$this->load->model('checkout/order');
|
||||
$this->load->model('extension/payment/btcpay');
|
||||
$this->load->model('extension/btcpay/payment/btcpay');
|
||||
|
||||
$debug = $this->config->get('payment_btcpay_debug_mode');
|
||||
|
||||
if ($debug) {
|
||||
$this->log->write('Entering success callback / redirect page.');
|
||||
$this->log->write('SESSION data: ');
|
||||
$this->log->write(print_r($this->session->data, true));
|
||||
}
|
||||
|
||||
if ($order_id = $this->session->data['order_id']) {
|
||||
$order = $this->model_extension_payment_btcpay->getOrder(
|
||||
$order_id
|
||||
if (isset($this->session->data['order_id'])) {
|
||||
$order = $this->model_extension_btcpay_payment_btcpay->getOrder(
|
||||
$this->session->data['order_id']
|
||||
);
|
||||
|
||||
// Check if token is present and valid.
|
||||
@ -136,7 +175,7 @@ class ControllerExtensionPaymentBTCPay extends Controller
|
||||
$this->request->get['token']
|
||||
) !== 0) {
|
||||
if ($debug) {
|
||||
$this->log->write('Redirect to home page, request had no valid token.');
|
||||
$this->log->write('Redirect to home page, had no valid token.');
|
||||
}
|
||||
$this->response->redirect(
|
||||
$this->url->link('common/home', '', true)
|
||||
@ -160,7 +199,9 @@ class ControllerExtensionPaymentBTCPay extends Controller
|
||||
public function callback()
|
||||
{
|
||||
$this->load->model('checkout/order');
|
||||
$this->load->model('extension/payment/btcpay');
|
||||
$this->load->model('extension/btcpay/payment/btcpay');
|
||||
|
||||
$json = [];
|
||||
|
||||
$debug = $this->config->get('payment_btcpay_debug_mode');
|
||||
|
||||
@ -189,10 +230,16 @@ class ControllerExtensionPaymentBTCPay extends Controller
|
||||
die($whMessage);
|
||||
}
|
||||
|
||||
$btcpay_order = $this->model_extension_payment_btcpay->getOrderByInvoiceId(
|
||||
$btcpay_order = $this->model_extension_btcpay_payment_btcpay->getOrderByInvoiceId(
|
||||
$data->invoiceId
|
||||
);
|
||||
|
||||
if (empty($btcpay_order)) {
|
||||
$this->log->write('Order not found. Aborting.');
|
||||
http_response_code(200);
|
||||
die();
|
||||
}
|
||||
|
||||
$order_info = $this->model_checkout_order->getOrder(
|
||||
$btcpay_order['order_id']
|
||||
);
|
||||
@ -201,7 +248,7 @@ class ControllerExtensionPaymentBTCPay extends Controller
|
||||
$this->log->write('Order:');
|
||||
$this->log->write($btcpay_order);
|
||||
$this->log->write('Webhook payload: ');
|
||||
$this->log->write($data);
|
||||
$this->log->write(print_r($data, true));
|
||||
}
|
||||
|
||||
if (!empty($order_info) && !empty($btcpay_order)) {
|
||||
@ -223,7 +270,7 @@ class ControllerExtensionPaymentBTCPay extends Controller
|
||||
|
||||
if ($debug) {
|
||||
$this->log->write('Invoice data: ');
|
||||
$this->log->write($invoice);
|
||||
$this->log->write(print_r($invoice, true));
|
||||
}
|
||||
|
||||
$invStatus = $invoice->getStatus();
|
||||
@ -231,7 +278,7 @@ class ControllerExtensionPaymentBTCPay extends Controller
|
||||
|
||||
if ($invoice) {
|
||||
$order_status = NULL;
|
||||
$order_message = 'Event: ' . $data->type;
|
||||
$order_message = 'Event: ' . $data->type . ': ';
|
||||
$notify = false;
|
||||
switch ($data->type) {
|
||||
case "InvoiceReceivedPayment":
|
||||
@ -287,7 +334,7 @@ class ControllerExtensionPaymentBTCPay extends Controller
|
||||
}
|
||||
|
||||
if (!is_null($order_status)) {
|
||||
$this->model_checkout_order->addOrderHistory(
|
||||
$this->model_checkout_order->addHistory(
|
||||
$btcpay_order['order_id'],
|
||||
$this->config->get($order_status),
|
||||
'Payment status update: ' . $order_message,
|
||||
@ -305,6 +352,7 @@ class ControllerExtensionPaymentBTCPay extends Controller
|
||||
}
|
||||
|
||||
$this->response->addHeader('HTTP/1.1 200 OK');
|
||||
$this->response->setOutput(json_encode($json));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -322,14 +370,14 @@ class ControllerExtensionPaymentBTCPay extends Controller
|
||||
$apiKey = $this->config->get('payment_btcpay_api_auth_token');
|
||||
$apiHost = $this->config->get('payment_btcpay_url');
|
||||
$apiStoreId = $this->config->get('payment_btcpay_btcpay_storeid');
|
||||
$client = new Invoice($apiHost, $apiKey);
|
||||
|
||||
$debug = $this->config->get('payment_btcpay_debug_mode');
|
||||
|
||||
$client = new Invoice($apiHost, $apiKey);
|
||||
|
||||
// Checkout options.
|
||||
$checkoutOptions = new InvoiceCheckoutOptions();
|
||||
$redirectUrl = $this->url->link(
|
||||
'extension/payment/btcpay/success',
|
||||
'extension/btcpay/payment/btcpay|success',
|
||||
['token' => $token],
|
||||
true
|
||||
);
|
||||
@ -381,7 +429,7 @@ class ControllerExtensionPaymentBTCPay extends Controller
|
||||
// Round to 2 decimals to avoid mismatch.
|
||||
$totalRounded = round((float) $total->__toString(), 2);
|
||||
|
||||
$btcpay_order = $this->model_extension_payment_btcpay->getOrder(
|
||||
$btcpay_order = $this->model_extension_btcpay_payment_btcpay->getOrder(
|
||||
$order_info['order_id']
|
||||
);
|
||||
|
||||
@ -416,4 +464,5 @@ class ControllerExtensionPaymentBTCPay extends Controller
|
||||
);
|
||||
return PreciseNumber::parseString($total);
|
||||
}
|
||||
|
||||
}
|
||||
@ -5,3 +5,5 @@ $_['button_confirm'] = 'Pay with Bitcoin';
|
||||
$_['invoice_expired_text'] = 'The invoice expired. Please try again or choose a different payment method.';
|
||||
$_['invoice_closed_text'] = 'Payment aborted. Please try again or choose a different payment method.';
|
||||
$_['invoice_failed_text'] = 'Payment aborted. Error processing the request. Please contact store owner if the problem persists.';
|
||||
$_['order_payment_link'] = 'You can check your payment status here: ';
|
||||
$_['session_checkout_order_error'] = 'Your cart order id could not be found, please try to log out and in again.';
|
||||
80
catalog/model/payment/btcpay.php
Normal file
80
catalog/model/payment/btcpay.php
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace Opencart\Catalog\Model\Extension\Btcpay\Payment;
|
||||
|
||||
class Btcpay extends \Opencart\System\Engine\Model
|
||||
{
|
||||
|
||||
public function addOrder(array $data): bool
|
||||
{
|
||||
return $this->db->query(
|
||||
"INSERT INTO `" . DB_PREFIX . "btcpay_order` SET `order_id` = '" . (int)$data['order_id'] . "', `token` = '" . $this->db->escape(
|
||||
$data['token']
|
||||
) . "', `invoice_id` = '" . $this->db->escape(
|
||||
$data['invoice_id']
|
||||
) . "'"
|
||||
);
|
||||
}
|
||||
|
||||
public function getOrder(int $order_id): array
|
||||
{
|
||||
$query = $this->db->query(
|
||||
"SELECT * FROM `" . DB_PREFIX . "btcpay_order` WHERE `order_id` = '" . $order_id . "' ORDER BY btcpay_order_id DESC LIMIT 1"
|
||||
);
|
||||
|
||||
return $query->row;
|
||||
}
|
||||
|
||||
public function getOrderByInvoiceId(string $invoice_id): array
|
||||
{
|
||||
$query = $this->db->query(
|
||||
"SELECT * FROM `" . DB_PREFIX . "btcpay_order` WHERE `invoice_id` = '" . $invoice_id . "' LIMIT 1"
|
||||
);
|
||||
|
||||
return $query->row;
|
||||
}
|
||||
|
||||
public function getMethods(array $address = []): array
|
||||
{
|
||||
$this->load->language('extension/btcpay/payment/btcpay');
|
||||
|
||||
$qStr = "SELECT * FROM `" . DB_PREFIX . "zone_to_geo_zone` WHERE `geo_zone_id` = '" . (int)$this->config->get(
|
||||
'payment_btcpay_geo_zone_id'
|
||||
) . "'";
|
||||
|
||||
if (isset($address['country_id'])) {
|
||||
$qStr .= " AND `country_id` = '" . (int)$address['country_id'] ."'";
|
||||
}
|
||||
if (isset($address['zone_id'])) {
|
||||
$qStr .= " AND (`zone_id` = '" . (int)$address['zone_id'] . "' OR `zone_id` = '0')";
|
||||
}
|
||||
|
||||
$query = $this->db->query($qStr);
|
||||
|
||||
if (!$this->config->get('payment_btcpay_geo_zone_id')) {
|
||||
$status = true;
|
||||
} elseif ($query->num_rows) {
|
||||
$status = true;
|
||||
} else {
|
||||
$status = false;
|
||||
}
|
||||
|
||||
$method_data = [];
|
||||
|
||||
if ($status) {
|
||||
$option_data['btcpay'] = [
|
||||
'code' => 'btcpay.btcpay',
|
||||
'name' => $this->language->get('text_title')
|
||||
];
|
||||
|
||||
$method_data = [
|
||||
'code' => 'btcpay',
|
||||
'name' => $this->language->get('text_title'),
|
||||
'option' => $option_data,
|
||||
'sort_order' => $this->config->get('payment_btcpay_sort_order')
|
||||
];
|
||||
}
|
||||
|
||||
return $method_data;
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,9 @@
|
||||
{% if error_warning %}
|
||||
<div class="alert alert-danger">{{ error_warning }}</div>
|
||||
{% endif %}
|
||||
<form action="{{ action }}" method="post">
|
||||
<div class="buttons">
|
||||
<div class="pull-right">
|
||||
<div class="text-end">
|
||||
<input type="submit" value="{{ button_confirm }}" class="btn btn-primary" />
|
||||
</div>
|
||||
</div>
|
||||
@ -1,7 +1,7 @@
|
||||
<script src="{{ modal_url }}"></script>
|
||||
|
||||
<div class="buttons">
|
||||
<div class="pull-right">
|
||||
<div class="text-end">
|
||||
<button class="btn btn-primary btcpay-modal">{{ button_confirm }}</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -13,10 +13,10 @@
|
||||
if (data.invoiceId !== undefined) {
|
||||
window.btcpay.setApiUrlPrefix('{{ btcpay_host }}');
|
||||
window.btcpay.showInvoice(data.invoiceId);
|
||||
} else {
|
||||
showError('{{ invoice_failed_text }}');
|
||||
}
|
||||
|
||||
let invoice_paid = false;
|
||||
|
||||
window.btcpay.onModalReceiveMessage(function (event) {
|
||||
if (isObject(event.data)) {
|
||||
console.log('invoiceId: ' + event.data.invoiceId);
|
||||
@ -43,19 +43,15 @@
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const isObject = obj => {
|
||||
return Object.prototype.toString.call(obj) === '[object Object]'
|
||||
}
|
||||
|
||||
}).fail(function() {
|
||||
showError('{{ invoice_failed_text }}');
|
||||
});
|
||||
|
||||
const showError = err => {
|
||||
const errFail = '<div class="alert alert-danger alert-dismissible">' + err + '<button type="button" class="close" data-dismiss="alert">×</button></div>';
|
||||
$(this).closest('.panel-body').first().prepend(errFail);
|
||||
const errFail = '<div class="alert alert-danger alert-dismissible"><i class="fa-solid fa-circle-exclamation"></i> ' + err + '<button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>';
|
||||
$('#alert').prepend(errFail);
|
||||
}
|
||||
|
||||
});
|
||||
</script>
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "btcpayserver/opencart",
|
||||
"description": "BTCPay Server plugin for OpenCart 3",
|
||||
"description": "BTCPay Server plugin for OpenCart 4",
|
||||
"type": "opencart-extension",
|
||||
"require": {
|
||||
"btcpayserver/btcpayserver-greenfield-php": "^1.3"
|
||||
@ -14,6 +14,6 @@
|
||||
],
|
||||
"minimum-stability": "stable",
|
||||
"config": {
|
||||
"vendor-dir": "upload/system/library/btcpay"
|
||||
"vendor-dir": "system/library/btcpay"
|
||||
}
|
||||
}
|
||||
|
||||
7
install.json
Normal file
7
install.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "BTCPay Server payment gateway",
|
||||
"version": "4.2.2",
|
||||
"license": "MIT",
|
||||
"author": "BTCPay Server",
|
||||
"link": "https://btcpayserver.org"
|
||||
}
|
||||
@ -19,24 +19,24 @@ abstract class AbstractResult implements \ArrayAccess
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
public function offsetExists($offset)
|
||||
public function offsetExists($offset): bool
|
||||
{
|
||||
$data = $this->getData();
|
||||
return array_key_exists($offset, $data);
|
||||
}
|
||||
|
||||
public function offsetGet($offset)
|
||||
public function offsetGet($offset): mixed
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data[$offset] ?? null;
|
||||
}
|
||||
|
||||
public function offsetSet($offset, $value)
|
||||
public function offsetSet($offset, $value): void
|
||||
{
|
||||
throw new \RuntimeException('You should not change the data in a result.');
|
||||
}
|
||||
|
||||
public function offsetUnset($offset)
|
||||
public function offsetUnset($offset): void
|
||||
{
|
||||
throw new \RuntimeException('You should not change the data in a result.');
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user