Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
94eab634ca | ||
|
|
225d4c33c5 | ||
|
|
b935000fda | ||
|
|
dec467e55b | ||
|
|
a6b435d7e2 | ||
|
|
706860e35f | ||
|
|
25b06ab911 | ||
|
|
7994834151 | ||
|
|
6042284704 | ||
|
|
848b1f5e30 | ||
|
|
d3f8e2a60c | ||
|
|
43920ce700 | ||
|
|
7cb3ee2400 | ||
|
|
8cb6afd918 | ||
|
|
86cf5af6fa | ||
|
|
0742b68e48 | ||
|
|
0aa893767d | ||
|
|
6a22f82a73 | ||
|
|
17cb4f7814 | ||
|
|
c469a3b4c1 | ||
|
|
cfbee77a5b |
@@ -0,0 +1,12 @@
|
|||||||
|
# BTCPay Server payment gateway for Odoo 16, 17, 18 and 19
|
||||||
|
|
||||||
|
## Accept bitcoin payments on Odoo 16, 17, 18 and 19
|
||||||
|
This odoo addon allows you to accept bitcoin and Lightning Network (and other cryptocurrency) payments in your Odoo e-commerce store.
|
||||||
|

|
||||||
|
|
||||||
|
## How to install
|
||||||
|
|
||||||
|
Please find the installation instructions here:
|
||||||
|
- [Odoo 18 + 19 documentation](https://github.com/btcpayserver/odoo/blob/19.0/payment_btcpayserver/README.md)
|
||||||
|
- [Odoo 17 documentation](https://github.com/btcpayserver/odoo/blob/17.0/payment_btcpayserver/README.md)
|
||||||
|
- [Odoo 16 documentation](https://github.com/btcpayserver/odoo/blob/16.0/payment_btcpayserver/README.md)
|
||||||
@@ -1,12 +1,20 @@
|
|||||||
# BTCPay Server payment gateway for Odoo 16
|
# BTCPay Server payment gateway for Odoo 18 / 19
|
||||||
|
|
||||||
## This is the module to connect Odoo 16 and BTCPay Server
|
## This is the module to connect Odoo 18 / 19 and BTCPay Server
|
||||||
This module allows you to accept bitcoin (and other cryptocurrency) payments in your Odoo e-commerce store.
|
This module allows you to accept bitcoin (and other cryptocurrency) payments in your Odoo e-commerce store.
|
||||||

|

|
||||||
|
|
||||||
|
:::tip
|
||||||
|
If you use Odoo 16 you can find the documentation [here](https://github.com/btcpayserver/odoo/blob/16.0/payment_btcpayserver/README.md) and for Odoo 17 [here](https://github.com/btcpayserver/odoo/blob/17.0/payment_btcpayserver/README.md).
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
The following instructions work for Odoo 18 and 19. You just need to make sure to download the matching branch release or use the matching branch (18.0 or 19.0) mentioned in the steps below.
|
||||||
|
:::
|
||||||
|
|
||||||
## Install the module
|
## Install the module
|
||||||
* Clone our [repository](https://github.com/btcpayserver/odoo) or download the .zip from the [releases page](https://github.com/btcpayserver/odoo/releases)
|
* Clone our [repository](https://github.com/btcpayserver/odoo) or download the .zip from the [releases page](https://github.com/btcpayserver/odoo/releases)
|
||||||
* Make sure you are on branch `16.0` or downloaded a release tagged with version v16.x
|
* Make sure you are on branch `19.0` (or `18.0`) or downloaded a [release](https://github.com/btcpayserver/odoo/releases) tagged with version v19.x (or v18.x)
|
||||||
* Place the `payment_btcpayserver` directory in your Odoo addons directory
|
* Place the `payment_btcpayserver` directory in your Odoo addons directory
|
||||||
* Install dependencies by running `pip install -r requirements.txt` (from inside the `payment_btcpayserver` directory)
|
* Install dependencies by running `pip install -r requirements.txt` (from inside the `payment_btcpayserver` directory)
|
||||||
* Restart Odoo
|
* Restart Odoo
|
||||||
@@ -21,28 +29,35 @@ This module allows you to accept bitcoin (and other cryptocurrency) payments in
|
|||||||
In the BTCPay settings form, tab "Credentials":
|
In the BTCPay settings form, tab "Credentials":
|
||||||
* Set field "State" to enabled
|
* Set field "State" to enabled
|
||||||
* Set field "BTCPay Server URL" as test or live URL including https://. Example URL: https://testnet.demo.btcpayserver.org
|
* Set field "BTCPay Server URL" as test or live URL including https://. Example URL: https://testnet.demo.btcpayserver.org
|
||||||
* Get a pairing code from your BTCPay Server store: Settings -> Access Tokens
|
* Get a pairing code from your BTCPay Server store:
|
||||||
|
* Go to: Settings -> Access Tokens
|
||||||
* Click on "Create Token" button
|
* Click on "Create Token" button
|
||||||
* Label: enter e.g. "My odoo store"
|
* Label: enter e.g. "My odoo store"
|
||||||
* Public Key: leave empty
|
* Public Key: leave empty
|
||||||
* Click on "Request Pairing" button, on next page click "Approve" button
|
* Click on "Request Pairing" button, on next page click "Approve" button
|
||||||
* At the top copy the code next to "Server initiated pairing code", e.g. "hg7z8wN"
|
* At the top copy the code next to "Server initiated pairing code", e.g. "hg7z8wN"
|
||||||
* Back in Odoo, paste the code into "Pairing Code" field
|
* Back in Odoo: paste the code into "Pairing Code" field
|
||||||
* Hit Tab key on your keyboard (or click on another field) and the pairing process will start automatically
|
* Hit Tab key on your keyboard (or click on another field) and the pairing process will start automatically
|
||||||
* When the pairing is successful the "Token" and "Private Key" field will be filled automatically
|
* When the pairing is successful the "Token" and "Private Key" field will be filled automatically (see screenshot below)
|
||||||
* Field Facade, keep default 'merchant'.
|
* Field Facade, keep default 'merchant'.
|
||||||
|
|
||||||
On the tab "Configuration":
|
On the tab "Configuration":
|
||||||
* Set field "Payment Journal" to "Bank", you can click the dropdown and click on the suggestion "Bank"
|
* Make sure field "Payment Journal" is set to "Bank", otherwise you can click the dropdown and click on the suggestion "Bank"
|
||||||
* Now you can **save** the settings
|
* Now you can **save** the settings
|
||||||
|
|
||||||

|
Check the payment method is enabled:
|
||||||
|
* Go to **Website** -> **Configuration** -> **Payment Methods**
|
||||||
|
* Make sure "Pay with Bitcoin / Lightning Network" is active
|
||||||
|
|
||||||
|
Congrats, all done. Do some testing to be sure all works.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## How does the payment page look?
|
## How does the payment page look?
|
||||||
|
|
||||||
During the checkout the customers will have the option to select the payment method "Pay with Bitcoin / Lightning Network". After selecting they will be redirected to the BTCPay checkout page as shown below.
|
During the checkout the customers will have the option to select the payment method "Pay with Bitcoin / Lightning Network". After selecting they will be redirected to the BTCPay checkout page as shown below.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
## Transaction BTCPay Details
|
## Transaction BTCPay Details
|
||||||
@@ -51,4 +66,8 @@ In transaction object, you will find more technical information about this metho
|
|||||||
* Invoice Id: the id of the invoice for which you want to fetch an event token
|
* Invoice Id: the id of the invoice for which you want to fetch an event token
|
||||||
* Transaction Status: That indicates state of transaction
|
* Transaction Status: That indicates state of transaction
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
### The order and transaction status does not get updated to "paid"
|
||||||
|
If the BTCPay connection generally works, like redirect to BTCPay checkout page (QR-code) then check your odoo logs and make sure PDF generation generally works. If there are errors mentioning wkhtmltopdf then you need to install `wkhtmltopdf` on your server.
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ from . import models
|
|||||||
from odoo.addons.payment import setup_provider, reset_payment_provider
|
from odoo.addons.payment import setup_provider, reset_payment_provider
|
||||||
|
|
||||||
|
|
||||||
def post_init_hook(cr, registry):
|
def post_init_hook(env):
|
||||||
setup_provider(cr, registry, 'btcpayserver')
|
setup_provider(env, 'btcpayserver')
|
||||||
|
|
||||||
|
|
||||||
def uninstall_hook(cr, registry):
|
def uninstall_hook(env):
|
||||||
reset_payment_provider(cr, registry, 'btcpayserver')
|
reset_payment_provider(env, 'btcpayserver')
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#******************************************************************************
|
#******************************************************************************
|
||||||
# PAYMENT BTCPAY SERVER FOR ODOO
|
# PAYMENT BTCPAY SERVER FOR ODOO
|
||||||
#
|
#
|
||||||
# Copyright (C) 2023 Susanna Fort <susannafm@gmail.com>, ndeet
|
# Copyright (C) 2024 Susanna Fort <susannafm@gmail.com>, ndeet
|
||||||
#
|
#
|
||||||
#******************************************************************************
|
#******************************************************************************
|
||||||
#
|
#
|
||||||
@@ -21,11 +21,11 @@
|
|||||||
|
|
||||||
{
|
{
|
||||||
'name': 'Payment Provider: BTCPay Server',
|
'name': 'Payment Provider: BTCPay Server',
|
||||||
'summary': 'This module integrates BTCPAY - pay with Bitcoin - with Odoo v16.0',
|
'summary': 'This module integrates BTCPAY - pay with Bitcoin - with Odoo v19.0',
|
||||||
'author': 'BTCPay Server team and contributors',
|
'author': 'BTCPay Server team and contributors',
|
||||||
'website': 'https://github.com/btcpayserver/odoo',
|
'website': 'https://github.com/btcpayserver/odoo',
|
||||||
'category': 'Accounting/Payment Providers',
|
'category': 'Accounting/Payment Providers',
|
||||||
'version': '16.0.2.0',
|
'version': '19.0.1.0',
|
||||||
'license': 'GPL-3',
|
'license': 'GPL-3',
|
||||||
'currency': 'USD',
|
'currency': 'USD',
|
||||||
'application': False,
|
'application': False,
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
'views/payment_transaction_views.xml',
|
'views/payment_transaction_views.xml',
|
||||||
'data/payment_provider_data.xml',
|
'data/payment_provider_data.xml',
|
||||||
],
|
],
|
||||||
'images': ['static/description/BTCPay-Odoo-16-featured.png'],
|
'images': ['static/description/BTCPay-Odoo-17-featured.png'],
|
||||||
'external_dependencies': {
|
'external_dependencies': {
|
||||||
'python': ['btcpay-python']
|
'python': ['btcpay-python']
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -19,24 +19,21 @@
|
|||||||
#
|
#
|
||||||
# ******************************************************************************
|
# ******************************************************************************
|
||||||
|
|
||||||
import logging
|
import json
|
||||||
import pprint
|
import pprint
|
||||||
|
|
||||||
import requests
|
|
||||||
import werkzeug
|
import werkzeug
|
||||||
from werkzeug import urls
|
from werkzeug import urls
|
||||||
from werkzeug.exceptions import Forbidden
|
|
||||||
|
|
||||||
from odoo import _, http, SUPERUSER_ID
|
from odoo import _, http
|
||||||
from odoo.exceptions import ValidationError
|
from odoo.exceptions import ValidationError
|
||||||
from odoo.http import request
|
from odoo.http import request
|
||||||
from odoo.tools import html_escape
|
|
||||||
|
|
||||||
import json
|
from odoo.addons.payment.logging import get_payment_logger
|
||||||
from ..models.libs.client import BTCPayClient
|
from ..models.libs.client import BTCPayClient
|
||||||
|
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = get_payment_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class BTCPayController(http.Controller):
|
class BTCPayController(http.Controller):
|
||||||
@@ -47,8 +44,19 @@ class BTCPayController(http.Controller):
|
|||||||
@http.route(_checkout_url, type='http', auth='public', csrf=False, website=True)
|
@http.route(_checkout_url, type='http', auth='public', csrf=False, website=True)
|
||||||
def checkout(self, **data):
|
def checkout(self, **data):
|
||||||
|
|
||||||
_logger.info("CHECKOUT: notification received from BTCPay with data:\n%s", pprint.pformat(data))
|
_logger.info("CHECKOUT: received data:\n%s", pprint.pformat(data))
|
||||||
tx_sudo = request.env['payment.transaction'].sudo()._get_tx_from_notification_data('btcpayserver', data)
|
|
||||||
|
# Look up the transaction by reference
|
||||||
|
reference = data.get('reference')
|
||||||
|
tx_sudo = request.env['payment.transaction'].sudo().search([
|
||||||
|
('reference', '=', reference),
|
||||||
|
('provider_code', '=', 'btcpayserver'),
|
||||||
|
], limit=1)
|
||||||
|
if not tx_sudo:
|
||||||
|
raise ValidationError(
|
||||||
|
_("BTCPay: No transaction found matching reference %s.", reference)
|
||||||
|
)
|
||||||
|
|
||||||
provider = tx_sudo.provider_id
|
provider = tx_sudo.provider_id
|
||||||
notification_url = str(data.get('notify_url')).replace("http://", "https://")
|
notification_url = str(data.get('notify_url')).replace("http://", "https://")
|
||||||
base_url = request.env['ir.config_parameter'].sudo().get_param('web.base.url')
|
base_url = request.env['ir.config_parameter'].sudo().get_param('web.base.url')
|
||||||
@@ -72,41 +80,47 @@ class BTCPayController(http.Controller):
|
|||||||
_logger.info('Invoice %s \n NOTIFY URL: %s', invoice, notification_url)
|
_logger.info('Invoice %s \n NOTIFY URL: %s', invoice, notification_url)
|
||||||
return werkzeug.utils.redirect(invoice['url'])
|
return werkzeug.utils.redirect(invoice['url'])
|
||||||
|
|
||||||
@http.route(_notify_url, type='json', auth='public', csrf=False)
|
@http.route(_notify_url, type='jsonrpc', auth='public', csrf=False)
|
||||||
def btcpay_ipn(self, **post):
|
def btcpay_ipn(self, **post):
|
||||||
""" BTCPay IPN. """
|
""" BTCPay IPN. """
|
||||||
_logger.info('BTCPAY IPN RECEIVED...')
|
_logger.info('BTCPAY IPN RECEIVED...')
|
||||||
data = json.loads(request.httprequest.data)
|
data = json.loads(request.httprequest.data)
|
||||||
_logger.info("%s", pprint.pformat(data))
|
_logger.info("%s", pprint.pformat(data))
|
||||||
try:
|
try:
|
||||||
notification_data = {"reference": data['data']['orderId'],
|
reference = data['data']['orderId']
|
||||||
"invoiceID": data['data']['id']}
|
invoice_id = data['data']['id']
|
||||||
# Check the origin and integrity of the notification
|
|
||||||
tx_sudo = request.env['payment.transaction'].sudo()._get_tx_from_notification_data('btcpayserver', notification_data)
|
# Look up the transaction by reference
|
||||||
|
tx_sudo = request.env['payment.transaction'].sudo().search([
|
||||||
|
('reference', '=', reference),
|
||||||
|
('provider_code', '=', 'btcpayserver'),
|
||||||
|
], limit=1)
|
||||||
|
if not tx_sudo:
|
||||||
|
_logger.warning("No transaction found matching reference %s.", reference)
|
||||||
|
return ''
|
||||||
|
|
||||||
provider = tx_sudo.provider_id
|
provider = tx_sudo.provider_id
|
||||||
client = BTCPayClient(host=provider.btcpay_location, pem=provider.btcpay_privateKey,
|
client = BTCPayClient(host=provider.btcpay_location, pem=provider.btcpay_privateKey,
|
||||||
tokens={provider.btcpay_facade: provider.btcpay_token})
|
tokens={provider.btcpay_facade: provider.btcpay_token})
|
||||||
|
|
||||||
fetched_invoice = client.get_invoice(notification_data['invoiceID'])
|
fetched_invoice = client.get_invoice(invoice_id)
|
||||||
_logger.info('fetched_invoice = %s', pprint.pformat(fetched_invoice))
|
_logger.info('fetched_invoice = %s', pprint.pformat(fetched_invoice))
|
||||||
|
|
||||||
notification_data = {"reference": fetched_invoice['orderId'],
|
payment_data = {
|
||||||
|
"reference": fetched_invoice['orderId'],
|
||||||
"status": fetched_invoice['status'],
|
"status": fetched_invoice['status'],
|
||||||
"invoiceID": fetched_invoice['id'],
|
"invoiceID": fetched_invoice['id'],
|
||||||
"txid": fetched_invoice['url']}
|
"txid": fetched_invoice['url'],
|
||||||
|
}
|
||||||
|
|
||||||
# Handle the notification data
|
# Use the new Odoo 19 _process() pipeline
|
||||||
tx_sudo._handle_notification_data('btcpayserver', notification_data)
|
tx_sudo._process('btcpayserver', payment_data)
|
||||||
except ValidationError: # Acknowledge the notification to avoid getting spammed
|
except ValidationError:
|
||||||
_logger.exception("Unable to handle the notification data; skipping to acknowledge")
|
_logger.exception("Unable to handle the notification data; skipping to acknowledge")
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
@http.route(_return_url, type='http', auth="public", methods=['GET'], crsf=False, save_session=False)
|
@http.route(_return_url, type='http', auth="public", methods=['GET'], csrf=False, save_session=False)
|
||||||
def btcpay_return_from_redirect(self, **data):
|
def btcpay_return_from_redirect(self, **data):
|
||||||
""" BTCPay return
|
""" BTCPay return """
|
||||||
|
|
||||||
We could process and check the invoice status here but there is no need to as the status get's updated via
|
|
||||||
IPN anyway, so just show the user the order confirmation / payment status page.
|
|
||||||
"""
|
|
||||||
_logger.info("BTCPay: user returned to shop after payment")
|
_logger.info("BTCPay: user returned to shop after payment")
|
||||||
return request.redirect('/payment/status')
|
return request.redirect('/payment/status')
|
||||||
@@ -1,13 +1,26 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<odoo noupdate="1">
|
<odoo noupdate="1">
|
||||||
|
|
||||||
|
<record id="payment_method_btcpayserver" model="payment.method">
|
||||||
|
<field name="name">Pay with Bitcoin / Lightning Network</field>
|
||||||
|
<field name="code">btcpayserver</field>
|
||||||
|
<field name="active">True</field>
|
||||||
|
<field name="image" type="base64" file="payment_btcpayserver/static/description/icon.png"/>
|
||||||
|
<field name="support_tokenization">False</field>
|
||||||
|
<field name="support_express_checkout">False</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
<record id="payment_provider_btcpayserver" model="payment.provider">
|
<record id="payment_provider_btcpayserver" model="payment.provider">
|
||||||
<field name="name">BTCPay payments</field>
|
<field name="name">BTCPay Server payments</field>
|
||||||
<field name="display_as">Pay with Bitcoin / Lightning Network</field>
|
|
||||||
<field name="code">btcpayserver</field>
|
<field name="code">btcpayserver</field>
|
||||||
<field name="image_128" type="base64" file="payment_btcpayserver/static/description/icon.png"/>
|
<field name="image_128" type="base64" file="payment_btcpayserver/static/description/icon.png"/>
|
||||||
<field name="module_id" ref="base.module_payment_btcpayserver"/>
|
|
||||||
<field name="redirect_form_view_id" ref="redirect_form"/>
|
<field name="redirect_form_view_id" ref="redirect_form"/>
|
||||||
|
<field name="module_id" ref="base.module_payment_btcpayserver"/>
|
||||||
|
<field name="payment_method_ids"
|
||||||
|
eval="[Command.set([
|
||||||
|
ref('payment_btcpayserver.payment_method_btcpayserver'),
|
||||||
|
])]"
|
||||||
|
/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
import logging
|
|
||||||
|
|
||||||
from odoo import _, api, fields, models
|
from odoo import _, api, fields, models
|
||||||
from .libs.client import BTCPayClient
|
from .libs.client import BTCPayClient
|
||||||
from .libs import crypto
|
from .libs import crypto
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
from odoo.addons.payment.logging import get_payment_logger
|
||||||
|
|
||||||
|
|
||||||
|
_logger = get_payment_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class PaymentProvider(models.Model):
|
class PaymentProvider(models.Model):
|
||||||
@@ -22,14 +23,13 @@ class PaymentProvider(models.Model):
|
|||||||
|
|
||||||
def create(self, values_list):
|
def create(self, values_list):
|
||||||
if self.code == 'btcpayserver':
|
if self.code == 'btcpayserver':
|
||||||
values_list['btcpay_privateKey'] = crypto.generate_privakey()
|
values_list['btcpay_privateKey'] = crypto.generate_privkey()
|
||||||
|
|
||||||
return super(PaymentProvider, self).create(values_list)
|
return super(PaymentProvider, self).create(values_list)
|
||||||
|
|
||||||
@api.onchange('btcpay_pairingCode')
|
@api.onchange('btcpay_pairingCode')
|
||||||
def _onchange_pairingCode(self):
|
def _onchange_pairingCode(self):
|
||||||
if not self.btcpay_token and self.code == 'btcpayserver' and not self.btcpay_pairingCode == '':
|
if not self.btcpay_token and self.code == 'btcpayserver' and not self.btcpay_pairingCode == '':
|
||||||
#_logger.info("ONCHANGE PAIRING CODE***SELF: %s %s %s", self.btcpay_location, self.btcpay_privateKey, self.btcpay_pairingCode)
|
|
||||||
self.btcpay_privateKey = crypto.generate_privkey()
|
self.btcpay_privateKey = crypto.generate_privkey()
|
||||||
client = BTCPayClient(host=self.btcpay_location, pem=self.btcpay_privateKey)
|
client = BTCPayClient(host=self.btcpay_location, pem=self.btcpay_privateKey)
|
||||||
token = client.pair_client(self.btcpay_pairingCode)
|
token = client.pair_client(self.btcpay_pairingCode)
|
||||||
@@ -39,13 +39,10 @@ class PaymentProvider(models.Model):
|
|||||||
def _onchange_token(self):
|
def _onchange_token(self):
|
||||||
if self.code == 'btcpayserver':
|
if self.code == 'btcpayserver':
|
||||||
self.btcpay_pairingCode = ''
|
self.btcpay_pairingCode = ''
|
||||||
#_logger.info("ONCHANGE TOKEN")
|
|
||||||
|
|
||||||
|
|
||||||
@api.onchange('btcpay_location')
|
@api.onchange('btcpay_location')
|
||||||
def _onchange_location(self):
|
def _onchange_location(self):
|
||||||
if self.code == 'btcpayserver':
|
if self.code == 'btcpayserver':
|
||||||
self.btcpay_token = ''
|
self.btcpay_token = ''
|
||||||
#_logger.info("ONCHANGE LOCATION ***SELF: %s %s %s", self.btcpay_location, self.btcpay_privateKey, self.btcpay_pairingCode)
|
|
||||||
self.btcpay_privateKey = ''
|
self.btcpay_privateKey = ''
|
||||||
self.btcpay_pairingCode = ''
|
self.btcpay_pairingCode = ''
|
||||||
@@ -1,13 +1,12 @@
|
|||||||
import logging
|
|
||||||
import pprint
|
import pprint
|
||||||
from werkzeug import urls
|
|
||||||
|
|
||||||
from odoo import _, api, fields, models
|
from odoo import _, api, fields, models
|
||||||
from odoo.exceptions import ValidationError
|
|
||||||
|
|
||||||
from odoo.addons.payment import utils as payment_utils
|
from odoo.addons.payment import utils as payment_utils
|
||||||
|
from odoo.addons.payment.logging import get_payment_logger
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
|
||||||
|
_logger = get_payment_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class PaymentTransaction(models.Model):
|
class PaymentTransaction(models.Model):
|
||||||
@@ -21,7 +20,7 @@ class PaymentTransaction(models.Model):
|
|||||||
notify_url = 'payment/btcpay/ipn'
|
notify_url = 'payment/btcpay/ipn'
|
||||||
|
|
||||||
def _get_specific_rendering_values(self, processing_values):
|
def _get_specific_rendering_values(self, processing_values):
|
||||||
""" Override of payment to return Specific rendering values.
|
""" Override of payment to return BTCPay-specific rendering values.
|
||||||
|
|
||||||
Note: self.ensure_one() from `_get_processing_values`
|
Note: self.ensure_one() from `_get_processing_values`
|
||||||
|
|
||||||
@@ -29,14 +28,12 @@ class PaymentTransaction(models.Model):
|
|||||||
:return: The dict of provider-specific processing values
|
:return: The dict of provider-specific processing values
|
||||||
:rtype: dict
|
:rtype: dict
|
||||||
"""
|
"""
|
||||||
|
|
||||||
res = super()._get_specific_rendering_values(processing_values)
|
res = super()._get_specific_rendering_values(processing_values)
|
||||||
|
|
||||||
if self.provider_code != 'btcpayserver':
|
if self.provider_code != 'btcpayserver':
|
||||||
return res
|
return res
|
||||||
|
|
||||||
base_url = self.provider_id.get_base_url()
|
base_url = self.provider_id.get_base_url()
|
||||||
_logger.info('Hola! API URL: %s', processing_values)
|
|
||||||
partner_first_name, partner_last_name = payment_utils.split_partner_name(self.partner_name)
|
partner_first_name, partner_last_name = payment_utils.split_partner_name(self.partner_name)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -57,77 +54,63 @@ class PaymentTransaction(models.Model):
|
|||||||
'notify_url': base_url + self.notify_url,
|
'notify_url': base_url + self.notify_url,
|
||||||
}
|
}
|
||||||
|
|
||||||
def _get_tx_from_notification_data(self, provider_code, notification_data):
|
@api.model
|
||||||
""" Override of payment to find the transaction based on BTCPay data.
|
def _extract_reference(self, provider_code, payment_data):
|
||||||
|
""" Override of payment to extract the transaction reference from BTCPay data.
|
||||||
:param str provider_code: The code of the provider that handled the transaction
|
|
||||||
:param dict notification_data: The notification data sent by the provider
|
|
||||||
:return: The transaction if found
|
|
||||||
:rtype: recordset of `payment.transaction`
|
|
||||||
:raise: ValidationError if the data match no transaction
|
|
||||||
"""
|
|
||||||
tx = super()._get_tx_from_notification_data(provider_code, notification_data)
|
|
||||||
_logger.info('GET TX FROM NOTIFICATION Notification_data %s', pprint.pformat(notification_data))
|
|
||||||
if provider_code != 'btcpayserver' or len(tx) == 1:
|
|
||||||
return tx
|
|
||||||
|
|
||||||
reference = notification_data.get('reference')
|
|
||||||
tx = self.search([('reference', '=', reference), ('provider_code', '=', 'btcpayserver')])
|
|
||||||
if not tx:
|
|
||||||
raise ValidationError(
|
|
||||||
"BTCPay: " + _("No transaction found matching reference %s.", reference)
|
|
||||||
)
|
|
||||||
return tx
|
|
||||||
|
|
||||||
def _handle_notification_data(self, provider_code, notification_data):
|
|
||||||
""" Match the transaction with the notification data, update its state and return it.
|
|
||||||
|
|
||||||
:param str provider_code: The code of the provider handling the transaction.
|
:param str provider_code: The code of the provider handling the transaction.
|
||||||
:param dict notification_data: The notification data sent by the provider.
|
:param dict payment_data: The payment data sent by the provider.
|
||||||
:return: The transaction.
|
:return: The transaction reference.
|
||||||
:rtype: recordset of `payment.transaction`
|
:rtype: str
|
||||||
"""
|
"""
|
||||||
tx = self._get_tx_from_notification_data(provider_code, notification_data)
|
if provider_code != 'btcpayserver':
|
||||||
tx._process_notification_data(notification_data)
|
return super()._extract_reference(provider_code, payment_data)
|
||||||
tx._execute_callback()
|
|
||||||
return tx
|
|
||||||
|
|
||||||
def _process_notification_data(self, notification_data):
|
return payment_data.get('reference')
|
||||||
|
|
||||||
|
def _extract_amount_data(self, payment_data):
|
||||||
|
""" Override of payment to skip amount validation for BTCPay.
|
||||||
|
|
||||||
|
BTCPay invoices handle amount validation on the BTCPay server side,
|
||||||
|
so we skip the Odoo-side validation.
|
||||||
|
|
||||||
|
:param dict payment_data: The payment data sent by the provider.
|
||||||
|
:return: None to skip validation.
|
||||||
|
:rtype: None
|
||||||
|
"""
|
||||||
|
if self.provider_code != 'btcpayserver':
|
||||||
|
return super()._extract_amount_data(payment_data)
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _apply_updates(self, payment_data):
|
||||||
""" Override of payment to process the transaction based on BTCPay data.
|
""" Override of payment to process the transaction based on BTCPay data.
|
||||||
|
|
||||||
Note: self.ensure_one()
|
Note: self.ensure_one() from `_process`
|
||||||
|
|
||||||
:param dict notification_data: The notification data sent by the provider
|
:param dict payment_data: The payment data sent by the provider.
|
||||||
:return: None
|
:return: None
|
||||||
:raise: ValidationError if inconsistent data were received
|
|
||||||
"""
|
"""
|
||||||
super()._process_notification_data(notification_data)
|
|
||||||
if self.provider_code != 'btcpayserver':
|
if self.provider_code != 'btcpayserver':
|
||||||
return
|
return super()._apply_updates(payment_data)
|
||||||
|
|
||||||
_logger.info("_process_notification_data %s", pprint.pformat(notification_data))
|
_logger.info("BTCPay _apply_updates: %s", pprint.pformat(payment_data))
|
||||||
txn_id = notification_data.get('reference')
|
|
||||||
if not all(txn_id):
|
|
||||||
raise ValidationError(
|
|
||||||
"BTCPay: " + _("Missing value for txn_id (%(txn_id)s)).", txn_id=txn_id))
|
|
||||||
|
|
||||||
self.provider_reference = txn_id
|
self.provider_reference = payment_data.get('reference')
|
||||||
self.btcpay_txid = notification_data.get('txid')
|
self.btcpay_txid = payment_data.get('txid')
|
||||||
self.btcpay_status = notification_data.get('status')
|
self.btcpay_status = payment_data.get('status')
|
||||||
|
|
||||||
if self.btcpay_status in ['paid', 'processing']:
|
if self.btcpay_status in ['paid', 'processing']:
|
||||||
self._set_pending(state_message=notification_data.get('pending_reason'))
|
self._set_pending(state_message=payment_data.get('pending_reason'))
|
||||||
elif self.btcpay_status in ['confirmed', 'complete']:
|
elif self.btcpay_status in ['confirmed', 'complete']:
|
||||||
self._set_done()
|
self._set_done()
|
||||||
confirmed_orders = self._check_amount_and_confirm_order()
|
|
||||||
confirmed_orders._send_order_confirmation_mail()
|
|
||||||
elif self.btcpay_status in ['new']:
|
elif self.btcpay_status in ['new']:
|
||||||
self.btcpay_invoiceId = notification_data.get('invoiceID')
|
self.btcpay_invoiceId = payment_data.get('invoiceID')
|
||||||
elif self.btcpay_status in ['cancel', 'cancelled']:
|
elif self.btcpay_status in ['cancel', 'cancelled']:
|
||||||
self._set_canceled()
|
self._set_canceled()
|
||||||
elif self.btcpay_status in ['invalid']:
|
elif self.btcpay_status in ['invalid']:
|
||||||
_logger.info(
|
_logger.info(
|
||||||
"received data with invalid payment status (%s) for transaction with reference %s",
|
"Received data with invalid payment status (%s) for transaction with reference %s",
|
||||||
self.btcpay_status, self.reference
|
self.btcpay_status, self.reference
|
||||||
)
|
)
|
||||||
self._set_error(
|
self._set_error(
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 155 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 154 KiB |
@@ -7,7 +7,7 @@
|
|||||||
<h3 class="oe_slogan">This module allows you to accept Bitcoin / Lightning Network (and other cryptocurrency) payments in your Odoo e-commerce store.</h3>
|
<h3 class="oe_slogan">This module allows you to accept Bitcoin / Lightning Network (and other cryptocurrency) payments in your Odoo e-commerce store.</h3>
|
||||||
<div class="oe_span12">
|
<div class="oe_span12">
|
||||||
<div class="oe_bg_img">
|
<div class="oe_bg_img">
|
||||||
<img src="BTCPay-Odoo-16-featured.png" class="oe_picture oe_screenshot">
|
<img src="BTCPay-Odoo-17-featured.png" class="oe_picture oe_screenshot">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -65,7 +65,7 @@
|
|||||||
<div class="oe_span12">
|
<div class="oe_span12">
|
||||||
<p class="oe_mt32">
|
<p class="oe_mt32">
|
||||||
<ul>
|
<ul>
|
||||||
<li>Odoo 16 running</li>
|
<li>Odoo 17 running</li>
|
||||||
<li>eCommerce module enabled</li>
|
<li>eCommerce module enabled</li>
|
||||||
<li>You have a BTCPay Server version 1.10.0 or later, either <a href="https://docs.btcpayserver.org/Deployment/">self-hosted</a> or <a href="https://docs.btcpayserver.org/Deployment/ThirdPartyHosting/">hosted by a third-party</a></li>
|
<li>You have a BTCPay Server version 1.10.0 or later, either <a href="https://docs.btcpayserver.org/Deployment/">self-hosted</a> or <a href="https://docs.btcpayserver.org/Deployment/ThirdPartyHosting/">hosted by a third-party</a></li>
|
||||||
<li><a href="https://docs.btcpayserver.org/RegisterAccount/" class="">You've a registered account on the instance</a></li>
|
<li><a href="https://docs.btcpayserver.org/RegisterAccount/" class="">You've a registered account on the instance</a></li>
|
||||||
@@ -84,7 +84,7 @@
|
|||||||
<p class="oe_mt32">
|
<p class="oe_mt32">
|
||||||
<ul>
|
<ul>
|
||||||
<li>Clone our [repository](https://github.com/btcpayserver/odoo) or download the .zip from the [releases page](https://github.com/btcpayserver/odoo/releases)
|
<li>Clone our [repository](https://github.com/btcpayserver/odoo) or download the .zip from the [releases page](https://github.com/btcpayserver/odoo/releases)
|
||||||
<li>Make sure you are on branch `16.0` or downloaded a release tagged with version v16.x
|
<li>Make sure you are on branch `17.0` or downloaded a release tagged with version v17.x
|
||||||
<li>Place the `payment_btcpayserver` directory in your Odoo addons directory
|
<li>Place the `payment_btcpayserver` directory in your Odoo addons directory
|
||||||
<li>Install dependencies by running `pip install -r requirements.txt` (from inside the `payment_btcpayserver` directory)
|
<li>Install dependencies by running `pip install -r requirements.txt` (from inside the `payment_btcpayserver` directory)
|
||||||
<li>Restart Odoo
|
<li>Restart Odoo
|
||||||
|
|||||||
@@ -7,11 +7,11 @@
|
|||||||
<field name="inherit_id" ref="payment.payment_provider_form"/>
|
<field name="inherit_id" ref="payment.payment_provider_form"/>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<group name="provider_credentials" position='inside'>
|
<group name="provider_credentials" position='inside'>
|
||||||
<group attrs="{'invisible': [('code', '!=', 'btcpayserver')]}">
|
<group invisible="code != 'btcpayserver'">
|
||||||
<field name="btcpay_location"/>
|
<field name="btcpay_location"/>
|
||||||
<field name="btcpay_pairingCode"/>
|
<field name="btcpay_pairingCode"/>
|
||||||
</group>
|
</group>
|
||||||
<group attrs="{'invisible': [('code', '!=', 'btcpayserver')]}">
|
<group invisible="code != 'btcpayserver'">
|
||||||
<field name="btcpay_token"/>
|
<field name="btcpay_token"/>
|
||||||
<field name="btcpay_privateKey"/>
|
<field name="btcpay_privateKey"/>
|
||||||
<field name="btcpay_facade"/>
|
<field name="btcpay_facade"/>
|
||||||
|
|||||||
Reference in New Issue
Block a user