38 Commits
Author SHA1 Message Date
ndeet a6b435d7e2 Marketplace: make banner work, updating description. 2024-08-12 16:35:47 +02:00
ndeetandGitHub 706860e35f Rename the module for publish on odoo marketplace. (#12)
* Rename the module for publish on odoo marketplace.

* More renaming needed.
2024-08-12 15:33:59 +02:00
ndeet 25b06ab911 Preparing module for app store submission. 2024-08-12 13:30:34 +02:00
ndeet 7994834151 Bumping version. 2024-07-31 14:21:48 +02:00
ndeet 6042284704 Make sure email is passed, also if used in PoS context. 2024-07-31 14:19:23 +02:00
ndeet 848b1f5e30 Updating teaser image also on primary README 2024-07-17 16:55:25 +02:00
ndeet d3f8e2a60c Updating teaser image. 2024-07-17 16:51:55 +02:00
ndeet 43920ce700 Replace relative links with full github url. 2024-07-16 15:00:55 +02:00
ndeet 7cb3ee2400 Link to Odoo 16 documentation. 2024-07-16 14:50:30 +02:00
ndeet 8cb6afd918 Fix image for btcpayserver docs embedding. 2024-07-09 11:52:14 +02:00
ndeet 86cf5af6fa Adding general readme linking to both versions installation instructions. 2024-07-09 11:11:50 +02:00
ndeet 0742b68e48 Update docs to latest changes.
(cherry picked from commit 9e2475f415)
2024-07-09 10:26:33 +02:00
ndeetandGitHub 0aa893767d Merge pull request #10 from ndeet/redirect
Simplify setup by removing confirmationURL parameter
2024-07-08 16:38:46 +02:00
ndeet 6a22f82a73 Remove customizable return url and redirect the user to order confirmation / payment status page as it would be expected. 2024-07-08 16:37:32 +02:00
ndeet 17cb4f7814 Fix IPN processing to cover additional invoice states. 2024-07-08 11:12:29 +02:00
ndeet c469a3b4c1 Fix typo. 2024-07-08 09:18:47 +02:00
ndeetandGitHub cfbee77a5b Porting module to work with Odoo 17.0 (#9) 2024-07-08 09:10:22 +02:00
ndeetandGitHub 27670dae99 Improvements (#6)
* Add external dependencies to manifest to avoid error on module activation; add requirements.txt.
* Readme 
* Fix errors, restructure settings form, update installation steps, streamline overall.
* Change version
2024-07-03 14:49:50 +02:00
vandekul 7930e3eb30 BTCPay Library Included 2023-11-13 14:40:43 +01:00
vandekul a37990667a Image modify 2023-09-19 14:40:53 +02:00
vandekul 411b83fb06 Modify Image for documentation 2023-09-19 14:37:35 +02:00
vandekul 73d2feabbe Modify url and delete notifyMailer field 2023-09-19 14:20:00 +02:00
vandekul feb4aa72b7 License and Readme 2023-09-19 12:10:37 +02:00
vandekul fa5d459fa2 Bug in duplicate providers 2023-09-18 12:04:39 +02:00
vandekul 7810629596 New version 16.0 2023-09-15 14:42:14 +02:00
vandekul ac2194498a Merge branch '9.0' of github.com:zynthian/addons-vandekul into 9.0 2023-07-26 18:13:22 +02:00
jofemodo 2e832d5b18 Add alternate icons for the payment acquirer. 2022-04-02 20:32:24 +02:00
jofemodo bad3ea017b + Improve BTCPay IPN controller handler for avoiding uneeded API call to BTCPay.
+ Add some logging/error messages.
2022-04-02 20:31:06 +02:00
susanna 80ce33f40d Error IPN 2021-11-05 13:05:56 +01:00
susanna 0c251a6790 Modify IPN error 2021-11-05 11:57:07 +01:00
jofemodo 25aecac922 Fix recently added Bitcoin icon. 2020-09-15 14:22:43 +02:00
jofemodo b2820f1cb2 Add Bitcoin icon for using on the payment button. 2020-09-15 13:57:06 +02:00
vandekul 01d2a36d37 Exception control in return status 2020-09-11 12:31:35 +02:00
vandekul 363c4169dc Bug solved in xml files structure 2020-09-10 23:52:16 +02:00
vandekul e980bad67e Merge branch '9.0' of github.com:vandekul/addons-vandekul into 9.0 2020-04-11 01:05:56 +02:00
vandekul 0aa10bf49c Validate provide BTCPay for new fields controll 2020-04-11 01:04:08 +02:00
SusannaandGitHub ef6f02da2a Update README.md 2020-04-11 00:10:27 +02:00
SusannaandGitHub 8844df3cb6 Update README.md 2020-04-11 00:08:24 +02:00
46 changed files with 747 additions and 862 deletions
+11
View File
@@ -0,0 +1,11 @@
# BTCPay Server payment gateway for Odoo 16 and 17
## Accept bitcoin payments on Odoo 16 and 17
This odoo addon allows you to accept bitcoin and Lightning Network (and other cryptocurrency) payments in your Odoo e-commerce store.
![BTCPay Server Banner](https://raw.githubusercontent.com/btcpayserver/odoo/17.0/payment_btcpayserver/static/description/BTCPay-Odoo-17-featured.png)
## How to install
Please find the installation instructions here:
- [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)
-27
View File
@@ -1,27 +0,0 @@
# payment_btcpay
# Gateway to BTCPay for Odoo v9.0
## This is the module to connect Odoo 9.0 and BTCPay
This module allow you to create an easily way to accept cryptocurrencies.
## Configure Payment Acquirer
* Install BTCPay Module -> Website -> eCommerce -> Payment Acquirers -> BTCPay
* Put your facace. Best option is 'merchant'.
* Put the location as test or live url. Test example url: https://testnet.demo.btcpayserver.org
* Put the Confirmation URL where BTCpay will return after payment.
* Check if you want that Odoo send an email to your buyer after transaction is "Confirmed"
* Put your "Pairing Code" if you want that system get the "Token", after that "Pairing Code" will be deleted and the "Token" will appear in the corresponding field. You must safe the changes in order that this happens. NOTE: if you want to get new "Token" throw new "Pairing Code", please remove the "Token" field. Keep in mind that "Token" field must be in blank if you want to get throw the API.
* Put your "Token" if you have it and don't want to use Pairing Code to get it. Remember, if you want to get throw API please don't write anything here.
* If you have a Private Key you can write here otherwise system will get when you safe the Payment Acquirer
* Remember to Publish On Website
![Payment Acquirer](/static/description/BTCPayPaymentAcquirer.png)
## Transaction BTCPay Details
In transaction object, you will find more technical information about this method of payment:
* Transaction Id: cryptocurrency transaction hash for the executed payout
* Invoice Id: the id of the invoice for which you want to fetch an event token
* Transaction Status: That indicates state of transaction
* Buyer Mail Notification: Indicates if mail has been sent or if not (it will be in blank)
![Transaction Btcpay Details](/static/description/BtcpayTxDetails.png)
-2
View File
@@ -1,2 +0,0 @@
import controller
import models
-43
View File
@@ -1,43 +0,0 @@
#******************************************************************************
# PAYMENT BTCPAY FOR ODOO
#
# Copyright (C) 2020 Susanna Fort <susannafm@gmail.com>
#
#******************************************************************************
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# For a full copy of the GNU General Public License see the LICENSE.txt file.
#
#******************************************************************************
{
'name': "Gateway BTCPay",
'summary': """This module integrates BTCPAY - pay with Bitcoin - with Odoo v9.0""",
'author': "Vandekul",
'website': "https://github.com/vandekul",
'category': 'Website',
'version': '9.0',
'license': 'GPL-3',
'price':'100',
'application': True,
'depends': ['base', 'payment'],
'data': [
'views/payment_btcpay_templates.xml',
'views/btcpay_configuration_view.xml',
'data/payment_acquirer_data.xml'
],
'installable': True,
'auto_install': False,
'description': 'static/description/index.html',
'images': ['static/description/icon.png', 'static/description/main_screenshot.png'],
}
-4
View File
@@ -1,4 +0,0 @@
# -*- coding: utf-8 -*-
import main
#import merchant_facade
#import crypto
-110
View File
@@ -1,110 +0,0 @@
#******************************************************************************
# PAYMENT BTCPAY FOR ODOO
#
# Copyright (C) 2020 Susanna Fort <susannafm@gmail.com>
#
#******************************************************************************
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# For a full copy of the GNU General Public License see the LICENSE.txt file.
#
#******************************************************************************
import json
import logging
import pprint
import requests
import werkzeug
import client
import crypto as bku
from client import BTCPayClient
import urllib2,cookielib
from openerp import api, fields, models, _
from openerp.osv import osv
from openerp import http, SUPERUSER_ID
from openerp.addons.payment.models.payment_acquirer import ValidationError
from openerp.http import request
_logger = logging.getLogger(__name__)
class BtcpayController(http.Controller):
_notify_url = '/payment/btcpay/ipn'
@http.route('/payment/btcpay/ipn', type='json', auth='none')
def btcpay_ipn(self, **post):
""" BTCPay IPN. """
cr, uid, context, env = request.cr, SUPERUSER_ID, request.context, request.env
acquirer = request.env['payment.acquirer'].search([('provider', '=', 'btcpay')])
#_logger.info('REQUEST JSONREQUEST %s',pprint.pformat(request.jsonrequest))
invoiceId = request.jsonrequest['data']['id']
client = BTCPayClient(host=acquirer.location, pem=acquirer.privateKey, tokens=acquirer.token)
self.invoice = client.get_invoice(invoiceId)
#_logger.info('SELF INVOICE IPN %s',pprint.pformat(self.invoice))
tx = None
if self.invoice['orderId']:
tx_ids = request.registry['payment.transaction'].search(cr, uid, [('reference', '=', self.invoice['orderId'])], context=context)
if tx_ids:
tx = request.registry['payment.transaction'].browse(cr, uid, tx_ids[0], context=context)
tx.btcpay_status = self.invoice['status']
if self.invoice['status'] in ['confirmed']:
tx.state = 'done'
tx.sale_order_id.state = 'sale'
if not tx.btcpay_buyerMailNotification and acquirer.buyerNotification:
tx.sale_order_id.force_quotation_send()
tx.btcpay_buyerMailNotification = "Send"
tx.sale_order_id.order_line._action_procurement_create()
elif self.invoice['status'] in ['paid']:
tx.state = 'pending'
tx.btcpay_invoiceId =self.invoice['id']
tx.btcpay_txid =((((self.invoice['cryptoInfo'])[0])['payments'])[0])['id']
return ''
@http.route(['/btcpay/checkout'], type='http', auth='none', csrf=None, website=True)
def checkout(self, **post):
cr, uid, context, env = request.cr, SUPERUSER_ID, request.context, request.env
acquirer = env['payment.acquirer'].search([('provider', '=', 'btcpay')])
currency = env['res.currency'].browse(eval(post.get('currency_id'))).name
base_url = request.env['ir.config_parameter'].get_param('web.base.url')
return_url = base_url + self._notify_url
client = BTCPayClient(host=acquirer.location, pem=acquirer.privateKey, tokens=acquirer.token)
acquirer.invoice = client.create_invoice(
{"price": post.get('amount'),
"currency": currency,
"orderId": post.get('reference'),
"token": acquirer.token,
"redirectURL": acquirer.confirmationURL,
"notificationURL": return_url,
"extendedNotifications": True,
"buyer": { "email": post.get('email'),
"name": post.get('name'),
"address1": post.get('street'),
"locality": post.get('city'),
"postalCode": post.get('zip'),
"country": post.get('country'),
"notify": False}})
invoiceId = dict(acquirer.invoice)['id']
self.invoice = client.get_invoice(invoiceId)
return werkzeug.utils.redirect(self.invoice['url'])
@@ -1,36 +0,0 @@
<!--******************************************************************************
# PAYMENT BTCPAY FOR ODOO
#
# Copyright (C) 2020 Susanna Fort <susannafm@gmail.com>
#
#******************************************************************************
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# For a full copy of the GNU General Public License see the LICENSE.txt file.
#
#******************************************************************************-->
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<record id="payment_acquirer_btcpay" model="payment.acquirer">
<field name="name">Btcpay</field>
<field name="image" type="base64" file="payment_btcpay/static/description/icon.png"/>
<field name="provider">btcpay</field>
<field name="company_id" ref="base.main_company"/>
<field name="view_template_id" ref="btcpay_acquirer_form"/>
<field name="environment">test</field>
<field name="pre_msg"><![CDATA[
<p>You will be redirected to BTCPay website after clicking on the payment button.</p>]]></field>
</record>
</data>
</openerp>
-1
View File
@@ -1 +0,0 @@
import btcpay
-81
View File
@@ -1,81 +0,0 @@
#******************************************************************************
# PAYMENT BTCPAY FOR ODOO
#
# Copyright (C) 2020 Susanna Fort <susannafm@gmail.com>
#
#******************************************************************************
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# For a full copy of the GNU General Public License see the LICENSE.txt file.
#
#******************************************************************************
from openerp import api, fields, models, _
from openerp.osv import osv
from ..controller import crypto as bku
from ..controller.client import BTCPayClient
import logging
import pprint
from openerp import http, SUPERUSER_ID
_logger = logging.getLogger(__name__)
class AcquirerBtcPay(models.Model):
_inherit = 'payment.acquirer'
def _get_providers(self, cr, uid, context=None):
providers = super(AcquirerBtcPay, self)._get_providers(cr, uid, context=context)
providers.append(['btcpay', 'btcpay'])
return providers
token = fields.Char('Token', help='Access Token to BTCPay')
privateKey = fields.Text('Private Key', help='Private Key for BTCPay Client')
facade = fields.Char('Facade', help='Token facade type: merchant/pos/payroll') #merchant
pairingCode = fields.Char('Pairing Code', help='Create a paring Code in your BTCPay server and put here')
location = fields.Char('Location', size=64)
confirmationURL = fields.Char('Confirmation URL', help='Confirmation URL to return after Btcpay payment')
buyerNotification = fields.Boolean('Odoo confirmation mail to buyer', help='If it is checked, Odoo will send the confirmation mail defined')
_defaults = {
'facade': 'merchant',
'location':'https://testnet.demo.btcpayserver.org', #Testnet BTCPay
'confirmationURL':'http://odoo-dev.zynthian.org/shop/confirmation',
'buyerNotification': 'True',
}
def create(self, cr, uid, values, context=None):
if not values.get('privateKey'):
values['privateKey'] = bku.generate_privkey()
return super(AcquirerBtcPay, self).create(cr, uid, values, context=context)
@api.onchange('pairingCode')
def _onchange_pairingCode(self):
if not self.token:
client = BTCPayClient(host=self.location, pem=self.privateKey)
token = client.pair_client(self.pairingCode)
self.token = token.get(self.facade)
@api.onchange('token')
def _onchange_token(self):
self.pairingCode = ''
class BtcPayTransaction(models.Model):
_inherit = "payment.transaction"
btcpay_invoiceId = fields.Char("Invoice Id")
btcpay_txid = fields.Char("Transaction Id")
btcpay_status = fields.Char("Transaction Status")
btcpay_buyerMailNotification = fields.Char("Buyer Mail Notification")
acquirer_name = fields.Selection(related='acquirer_id.provider')
Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

@@ -1,89 +0,0 @@
<html xmlns="http://www.w3.org/1999/html">
<body>
<section class="oe_container">
<div class="oe_row oe_spaced">
<h2 class="oe_slogan">BTCPay Gateway</h2>
<h3 class="oe_slogan">This is the module to connect Odoo 9.0 and Btcpay</h3>
<div class="oe_span6">
<div class="oe_bg_img">
<img src="Btcpay_com.png" class="oe_picture oe_screenshot">
</div>
</div>
<div class="oe_span6">
<p class='oe_mt32'>
This module allow you to create an easily way to accept Bitcoins.
</p>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<h2 class="oe_slogan">Configure Payment Acquirer</h2>
<div class="oe_span6">
<p class='oe_mt32'>
<ul>
<li>Install BTCPay Module -> Website -> eCommerce -> Payment Acquirers -> BTCPay</li>
<li>Put your facace. Best option is 'merchant'.</li>
<li>Put the location as test or live url. Test example url: https://testnet.demo.btcpayserver.org</li>
<li>Put the Confirmation URL where BTCpay will return after payment.</li>
<li>Check if you want that Odoo send an email to your buyer after transaction is "Confirmed"</li>
<li>Put your "Pairing Code" if you want that system get the "Token", after that "Pairing Code" will be deleted and the "Token" will appear in the corresponding field. You must safe the changes in order that this happens. NOTE: if you want to get new "Token" throw new "Pairing Code", please remove the "Token" field. Keep in mind that "Token" field must be in blank if you want to get throw the API.</li>
<li>Put your "Token" if you have it and don't want to use Pairing Code to get it. Remember, if you want to get throw API please don't write anything here.</li>
<li>If you have a Private Key you can write here otherwise system will get when you safe the Payment Acquirer </li>
<li>Remember to Publish On Website</li>
</ul>
</p>
</div>
<div class="oe_span6">
<div class="oe_bg_img">
<img src="BTCPayPaymentAcquirer.png" class="oe_picture oe_screenshot">
</div>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<h2 class="oe_slogan">How it looks like?</h2>
<div class="oe_span6">
<div class="oe_bg_img">
<img src="BTCPayLooksLike.png" class="oe_picture oe_screenshot">
</div>
</div>
<div class="oe_span6">
<p class='oe_mt32'>
<ul>
In payment webpage where payment methods appear, you will find new payment method called BTCPay.
If you click on it you will be redirect to the server that you indicate in location field.
</ul>
</p>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<h2 class="oe_slogan">Transaction BTCPay Details</h2>
<div class="oe_span6">
<p class='oe_mt32'>
<ul>
In transaction object, you will find more technical information about this method of payment:
<li>Transaction Id: cryptocurrency transaction hash for the executed payout.</li>
<li>Invoice Id: the id of the invoice for which you want to fetch an event token</li>
<li>Transaction Status: That indicates state of transaction</li>
<li>Buyer Mail Notification: Indicates if mail has been sent or if not (it will be in blank)</li>
</ul>
</p>
</div>
<div class="oe_span6">
<div class="oe_bg_img">
<img src="BtcpayTxDetails.png" class="oe_picture oe_screenshot">
</div>
</div>
</div>
</section>
</body>
</html>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

-2
View File
@@ -1,2 +0,0 @@
# -*- coding: utf-8 -*-
from . import btcpay_test
-244
View File
@@ -1,244 +0,0 @@
NEW ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
': {u'BTC': u'tb1q6xglf49usp7hvz57hcn5s3ela0z7784xzxc6zz'},
u'amountPaid': 0,
u'bitcoinAddress': u'tb1q6xglf49usp7hvz57hcn5s3ela0z7784xzxc6zz',
u'btcDue': u'0.00016569',
u'btcPaid': u'0.00000000',
u'btcPrice': u'0.00016569',
u'buyer': {u'address1': u'Carretera Rubi\xf3',
u'address2': None,
u'country': None,
u'email': u'cristina@solis.com',
u'locality': None,
u'name': u'Maria Cristina Sol\xeds',
u'phone': None,
u'postalCode': None,
u'region': None},
u'buyerPaidBtcMinerFee': None,
u'buyerTotalBtcAmount': None,
u'cryptoInfo': [{u'address': u'tb1q6xglf49usp7hvz57hcn5s3ela0z7784xzxc6zz',
u'cryptoCode': u'BTC',
u'cryptoPaid': u'0.00000000',
u'due': u'0.00016569',
u'exRates': {u'EUR': 0.0},
u'networkFee': u'0.00000000',
u'paid': u'0.00000000',
u'paymentType': u'BTCLike',
u'paymentUrls': {u'BIP21': u'bitcoin:tb1q6xglf49usp7hvz57hcn5s3ela0z7784xzxc6zz?amount=0.00016569',
u'BIP72': None,
u'BIP72b': None,
u'BIP73': None,
u'BOLT11': None},
u'payments': [],
u'price': u'0.00016569',
u'rate': 6035.635,
u'totalDue': u'0.00016569',
u'txCount': 0,
u'url': u'https://testnet.demo.btcpayserver.org/i/BTC/8Ne9cafEfuJTX5qBMMVFVa'}],
u'currency': u'EUR',
u'currentTime': 1585230897038,
u'exRates': {u'EUR': 0.0},
u'exceptionStatus': False,
u'exchangeRates': {u'BTC': {u'EUR': 0.0}},
u'expirationTime': 1585231795000,
u'flags': {u'refundable': False},
u'guid': u'e1913afa-136c-415c-bf5d-bcd9bb817b0d',
u'id': u'8Ne9cafEfuJTX5qBMMVFVa',
u'invoiceTime': 1585230895000,
u'itemCode': None,
u'itemDesc': None,
u'lowFeeDetected': False,
u'minerFees': {u'BTC': {u'satoshisPerByte': 1.0, u'totalFee': 0.0}},
u'orderId': u'SO3166',
u'paymentCodes': {u'BTC': {u'BIP21': u'bitcoin:tb1q6xglf49usp7hvz57hcn5s3ela0z7784xzxc6zz?amount=0.00016569',
u'BIP72': None,
u'BIP72b': None,
u'BIP73': None,
u'BOLT11': None}},
u'paymentSubtotals': {u'BTC': 16569.0},
u'paymentTotals': {u'BTC': 16569.0},
u'paymentUrls': {u'BIP21': u'bitcoin:tb1q6xglf49usp7hvz57hcn5s3ela0z7784xzxc6zz?amount=0.00016569',
u'BIP72': None,
u'BIP72b': None,
u'BIP73': None,
u'BOLT11': None},
u'posData': None,
u'price': 1.0,
u'rate': 6035.635,
u'refundAddressRequestPending': False,
u'status': u'new',
u'supportedTransactionCurrencies': {u'BTC': {u'enabled': True,
u'reason': None}},
u'token': u'Xf3ji4rhcZc7QoKNyzorFq',
u'url': u'https://testnet.demo.btcpayserver.org/invoice?id=8Ne9cafEfuJTX5qBMMVFVa'}
PAID +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{u'addresses': {u'BTC': u'tb1q6xglf49usp7hvz57hcn5s3ela0z7784xzxc6zz'},
u'amountPaid': 0,
u'bitcoinAddress': u'tb1q6xglf49usp7hvz57hcn5s3ela0z7784xzxc6zz',
u'btcDue': u'0.00000000',
u'btcPaid': u'0.00016569',
u'btcPrice': u'0.00016569',
u'buyer': {u'address1': u'Carretera Rubi\xf3',
u'address2': None,
u'country': None,
u'email': u'cristina@solis.com',
u'locality': None,
u'name': u'Maria Cristina Sol\xeds',
u'phone': None,
u'postalCode': None,
u'region': None},
u'buyerPaidBtcMinerFee': None,
u'buyerTotalBtcAmount': None,
u'cryptoInfo': [{u'address': u'tb1q6xglf49usp7hvz57hcn5s3ela0z7784xzxc6zz',
u'cryptoCode': u'BTC',
u'cryptoPaid': u'0.00016569',
u'due': u'0.00000000',
u'exRates': {u'EUR': 0.0},
u'networkFee': u'0.00000000',
u'paid': u'0.00016569',
u'paymentType': u'BTCLike',
u'paymentUrls': {u'BIP21': u'bitcoin:tb1q6xglf49usp7hvz57hcn5s3ela0z7784xzxc6zz?amount=0.00',
u'BIP72': None,
u'BIP72b': None,
u'BIP73': None,
u'BOLT11': None},
u'payments': [{u'completed': False,
u'confirmed': False,
u'destination': u'tb1q6xglf49usp7hvz57hcn5s3ela0z7784xzxc6zz',
u'fee': 0.0,
u'id': u'8e334ae16f57eca9ca6a1c2fe8de0aa3fe85a07f3fe64aab2a08657b7e185239-1',
u'paymentType': u'BTCLike',
u'receivedDate': u'2020-03-26T13:56:39',
u'value': 0.00016569}],
u'price': u'0.00016569',
u'rate': 6035.635,
u'totalDue': u'0.00016569',
u'txCount': 1,
u'url': u'https://testnet.demo.btcpayserver.org/i/BTC/8Ne9cafEfuJTX5qBMMVFVa'}],
u'currency': u'EUR',
u'currentTime': 1585231001490,
u'exRates': {u'EUR': 0.0},
u'exceptionStatus': False,
u'exchangeRates': {u'BTC': {u'EUR': 0.0}},
u'expirationTime': 1585231795000,
u'flags': {u'refundable': False},
u'guid': u'0247206a-d05b-4f00-b679-d7261aca0714',
u'id': u'8Ne9cafEfuJTX5qBMMVFVa',
u'invoiceTime': 1585230895000,
u'itemCode': None,
u'itemDesc': None,
u'lowFeeDetected': False,
u'minerFees': {u'BTC': {u'satoshisPerByte': 1.0, u'totalFee': 0.0}},
u'orderId': u'SO3166',
u'paymentCodes': {u'BTC': {u'BIP21': u'bitcoin:tb1q6xglf49usp7hvz57hcn5s3ela0z7784xzxc6zz?amount=0.00',
u'BIP72': None,
u'BIP72b': None,
u'BIP73': None,
u'BOLT11': None}},
u'paymentSubtotals': {u'BTC': 16569.0},
u'paymentTotals': {u'BTC': 16569.0},
u'paymentUrls': {u'BIP21': u'bitcoin:tb1q6xglf49usp7hvz57hcn5s3ela0z7784xzxc6zz?amount=0.00',
u'BIP72': None,
u'BIP72b': None,
u'BIP73': None,
u'BOLT11': None},
u'posData': None,
u'price': 1.0,
u'rate': 6035.635,
u'refundAddressRequestPending': False,
u'status': u'paid',
u'supportedTransactionCurrencies': {u'BTC': {u'enabled': True,
u'reason': None}},
u'token': u'SV24W1puvz1ZqaHj9nb6vx',
u'url': u'https://testnet.demo.btcpayserver.org/invoice?id=8Ne9cafEfuJTX5qBMMVFVa'}
CONFIRMED ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{u'addresses': {u'BTC': u'tb1q6xglf49usp7hvz57hcn5s3ela0z7784xzxc6zz'},
u'amountPaid': 0,
u'bitcoinAddress': u'tb1q6xglf49usp7hvz57hcn5s3ela0z7784xzxc6zz',
u'btcDue': u'0.00000000',
u'btcPaid': u'0.00016569',
u'btcPrice': u'0.00016569',
u'buyer': {u'address1': u'Carretera Rubi\xf3',
u'address2': None,
u'country': None,
u'email': u'cristina@solis.com',
u'locality': None,
u'name': u'Maria Cristina Sol\xeds',
u'phone': None,
u'postalCode': None,
u'region': None},
u'buyerPaidBtcMinerFee': None,
u'buyerTotalBtcAmount': None,
u'cryptoInfo': [{u'address': u'tb1q6xglf49usp7hvz57hcn5s3ela0z7784xzxc6zz',
u'cryptoCode': u'BTC',
u'cryptoPaid': u'0.00016569',
u'due': u'0.00000000',
u'exRates': {u'EUR': 0.0},
u'networkFee': u'0.00000000',
u'paid': u'0.00016569',
u'paymentType': u'BTCLike',
u'paymentUrls': {u'BIP21': u'bitcoin:tb1q6xglf49usp7hvz57hcn5s3ela0z7784xzxc6zz?amount=0.00',
u'BIP72': None,
u'BIP72b': None,
u'BIP73': None,
u'BOLT11': None},
u'payments': [{u'completed': False,
u'confirmed': True,
u'destination': u'tb1q6xglf49usp7hvz57hcn5s3ela0z7784xzxc6zz',
u'fee': 0.0,
u'id': u'8e334ae16f57eca9ca6a1c2fe8de0aa3fe85a07f3fe64aab2a08657b7e185239-1',
u'paymentType': u'BTCLike',
u'receivedDate': u'2020-03-26T13:56:39',
u'value': 0.00016569}],
u'price': u'0.00016569',
u'rate': 6035.635,
u'totalDue': u'0.00016569',
u'txCount': 1,
u'url': u'https://testnet.demo.btcpayserver.org/i/BTC/8Ne9cafEfuJTX5qBMMVFVa'}],
u'currency': u'EUR',
u'currentTime': 1585231286866,
u'exRates': {u'EUR': 0.0},
u'exceptionStatus': False,
u'exchangeRates': {u'BTC': {u'EUR': 0.0}},
u'expirationTime': 1585231795000,
u'flags': {u'refundable': False},
u'guid': u'3e236c9a-290b-45ee-ad2f-529c2b9ef392',
u'id': u'8Ne9cafEfuJTX5qBMMVFVa',
u'invoiceTime': 1585230895000,
u'itemCode': None,
u'itemDesc': None,
u'lowFeeDetected': False,
u'minerFees': {u'BTC': {u'satoshisPerByte': 1.0, u'totalFee': 0.0}},
u'orderId': u'SO3166',
u'paymentCodes': {u'BTC': {u'BIP21': u'bitcoin:tb1q6xglf49usp7hvz57hcn5s3ela0z7784xzxc6zz?amount=0.00',
u'BIP72': None,
u'BIP72b': None,
u'BIP73': None,
u'BOLT11': None}},
u'paymentSubtotals': {u'BTC': 16569.0},
u'paymentTotals': {u'BTC': 16569.0},
u'paymentUrls': {u'BIP21': u'bitcoin:tb1q6xglf49usp7hvz57hcn5s3ela0z7784xzxc6zz?amount=0.00',
u'BIP72': None,
u'BIP72b': None,
u'BIP73': None,
u'BOLT11': None},
u'posData': None,
u'price': 1.0,
u'rate': 6035.635,
u'refundAddressRequestPending': False,
u'status': u'confirmed',
u'supportedTransactionCurrencies': {u'BTC': {u'enabled': True,
u'reason': None}},
u'token': u'S8QfFkkTLY6GmrrauWMmHL',
u'url': u'https://testnet.demo.btcpayserver.org/invoice?id=8Ne9cafEfuJTX5qBMMVFVa'}
-61
View File
@@ -1,61 +0,0 @@
import pprint
import logging
import requests
import json
import re
import os.path
#import bitpay_key_utils as bku
#from bitpay_client import *
import btcpay.crypto
from btcpay import BTCPayClient
API_HOST = "https://testnet.demo.btcpayserver.org" #Testnet BTCPAY
KEY_FILE = "/tmp/key.priv"
TOKEN_FILE = "/tmp/btctoken.priv"
if os.path.isfile(KEY_FILE):
f = open(KEY_FILE, 'r')
key = f.read()
f.close()
print("Creating a bitpay client using existing private key from disk.")
else:
key = btcpay.crypto.generate_privkey()
f = open(KEY_FILE, 'w')
f.write(key)
f.close()
client = BTCPayClient(host=API_HOST, pem=key)
def fetch_token(facade, pairingCode):
if os.path.isfile(TOKEN_FILE + facade):
f = open(TOKEN_FILE + facade, 'r')
token = f.read()
f.close()
client.tokens[facade] = token
else:
token = client.pair_client(pairingCode)
client.tokens[facade] = token
f = open(TOKEN_FILE + facade, 'w')
print(token[facade])
f.write(token[facade])
f.close()
pairingCode = "otMSapf"
facade = "merchant"
fetch_token(facade, pairingCode)
print(client.tokens[facade])
client = BTCPayClient(host=API_HOST, pem=key, tokens=client.tokens)
print(client)
#fetch_token(facade, pairingCode)
#print("Token: ", client.tokens[facade])
new_invoice = client.create_invoice({"price": 20, "currency": "EUR", "token": client.tokens[facade],"extendedNotifications": True})
print("NEW INVOICE: ", new_invoice)
fetched_invoice = client.get_invoice(new_invoice['id'])
print("FETCHED INVOICE: ", new_invoice['id'])
curl --no-keepalive --raw --show-error --verbose --connect-timeout 10 --insecure --max-redirs 1 -H "Content-Type: application/json" -d '{"data": "{"id":"P38S4ewSvvLoRrBSoEiMTz"}"}" http://odoo-dev.zynthian.org/payment/btcpay/ipn
@@ -1,63 +0,0 @@
<!--******************************************************************************
# PAYMENT BTCPAY FOR ODOO
#
# Copyright (C) 2020 Susanna Fort <susannafm@gmail.com>
#
#******************************************************************************
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# For a full copy of the GNU General Public License see the LICENSE.txt file.
#
#******************************************************************************-->
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="acquirer_form_btcpay" model="ir.ui.view">
<field name="name">acquirer.form.btcpay</field>
<field name="model">payment.acquirer</field>
<field name="inherit_id" ref="payment.acquirer_form"/>
<field name="arch" type="xml">
<xpath expr='//group[@name="acquirer"]' position='after'>
<group attrs="{'invisible': [('provider', '!=', 'btcpay')]}">
<field name="facade"/>
<field name="location"/>
<field name="confirmationURL"/>
<field name="buyerNotification"/>
<field name="pairingCode"/>
<field name="token"/>
<field name="privateKey"/>
</group>
</xpath>
</field>
</record>
<record id="transaction_form_btcpay" model="ir.ui.view">
<field name="name">acquirer.transaction.form.btcpay</field>
<field name="model">payment.transaction</field>
<field name="inherit_id" ref="payment.transaction_form"/>
<field name="arch" type="xml">
<xpath expr='//notebook' position='inside'>
<page string="Btcpay TX Details">
<group>
<field name="btcpay_txid"/>
<field name="btcpay_invoiceId" />
<field name="btcpay_status"/>
<field name="btcpay_buyerMailNotification"/>
</group>
</page>
</xpath>
</field>
</record>
</data>
</openerp>
-32
View File
@@ -1,32 +0,0 @@
<!--******************************************************************************
# PAYMENT BTCPAY FOR ODOO
#
# Copyright (C) 2020 Susanna Fort <susannafm@gmail.com>
#
#******************************************************************************
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# For a full copy of the GNU General Public License see the LICENSE.txt file.
#
#******************************************************************************-->
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!--BtcPay Top Menu-->
<menuitem id="btcpay_main_menu" name="BtcPay" icon="terp-sale" sequence="1"/>
<!--Main Menus-->
<menuitem id="btcpay_configuration_menu" action="action_btcpay_instance" name="Configuration"
parent="btcpay_main_menu" sequence="0"/>
</data>
</openerp>
@@ -1,47 +0,0 @@
<!--******************************************************************************
# PAYMENT BTCPAY FOR ODOO
#
# Copyright (C) 2020 Susanna Fort <susannafm@gmail.com>
#
#******************************************************************************
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# For a full copy of the GNU General Public License see the LICENSE.txt file.
#
#******************************************************************************-->
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<template id="btcpay_acquirer_form" name="Btcpay Payment Button">
<form t-if="acquirer" action="/btcpay/checkout" method="post" target="_self">
<input type="hidden" name="acquirer" t-att-value="acquirer.id"/>
<input type="hidden" name="reference" t-att-value="reference"/>
<input type="hidden" name="name" t-att-value="partner_name"/>
<input type="hidden" name="email" t-att-value="partner_email"/>
<input type="hidden" name="street" t-att-value="partner_address"/>
<input type="hidden" name="zip" t-att-value="partner_zip"/>
<input type="hidden" name="city" t-att-value="partner_city"/>
<input type="hidden" name="currency_id" t-att-value="currency_id"/>
<input type="hidden" name="country" t-att-value="partner_country_id"/>
<input type="hidden" name="custom" t-att-value="custom"/>
<input type="hidden" name="amount" t-att-value="amount"/>
<button type="submit" width="100px" t-att-class="submit_class">
<img t-if="not submit_txt" src="/static/description/icon.png"/>
<span t-if="submit_txt"> <t t-esc="submit_txt"/> <span class="fa fa-long-arrow-right"/>
</span>
</button>
</form>
</template>
</data>
</openerp>
+64
View File
@@ -0,0 +1,64 @@
# BTCPay Server payment gateway for Odoo 17
## This is the module to connect Odoo 17 and BTCPay Server
This module allows you to accept bitcoin (and other cryptocurrency) payments in your Odoo e-commerce store.
![BTCPay Server Banner](https://raw.githubusercontent.com/btcpayserver/odoo/17.0/payment_btcpayserver/static/description/BTCPay-Odoo-17-featured.png)
:::tip
If you use Odoo 16 you can find the documentation [here](https://github.com/btcpayserver/odoo/blob/16.0/payment_btcpayserver/README.md).
:::
## 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)
* Make sure you are on branch `17.0` or downloaded a release tagged with version v17.x
* 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)
* Restart Odoo
* Go to Apps -> Update Apps List
* Remove the "Apps" filter and search for "btcpay"
* Click **Activate** button
## Configure BTCPay as payment provider
* Go to **Website** -> **Configuration** -> **Payment Providers**
* Search for BTCPay and click on button **Activate**
In the BTCPay settings form, tab "Credentials":
* Set field "State" to enabled
* 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
* Click on "Create Token" button
* Label: enter e.g. "My odoo store"
* Public Key: leave empty
* 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"
* 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
* When the pairing is successful the "Token" and "Private Key" field will be filled automatically
* Field Facade, keep default 'merchant'.
On the tab "Configuration":
* 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
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.
![Payment Provider Settings](https://raw.githubusercontent.com/btcpayserver/odoo/17.0/payment_btcpayserver/static/description/BTCPayPaymentSettings.png)
## 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.
![Checkout page example](https://raw.githubusercontent.com/btcpayserver/odoo/17.0/payment_btcpayserver/static/description/BTCPayLooksLike.png)
## Transaction BTCPay Details
In transaction object, you will find more technical information about this method of payment:
* Transaction Id: cryptocurrency transaction hash for the executed payout
* Invoice Id: the id of the invoice for which you want to fetch an event token
* Transaction Status: That indicates state of transaction
![Transaction details of BTCPay](https://raw.githubusercontent.com/btcpayserver/odoo/17.0/payment_btcpayserver/static/description/BtcpayTxDetails.png)
+14
View File
@@ -0,0 +1,14 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import controllers
from . import models
from odoo.addons.payment import setup_provider, reset_payment_provider
def post_init_hook(env):
setup_provider(env, 'btcpayserver')
def uninstall_hook(env):
reset_payment_provider(env, 'btcpayserver')
+47
View File
@@ -0,0 +1,47 @@
#******************************************************************************
# PAYMENT BTCPAY SERVER FOR ODOO
#
# Copyright (C) 2024 Susanna Fort <susannafm@gmail.com>, ndeet
#
#******************************************************************************
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# For a full copy of the GNU General Public License see the LICENSE.txt file.
#
#******************************************************************************
{
'name': 'Payment Provider: BTCPay Server',
'summary': 'This module integrates BTCPAY - pay with Bitcoin - with Odoo v17.0',
'author': 'BTCPay Server team and contributors',
'website': 'https://github.com/btcpayserver/odoo',
'category': 'Accounting/Payment Providers',
'version': '17.0.2.0',
'license': 'GPL-3',
'currency': 'USD',
'application': False,
'installable': True,
'auto_install': False,
'depends': ['base', 'account', 'payment'],
'data': [
'views/payment_btcpayserver_templates.xml',
'views/payment_provider_views.xml',
'views/payment_transaction_views.xml',
'data/payment_provider_data.xml',
],
'images': ['static/description/BTCPay-Odoo-17-featured.png'],
'external_dependencies': {
'python': ['btcpay-python']
},
'post_init_hook': 'post_init_hook',
'uninstall_hook': 'uninstall_hook',
}
@@ -0,0 +1 @@
from . import main
+112
View File
@@ -0,0 +1,112 @@
# ******************************************************************************
# PAYMENT BTCPAY FOR ODOO
#
# Copyright (C) 2020 Susanna Fort <susannafm@gmail.com>
#
# ******************************************************************************
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# For a full copy of the GNU General Public License see the LICENSE.txt file.
#
# ******************************************************************************
import logging
import pprint
import requests
import werkzeug
from werkzeug import urls
from werkzeug.exceptions import Forbidden
from odoo import _, http, SUPERUSER_ID
from odoo.exceptions import ValidationError
from odoo.http import request
from odoo.tools import html_escape
import json
from ..models.libs.client import BTCPayClient
_logger = logging.getLogger(__name__)
class BTCPayController(http.Controller):
_checkout_url = '/btcpay/checkout'
_notify_url = '/payment/btcpay/ipn'
_return_url = '/payment/btcpay/return'
@http.route(_checkout_url, type='http', auth='public', csrf=False, website=True)
def checkout(self, **data):
_logger.info("CHECKOUT: notification received from BTCPay with data:\n%s", pprint.pformat(data))
tx_sudo = request.env['payment.transaction'].sudo()._get_tx_from_notification_data('btcpayserver', data)
provider = tx_sudo.provider_id
notification_url = str(data.get('notify_url')).replace("http://", "https://")
base_url = request.env['ir.config_parameter'].sudo().get_param('web.base.url')
redirect_url = urls.url_join(base_url, self._return_url)
client = BTCPayClient(host=provider.btcpay_location, pem=provider.btcpay_privateKey, tokens={provider.btcpay_facade: provider.btcpay_token})
invoice = client.create_invoice(
{"price": data.get('amount'),
"currency": data.get('currency_id'),
"orderId": data.get('reference'),
"token": provider.btcpay_token,
"redirectURL": redirect_url,
"notificationURL": notification_url,
"extendedNotifications": True,
"buyer": {"email": data.get('email') or 'noemailavailable@example.com',
"name": data.get('name'),
"address1": data.get('street'),
"locality": data.get('city'),
"postalCode": data.get('zip'),
"country": data.get('country'),
"notify": False}})
_logger.info('Invoice %s \n NOTIFY URL: %s', invoice, notification_url)
return werkzeug.utils.redirect(invoice['url'])
@http.route(_notify_url, type='json', auth='public', csrf=False)
def btcpay_ipn(self, **post):
""" BTCPay IPN. """
_logger.info('BTCPAY IPN RECEIVED... ')
data = json.loads(request.httprequest.data)
_logger.info("%s", pprint.pformat(data))
try:
notification_data = {"reference": data['data']['orderId'],
"invoiceID": 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)
provider = tx_sudo.provider_id
client = BTCPayClient(host=provider.btcpay_location, pem=provider.btcpay_privateKey,
tokens={provider.btcpay_facade: provider.btcpay_token})
fetched_invoice = client.get_invoice(notification_data['invoiceID'])
_logger.info('fetched_invoice = %s',pprint.pformat(fetched_invoice))
notification_data = {"reference": fetched_invoice['orderId'],
"status": fetched_invoice['status'],
"invoiceID": fetched_invoice['id'],
"txid": fetched_invoice['url']}
# Handle the notification data
tx_sudo._handle_notification_data('btcpayserver', notification_data)
except ValidationError: # Acknowledge the notification to avoid getting spammed
_logger.exception("Unable to handle the notification data; skipping to acknowledge")
return ''
@http.route(_return_url, type='http', auth="public", methods=['GET'], crsf=False, save_session=False)
def btcpay_return_from_redirect(self, **data):
""" 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")
return request.redirect('/payment/status')
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<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">
<field name="name">BTCPay Server payments</field>
<field name="code">btcpayserver</field>
<field name="image_128" type="base64" file="payment_btcpayserver/static/description/icon.png"/>
<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>
</odoo>
+1
View File
@@ -0,0 +1 @@
from . import payment_provider, payment_transaction
@@ -1,23 +1,17 @@
"""btcpay.crypto
"""btcpay.client
These are various crytography related utility functions borrowed from:
bitpay-python: https://github.com/bitpay/bitpay-python
BTCPay API Client.
"""
import re
import json
import urllib
import urlparse
import logging
import pprint
#from urllib.parse import urlencode
from urllib.parse import urlencode
import requests
from requests.exceptions import HTTPError
from . import crypto
_logger = logging.getLogger(__name__)
class BTCPayClient:
def __init__(self, host, pem, insecure=False, tokens=None):
@@ -41,23 +35,19 @@ class BTCPayClient:
}
def _signed_get_request(self, path, params=None, token=None):
#token = token or list(self.tokens.values())[0]
token = self.tokens
token = token or list(self.tokens.values())[0]
params = params or dict()
params['token'] = token
uri = self.host + path
#payload = '?' + urlencode(params)
payload ="?token=" + params['token']
payload = '?' + urlencode(params)
headers = self._create_signed_headers(uri, payload)
r = self.s.get(uri, params=params, headers=headers)
r.raise_for_status()
return r.json()['data']
def _signed_post_request(self, path, payload, token=None):
#token = token or list(self.tokens.values())[0]
token = self.tokens
token = token or list(self.tokens.values())[0]
uri = self.host + path
payload['token'] = token
payload = json.dumps(payload)
@@ -108,13 +98,10 @@ class BTCPayClient:
return rate['rate']
def create_invoice(self, payload, token=None):
if re.match(r'^[A-Z]{3,3}$', payload['currency']) is None:
raise ValueError('Currency is invalid.')
try:
float(payload['price'])
except ValueError as e:
raise ValueError('Price must be a float')
raise ValueError('Price must be a float') from e
return self._signed_post_request('/invoices/', payload, token=token)
def get_invoice(self, invoice_id, token=None):
@@ -155,6 +142,24 @@ class BTCPayClient:
token = client.pair_client(code)
return BTCPayClient(host=host, pem=pem, tokens=token)
@classmethod
def create_tor_client(cls, code, host, proxy='socks5://127.0.0.1:9050'):
""" Useful for .onion services, the `proxy` input assumes the default
proxy header
"""
pem = crypto.generate_privkey()
client = BTCPayClient(host=host, pem=pem)
client.s.proxies = {
'http': proxy,
'https': proxy}
token = client.pair_client(code)
final_client = BTCPayClient(host=host, pem=pem, tokens=token)
final_client.s.proxies = {
'http': proxy,
'https': proxy}
return final_client
def __repr__(self):
return '{}({})'.format(
type(self).__name__,
@@ -0,0 +1,51 @@
import logging
from odoo import _, api, fields, models
from .libs.client import BTCPayClient
from .libs import crypto
_logger = logging.getLogger(__name__)
class PaymentProvider(models.Model):
_inherit = 'payment.provider'
code = fields.Selection(
selection_add=[('btcpayserver', "BTCPay")], ondelete={'btcpayserver': 'set default'})
btcpay_location = fields.Char(string='BTCPay Server URL', size=64, help='URL where your BTCPay Server instance is reachable (where you log into your BTCPay Server).', default='https://testnet.demo.btcpayserver.org')
btcpay_pairingCode = fields.Char(string='Pairing Code', help='Create paring Code in your BTCPay server and put here')
btcpay_token = fields.Char(string='Token', help='Access Token to BTCPay. Leave empty, will be autogenerated during pairing.')
btcpay_privateKey = fields.Text(string='Private Key', help='Private Key for BTCPay Client. Leave empty, will be autogenerated during pairing.')
btcpay_facade = fields.Char(string='Facade', help='Token facade type: merchant/pos/payroll. Keep merchant', default='merchant')
def create(self, values_list):
if self.code == 'btcpayserver':
values_list['btcpay_privateKey'] = crypto.generate_privakey()
return super(PaymentProvider, self).create(values_list)
@api.onchange('btcpay_pairingCode')
def _onchange_pairingCode(self):
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()
client = BTCPayClient(host=self.btcpay_location, pem=self.btcpay_privateKey)
token = client.pair_client(self.btcpay_pairingCode)
self.btcpay_token = token.get(self.btcpay_facade)
@api.onchange('btcpay_token')
def _onchange_token(self):
if self.code == 'btcpayserver':
self.btcpay_pairingCode = ''
#_logger.info("ONCHANGE TOKEN")
@api.onchange('btcpay_location')
def _onchange_location(self):
if self.code == 'btcpayserver':
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_pairingCode = ''
@@ -0,0 +1,135 @@
import logging
import pprint
from werkzeug import urls
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
from odoo.addons.payment import utils as payment_utils
_logger = logging.getLogger(__name__)
class PaymentTransaction(models.Model):
_inherit = 'payment.transaction'
btcpay_invoiceId = fields.Char("Invoice Id")
btcpay_txid = fields.Char("Transaction Id")
btcpay_status = fields.Char("Transaction Status")
api_url = '/btcpay/checkout'
checkout_url = '/btcpay/checkout'
notify_url = 'payment/btcpay/ipn'
def _get_specific_rendering_values(self, processing_values):
""" Override of payment to return Specific rendering values.
Note: self.ensure_one() from `_get_processing_values`
:param dict processing_values: The generic and specific processing values of the transaction
:return: The dict of provider-specific processing values
:rtype: dict
"""
res = super()._get_specific_rendering_values(processing_values)
if self.provider_code != 'btcpayserver':
return res
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)
return {
'address1': self.partner_address,
'amount': self.amount,
'city': self.partner_city,
'country': self.partner_country_id.code,
'currency_code': self.currency_id.name,
'email': self.partner_email,
'first_name': partner_first_name,
'item_name': f"{self.company_id.name}: {self.reference}",
'item_number': self.reference,
'last_name': partner_last_name,
'lc': self.partner_lang,
'state': self.partner_state_id.name,
'zip_code': self.partner_zip,
'api_url': self.checkout_url,
'notify_url': base_url + self.notify_url,
}
def _get_tx_from_notification_data(self, provider_code, notification_data):
""" Override of payment to find the transaction based on 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 dict notification_data: The notification data sent by the provider.
:return: The transaction.
:rtype: recordset of `payment.transaction`
"""
tx = self._get_tx_from_notification_data(provider_code, notification_data)
tx._process_notification_data(notification_data)
tx._execute_callback()
return tx
def _process_notification_data(self, notification_data):
""" Override of payment to process the transaction based on BTCPay data.
Note: self.ensure_one()
:param dict notification_data: The notification data sent by the provider
:return: None
:raise: ValidationError if inconsistent data were received
"""
super()._process_notification_data(notification_data)
if self.provider_code != 'btcpayserver':
return
_logger.info("_process_notification_data %s", pprint.pformat(notification_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.btcpay_txid = notification_data.get('txid')
self.btcpay_status = notification_data.get('status')
if self.btcpay_status in ['paid','processing']:
self._set_pending(state_message=notification_data.get('pending_reason'))
elif self.btcpay_status in ['confirmed', 'complete']:
self._set_done()
confirmed_orders = self._check_amount_and_confirm_order()
confirmed_orders._send_order_confirmation_mail()
elif self.btcpay_status in ['new']:
self.btcpay_invoiceId = notification_data.get('invoiceID')
elif self.btcpay_status in ['cancel','cancelled']:
self._set_canceled()
elif self.btcpay_status in ['invalid']:
_logger.info(
"received data with invalid payment status (%s) for transaction with reference %s",
self.btcpay_status, self.reference
)
self._set_error(
"BTCPay: " + _("Received data with invalid payment status: %s", self.btcpay_status)
)
+1
View File
@@ -0,0 +1 @@
btcpay-python
Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

@@ -0,0 +1,194 @@
<html xmlns="http://www.w3.org/1999/html">
<body>
<section class="oe_container">
<div class="oe_row oe_spaced">
<h2 class="oe_slogan">BTCPay Server Gateway</h2>
<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_bg_img">
<img src="BTCPay-Odoo-17-featured.png" class="oe_picture oe_screenshot">
</div>
</div>
</div>
<div class="oe_row oe_spaced">
<p class="oe_mt32">
BTCPay Server for Odoo is a revolutionary, self-hosted, open-source payment gateway to accept Bitcoin payments. Our seamless integration with Odoo allows you to connect your self-hosted BTCPay Server and start accepting Bitcoin payments in just a few simple steps.
</p>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<h2 class="oe_slogan">Features</h2>
<div class="oe_span12">
<p class="oe_mt32">
<ul>
<li><strong>Zero fees</strong>: Enjoy a payment gateway with no fees. Yes, really!</li>
<li><strong>Fully automated system</strong>: BTCPay takes care of payments, invoice management and refunds automatically.</li>
<li><strong>Display Bitcoin QR code at checkout</strong>: Enhance customer experience with an easy and secure payment option.</li>
<li><strong>No middlemen or KYC</strong>:
<ul>
<li>Direct, P2P payments (going directly to your wallet)</li>
<li>Say goodbye to intermediaries and tedious paperwork</li>
<li>Transaction information is only shared between you and your customer</li>
</ul>
</li>
<li><strong>Self-hosted infrastructure</strong>: Maintain full control over your payment gateway.</li>
<li><strong>Direct wallet payments</strong>: Be your own bank with a self-custodial service.</li>
<li><strong>Lightning Network</strong> integrated out of the box instant, fast and low cost payments and payouts</li>
<li><strong>Reporting and accounting</strong> CSV exports</li>
<li><strong>Advanced invoice managemen</strong>t and refunding integrated in the WooCommerce UI</li>
<li><strong>Real-time exchange price tracking</strong> for correct payment amounts</li>
<li><strong>Versatile plugin system</strong>:
<ul>
<li>Extend functionality according to your needs</li>
<li>Accept payments in altcoins through various plugins</li>
</ul>
</li>
<li><strong>Elegant checkout design</strong>: Compatible with all Bitcoin wallets and enhanced with your stores logo and branding for a unique UX.</li>
<li><strong>Point-of-sale</strong> integration Accept payments in your physical shops</li>
<li><strong>Multilingual ready</strong>: Serve a global audience right out of the box.</li>
<li><strong>Top-notch privacy and security</strong>: Protect your and your customers data.</li>
<li><strong>Community-driven support</strong>: Get responsive assistance from our dedicated community (<a href="http://chat.btcpayserver.org" rel="nofollow ugc">Mattermost</a> or <a href="https://t.me/btcpayserver" rel="nofollow ugc">Telegram</a>).</li>
</ul>
</p>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<h2 class="oe_slogan">Requirements</h2>
<div class="oe_span12">
<p class="oe_mt32">
<ul>
<li>Odoo 17 running</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><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/CreateStore/" class="">You've a BTCPay store on the instance</a></li>
<li><a href="https://docs.btcpayserver.org/WalletSetup/" class="">You've a wallet connected to your store</a></li>
</ul>
</p>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<h2 class="oe_slogan">Install the module</h2>
<div class="oe_span12">
<p class="oe_mt32">
<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>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>Install dependencies by running `pip install -r requirements.txt` (from inside the `payment_btcpayserver` directory)
<li>Restart Odoo
<li>Go to Apps -> Update Apps List
<li>Remove the "Apps" filter and search for "btcpay"
<li>Click **Activate** button
</ul>
</p>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<h2 class="oe_slogan">Configure BTCPay as payment provider</h2>
<div class="oe_span6">
<p class="oe_mt32">
<ul>
<li>Go to <strong>Website</strong> -> <strong>Configuration</strong> -> <strong>Payment Providers</strong></li>
<li>Search for BTCPay and click on button <strong>Activate</strong></li>
</ul>
<p>In the BTCPay settings form, tab "Credentials":</p>
<ul>
<li>Set field "State" to enabled</li>
<li>Set field "BTCPay Server URL" as test or live URL including https://. Example URL: <a href="https://testnet.demo.btcpayserver.org">https://testnet.demo.btcpayserver.org</a></li>
<li>Get a pairing code from your BTCPay Server store: Settings -> Access Tokens
<ul>
<li>Click on "Create Token" button</li>
<li>Label: enter e.g. "My odoo store"</li>
<li>Public Key: leave empty</li>
<li>Click on "Request Pairing" button, on next page click "Approve" button</li>
<li>At the top copy the code next to "Server initiated pairing code", e.g. "hg7z8wN"</li>
</ul>
</li>
<li>Back in Odoo, paste the code into "Pairing Code" field</li>
<li>Hit Tab key on your keyboard (or click on another field) and the pairing process will start automatically</li>
<li>When the pairing is successful the "Token" and "Private Key" field will be filled automatically</li>
<li>Field Facade, keep default 'merchant'.</li>
</ul>
<p>On the tab "Configuration":</p>
<ul>
<li>Make sure field "Payment Journal" is set to "Bank", otherwise you can click the dropdown and click on the suggestion "Bank"</li>
<li>Now you can <strong>save</strong> the settings</li>
</ul>
<p>Check the payment method is enabled:</p>
<ul>
<li>Go to <strong>Website</strong> -> <strong>Configuration</strong> -> <strong>Payment Methods</strong></li>
<li>Make sure "Pay with Bitcoin / Lightning Network" is active</li>
</ul>
<p>Congrats, all done. Do some testing to be sure all works.</p>
</p>
</div>
<div class="oe_span6">
<div class="oe_bg_img">
<img src="BTCPayPaymentSettings.png" class="oe_picture oe_screenshot">
</div>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<h2 class="oe_slogan">How it looks like?</h2>
<div class="oe_span6">
<div class="oe_bg_img">
<img src="BTCPayLooksLike.png" class="oe_picture oe_screenshot">
</div>
</div>
<div class="oe_span6">
<p class="oe_mt32">
<ul>
In payment webpage where payment methods appear, you will find new payment method called BTCPay.
If you click on it you will be redirect to the server that you indicate in location field.
</ul>
</p>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<h2 class="oe_slogan">Transaction BTCPay Details</h2>
<div class="oe_span6">
<p class="oe_mt32">
<ul>
In transaction object, you will find more technical information about this method of payment:
<li>Transaction Id: cryptocurrency transaction hash for the executed payout.</li>
<li>Invoice Id: the id of the invoice for which you want to fetch an event token</li>
<li>Transaction Status: That indicates state of transaction</li>
</ul>
</p>
</div>
<div class="oe_span6">
<div class="oe_bg_img">
<img src="BtcpayTxDetails.png" class="oe_picture oe_screenshot">
</div>
</div>
</div>
</section>
</body>
</html>
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="redirect_form">
<form t-att-action="api_url" method="post">
<input type="hidden" name="reference" t-att-value="item_number"/>
<input type="hidden" name="name" t-att-value="first_name"/>
<input type="hidden" name="email" t-att-value="email"/>
<input type="hidden" name="street" t-att-value="address1"/>
<input type="hidden" name="zip" t-att-value="zip_code"/>
<input type="hidden" name="city" t-att-value="city"/>
<input type="hidden" name="currency_id" t-att-value="currency_code"/>
<input type="hidden" name="country" t-att-value="country"/>
<input type="hidden" name="custom" t-att-value="item_name"/>
<input type="hidden" name="amount" t-att-value="amount"/>
<input type="hidden" name="notify_url" t-att-value="notify_url"/>
<button type="submit" width="100px" t-att-class="submit_class">
<img t-if="not submit_txt" src="/static/description/icon.png"/>
<span t-if="submit_txt"> <t t-esc="submit_txt"/> <span class="fa fa-long-arrow-right"/>
</span>
</button>
</form>
</template>
</odoo>
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="payment_provider_form" model="ir.ui.view">
<field name="name">BTCPay Provider Form</field>
<field name="model">payment.provider</field>
<field name="inherit_id" ref="payment.payment_provider_form"/>
<field name="arch" type="xml">
<group name="provider_credentials" position='inside'>
<group invisible="code != 'btcpayserver'">
<field name="btcpay_location"/>
<field name="btcpay_pairingCode"/>
</group>
<group invisible="code != 'btcpayserver'">
<field name="btcpay_token"/>
<field name="btcpay_privateKey"/>
<field name="btcpay_facade"/>
</group>
</group>
</field>
</record>
</odoo>
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="payment_transaction_form" model="ir.ui.view">
<field name="name">BTCPay Transaction Form</field>
<field name="model">payment.transaction</field>
<field name="inherit_id" ref="payment.payment_transaction_form"/>
<field name="arch" type="xml">
<field name="provider_reference" position="after">
<field name="btcpay_txid"/>
<field name="btcpay_invoiceId" />
<field name="btcpay_status"/>
</field>
</field>
</record>
</odoo>