forked from 3wordchant/capsul-flask
added btcpay pairing instructions to readme
This commit is contained in:
parent
63a902774e
commit
58f85edcb4
1
Pipfile
1
Pipfile
@ -28,6 +28,7 @@ stripe = "*"
|
|||||||
matplotlib = "*"
|
matplotlib = "*"
|
||||||
requests = "*"
|
requests = "*"
|
||||||
python-dotenv = "*"
|
python-dotenv = "*"
|
||||||
|
bitpay = "*"
|
||||||
|
|
||||||
[dev-packages]
|
[dev-packages]
|
||||||
|
|
||||||
|
16
Pipfile.lock
generated
16
Pipfile.lock
generated
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"_meta": {
|
"_meta": {
|
||||||
"hash": {
|
"hash": {
|
||||||
"sha256": "4f61804f9405ff8f66e41739aeac24a2577f7b64f7d08b93459b568528c4f494"
|
"sha256": "51691e6158d1c309027d595bc4d26079c368f983223f7a567688dd5a98c865fa"
|
||||||
},
|
},
|
||||||
"pipfile-spec": 6,
|
"pipfile-spec": 6,
|
||||||
"requires": {
|
"requires": {
|
||||||
@ -24,6 +24,13 @@
|
|||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==2.4.1"
|
"version": "==2.4.1"
|
||||||
},
|
},
|
||||||
|
"bitpay": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:3da21326e5a7e98fae93f7fe4c1b046993cf1d8fba60a6c5049cc15f30026b75"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==2.6.1910"
|
||||||
|
},
|
||||||
"blinker": {
|
"blinker": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"
|
"sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"
|
||||||
@ -60,6 +67,13 @@
|
|||||||
],
|
],
|
||||||
"version": "==0.10.0"
|
"version": "==0.10.0"
|
||||||
},
|
},
|
||||||
|
"ecdsa": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:867ec9cf6df0b03addc8ef66b56359643cb5d0c1dc329df76ba7ecfe256c8061",
|
||||||
|
"sha256:8f12ac317f8a1318efa75757ef0a651abe12e51fc1af8838fb91079445227277"
|
||||||
|
],
|
||||||
|
"version": "==0.15"
|
||||||
|
},
|
||||||
"flask": {
|
"flask": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:4efa1ae2d7c9865af48986de8aeb8504bf32c7f3d6fdc9353d34b21f4b127060",
|
"sha256:4efa1ae2d7c9865af48986de8aeb8504bf32c7f3d6fdc9353d34b21f4b127060",
|
||||||
|
61
README.md
61
README.md
@ -45,9 +45,8 @@ Run the app
|
|||||||
FLASK_APP=capsulflask flask run
|
FLASK_APP=capsulflask flask run
|
||||||
```
|
```
|
||||||
|
|
||||||
Run the app in gunicorn locally
|
Run the app in gunicorn
|
||||||
```
|
```
|
||||||
pip install gunicorn
|
|
||||||
.venv/bin/gunicorn --bind 127.0.0.1:5000 capsulflask:app
|
.venv/bin/gunicorn --bind 127.0.0.1:5000 capsulflask:app
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -61,3 +60,61 @@ For example, the script named `02_up_xyz.sql` should contain code that migrates
|
|||||||
**IMPORTANT: if you need to make changes to the schema, make a NEW schema version. DO NOT EDIT the existing schema versions.**
|
**IMPORTANT: if you need to make changes to the schema, make a NEW schema version. DO NOT EDIT the existing schema versions.**
|
||||||
|
|
||||||
In general, for safety, schema version upgrades should not delete data. Schema version downgrades will simply throw an error and exit for now.
|
In general, for safety, schema version upgrades should not delete data. Schema version downgrades will simply throw an error and exit for now.
|
||||||
|
|
||||||
|
|
||||||
|
## how to setup btcpay server
|
||||||
|
|
||||||
|
Generate a private key and the accompanying bitpay SIN for the bitpay API client.
|
||||||
|
|
||||||
|
I used this code as an example: https://github.com/bitpay/bitpay-python/blob/master/bitpay/key_utils.py#L6
|
||||||
|
|
||||||
|
```
|
||||||
|
$ python ./readme/generate_btcpay_keys.py
|
||||||
|
```
|
||||||
|
|
||||||
|
It should output something looking like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
-----BEGIN EC PRIVATE KEY-----
|
||||||
|
EXAMPLEIArx/EXAMPLEKH23EXAMPLEsYXEXAMPLE5qdEXAMPLEcFHoAcEXAMPLEK
|
||||||
|
oUQDQgAEnWs47PT8+ihhzyvXX6/yYMAWWODluRTR2Ix6ZY7Z+MV7v0W1maJzqeqq
|
||||||
|
NQ+cpBvPDbyrDk9+Uf/sEaRCma094g==
|
||||||
|
-----END EC PRIVATE KEY-----
|
||||||
|
|
||||||
|
|
||||||
|
EXAMPLEwzAEXAMPLEEXAMPLEURD7EXAMPLE
|
||||||
|
```
|
||||||
|
|
||||||
|
In order to register the key with the btcpay server, you have to first generate a pairing token using the btcpay server interface.
|
||||||
|
This requires your btcpay server account to have access to the capsul store. Ask Cass about this.
|
||||||
|
|
||||||
|
Navigate to `Manage store: Access Tokens` at: `https://btcpay.cyberia.club/stores/<store-id>/Tokens`
|
||||||
|
|
||||||
|
![](readme/btcpay_sin_pairing.jpg)
|
||||||
|
|
||||||
|
|
||||||
|
Finally, send an http request to the btcpay server to complete the pairing:
|
||||||
|
|
||||||
|
```
|
||||||
|
curl -H "Content-Type: application/json" https://btcpay.cyberia.club/tokens -d "{'id': 'EXAMPLEwzAEXAMPLEEXAMPLEURD7EXAMPLE', 'pairingCode': 'XXXXXXX'}"
|
||||||
|
```
|
||||||
|
|
||||||
|
It should respond with a token:
|
||||||
|
|
||||||
|
```
|
||||||
|
{"data":[{"policies":[],"pairingCode":"XXXXXXX","pairingExpiration":1589473817597,"dateCreated":1589472917597,"facade":"merchant","token":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx","label":"capsulflask"}]}
|
||||||
|
```
|
||||||
|
|
||||||
|
And you should see the token in the btcpay server UI:
|
||||||
|
|
||||||
|
![](readme/paired.jpg)
|
||||||
|
|
||||||
|
Now simply set your BTCPAY_PRIVATE_KEY private key in `.env`
|
||||||
|
|
||||||
|
```
|
||||||
|
BTCPAY_PRIVATE_KEY='-----BEGIN EC PRIVATE KEY-----
|
||||||
|
EXAMPLEIArx/EXAMPLEKH23EXAMPLEsYXEXAMPLE5qdEXAMPLEcFHoAcEXAMPLEK
|
||||||
|
oUQDQgAEnWs47PT8+ihhzyvXX6/yYMAWWODluRTR2Ix6ZY7Z+MV7v0W1maJzqeqq
|
||||||
|
NQ+cpBvPDbyrDk9+Uf/sEaRCma094g==
|
||||||
|
-----END EC PRIVATE KEY-----'
|
||||||
|
```
|
@ -28,8 +28,10 @@ app.config.from_mapping(
|
|||||||
|
|
||||||
STRIPE_API_VERSION=os.environ.get("STRIPE_API_VERSION", default="2020-03-02"),
|
STRIPE_API_VERSION=os.environ.get("STRIPE_API_VERSION", default="2020-03-02"),
|
||||||
STRIPE_SECRET_KEY=os.environ.get("STRIPE_SECRET_KEY", default=""),
|
STRIPE_SECRET_KEY=os.environ.get("STRIPE_SECRET_KEY", default=""),
|
||||||
STRIPE_PUBLISHABLE_KEY=os.environ.get("STRIPE_PUBLISHABLE_KEY", default="")
|
STRIPE_PUBLISHABLE_KEY=os.environ.get("STRIPE_PUBLISHABLE_KEY", default=""),
|
||||||
#STRIPE_WEBHOOK_SECRET=os.environ.get("STRIPE_WEBHOOK_SECRET", default="")
|
#STRIPE_WEBHOOK_SECRET=os.environ.get("STRIPE_WEBHOOK_SECRET", default="")
|
||||||
|
|
||||||
|
BTCPAY_PRIVATE_KEY=os.environ.get("BTCPAY_PRIVATE_KEY", default="")
|
||||||
)
|
)
|
||||||
|
|
||||||
stripe.api_key = app.config['STRIPE_SECRET_KEY']
|
stripe.api_key = app.config['STRIPE_SECRET_KEY']
|
||||||
|
BIN
readme/btcpay_sin_pairing.jpg
Normal file
BIN
readme/btcpay_sin_pairing.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 35 KiB |
47
readme/generate_btcpay_keys.py
Normal file
47
readme/generate_btcpay_keys.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
from ecdsa import SigningKey, SECP256k1, VerifyingKey
|
||||||
|
import binascii
|
||||||
|
import hashlib
|
||||||
|
|
||||||
|
def sha_digest(hexastring):
|
||||||
|
return hashlib.sha256(binascii.unhexlify(hexastring)).hexdigest()
|
||||||
|
|
||||||
|
def base58encode(hexastring):
|
||||||
|
chars = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
|
||||||
|
int_val = int(hexastring, 16)
|
||||||
|
encoded = encode58("", int_val, chars)
|
||||||
|
return encoded
|
||||||
|
|
||||||
|
def encode58(string, int_val, chars):
|
||||||
|
if int_val == 0:
|
||||||
|
return string
|
||||||
|
else:
|
||||||
|
new_val, rem = divmod(int_val, 58)
|
||||||
|
new_string = (chars[rem]) + string
|
||||||
|
return encode58(new_string, new_val, chars)
|
||||||
|
|
||||||
|
sk = SigningKey.generate(curve=SECP256k1)
|
||||||
|
pem = sk.to_pem()
|
||||||
|
pem = pem.decode("utf-8")
|
||||||
|
|
||||||
|
print("")
|
||||||
|
print(pem)
|
||||||
|
print("")
|
||||||
|
|
||||||
|
public_key = SigningKey.from_pem(pem).get_verifying_key().to_string()
|
||||||
|
public_key_hex = binascii.hexlify(public_key)
|
||||||
|
checksum_int = int(public_key_hex, 16)
|
||||||
|
if(checksum_int % 2 == 0):
|
||||||
|
prefix = "02"
|
||||||
|
else:
|
||||||
|
prefix = "03"
|
||||||
|
public_key_compressed = prefix + public_key_hex[0:64].decode("utf-8")
|
||||||
|
hash_of_public_key = sha_digest(public_key_compressed)
|
||||||
|
ripe_hash_of_public_key = hashlib.new("ripemd160")
|
||||||
|
ripe_hash_of_public_key.update(binascii.unhexlify(hash_of_public_key))
|
||||||
|
version_hash = "0F02"+ripe_hash_of_public_key.hexdigest()
|
||||||
|
version_checksum = sha_digest(sha_digest(version_hash))[0:8]
|
||||||
|
btcpay_sin = base58encode(version_hash+version_checksum)
|
||||||
|
|
||||||
|
print("")
|
||||||
|
print(btcpay_sin)
|
||||||
|
print("")
|
BIN
readme/paired.jpg
Normal file
BIN
readme/paired.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
Loading…
Reference in New Issue
Block a user