mirror of
https://github.com/lnbits/lnbits.git
synced 2025-10-11 04:52:34 +02:00
Get entire flow working
This commit is contained in:
@@ -3,79 +3,50 @@
|
|||||||
<div class="col-12 col-md-7 col-lg-6 q-gutter-y-md">
|
<div class="col-12 col-md-7 col-lg-6 q-gutter-y-md">
|
||||||
<q-card class="q-pa-lg">
|
<q-card class="q-pa-lg">
|
||||||
<q-card-section class="q-pa-none">
|
<q-card-section class="q-pa-none">
|
||||||
<h3 class="q-my-none">Donate Bitcoin to {{ twitchuser }}!</h3>
|
<h5 class="q-my-none">Donate Bitcoin to {{ twitchuser }}</h5>
|
||||||
<br />
|
<br />
|
||||||
<q-form @submit="Invoice()" class="q-gutter-md">
|
<q-form @submit="Invoice()" class="q-gutter-md">
|
||||||
<q-input
|
<q-input
|
||||||
filled
|
filled
|
||||||
dense
|
dense
|
||||||
v-model.trim="formDialog.data.name"
|
v-model.trim="donationDialog.data.name"
|
||||||
type="name"
|
type="name"
|
||||||
label="Your Name"
|
label="Your Name (leave blank for Anonymous donation)"
|
||||||
></q-input>
|
></q-input>
|
||||||
<q-input
|
<q-input
|
||||||
filled
|
filled
|
||||||
dense
|
dense
|
||||||
v-model.trim="formDialog.data.amount"
|
v-model.number="donationDialog.data.sats"
|
||||||
type="number"
|
type="number"
|
||||||
|
min=1
|
||||||
|
suffix=sats
|
||||||
|
:rules="[val => val > 0 || 'Choose a positive number of sats!']"
|
||||||
label="Amount of sats"
|
label="Amount of sats"
|
||||||
></q-input>
|
></q-input>
|
||||||
<q-input
|
<q-input
|
||||||
filled
|
filled
|
||||||
dense
|
dense
|
||||||
v-model.number="formDialog.data.text"
|
v-model.trim="donationDialog.data.message"
|
||||||
type="textarea"
|
type="textarea"
|
||||||
label="Donation Message"
|
label="Donation Message (you can leave this blank too)"
|
||||||
></q-input>
|
></q-input>
|
||||||
<p>{% raw %}{{amountWords}}{% endraw %}</p>
|
|
||||||
<div class="row q-mt-lg">
|
<div class="row q-mt-lg">
|
||||||
<q-btn
|
<q-btn
|
||||||
unelevated
|
unelevated
|
||||||
color="deep-purple"
|
color="deep-purple"
|
||||||
:disable="formDialog.data.name == '' || formDialog.data.text == ''"
|
:disable="donationDialog.data.sats < 1 || !donationDialog.data.sats"
|
||||||
type="submit"
|
type="submit"
|
||||||
>Submit</q-btn
|
>Submit</q-btn
|
||||||
>
|
>
|
||||||
<q-btn @click="resetForm" flat color="grey" class="q-ml-auto"
|
|
||||||
>Cancel</q-btn
|
|
||||||
>
|
|
||||||
</div>
|
</div>
|
||||||
</q-form>
|
</q-form>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
</q-card>
|
</q-card>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<q-dialog v-model="receive.show" position="top" @hide="closeReceiveDialog">
|
|
||||||
<q-card
|
|
||||||
v-if="!receive.paymentReq"
|
|
||||||
class="q-pa-lg q-pt-xl lnbits__dialog-card"
|
|
||||||
>
|
|
||||||
</q-card>
|
|
||||||
<q-card v-else class="q-pa-lg q-pt-xl lnbits__dialog-card">
|
|
||||||
<div class="text-center q-mb-lg">
|
|
||||||
<a :href="'lightning:' + receive.paymentReq">
|
|
||||||
<q-responsive :ratio="1" class="q-mx-xl">
|
|
||||||
<qrcode
|
|
||||||
:value="paymentReq"
|
|
||||||
:options="{width: 340}"
|
|
||||||
class="rounded-borders"
|
|
||||||
></qrcode>
|
|
||||||
</q-responsive>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div class="row q-mt-lg">
|
|
||||||
<q-btn outline color="grey" @click="copyText(receive.paymentReq)"
|
|
||||||
>Copy invoice</q-btn
|
|
||||||
>
|
|
||||||
<q-btn v-close-popup flat color="grey" class="q-ml-auto">Close</q-btn>
|
|
||||||
</div>
|
|
||||||
</q-card>
|
|
||||||
</q-dialog>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endblock %} {% block scripts %}
|
{% endblock %} {% block scripts %}
|
||||||
<script>
|
<script>
|
||||||
console.log('{{ form_costpword }}')
|
|
||||||
Vue.component(VueQrcode.name, VueQrcode)
|
Vue.component(VueQrcode.name, VueQrcode)
|
||||||
|
|
||||||
new Vue({
|
new Vue({
|
||||||
@@ -85,12 +56,12 @@
|
|||||||
return {
|
return {
|
||||||
paymentReq: null,
|
paymentReq: null,
|
||||||
redirectUrl: null,
|
redirectUrl: null,
|
||||||
formDialog: {
|
donationDialog: {
|
||||||
show: false,
|
show: false,
|
||||||
data: {
|
data: {
|
||||||
name: '',
|
name: '',
|
||||||
email: '',
|
sats: '',
|
||||||
text: ''
|
message: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
receive: {
|
receive: {
|
||||||
@@ -100,93 +71,21 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
|
||||||
amountWords() {
|
|
||||||
var regex = /\s+/gi
|
|
||||||
var nwords = this.formDialog.data.text
|
|
||||||
.trim()
|
|
||||||
.replace(regex, ' ')
|
|
||||||
.split(' ').length
|
|
||||||
var sats = nwords * parseInt('{{ form_costpword }}')
|
|
||||||
if (sats === parseInt('{{ form_costpword }}')) {
|
|
||||||
return '0 Sats to pay'
|
|
||||||
} else {
|
|
||||||
this.formDialog.data.sats = sats
|
|
||||||
return sats + ' Sats to pay'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
resetForm: function (e) {
|
|
||||||
e.preventDefault()
|
|
||||||
this.formDialog.data.name = ''
|
|
||||||
this.formDialog.data.email = ''
|
|
||||||
this.formDialog.data.text = ''
|
|
||||||
},
|
|
||||||
|
|
||||||
closeReceiveDialog: function () {
|
|
||||||
var checker = this.receive.paymentChecker
|
|
||||||
dismissMsg()
|
|
||||||
|
|
||||||
clearInterval(paymentChecker)
|
|
||||||
setTimeout(function () {}, 10000)
|
|
||||||
},
|
|
||||||
Invoice: function () {
|
Invoice: function () {
|
||||||
var self = this
|
var self = this
|
||||||
axios
|
axios
|
||||||
.post('/lnticket/api/v1/tickets/{{ form_id }}', {
|
.post('/twitchalerts/api/v1/donations', {
|
||||||
form: '{{ form_id }}',
|
service: {{ service }},
|
||||||
name: self.formDialog.data.name,
|
name: self.donationDialog.data.name,
|
||||||
email: self.formDialog.data.email,
|
sats: self.donationDialog.data.sats,
|
||||||
ltext: self.formDialog.data.text,
|
message: self.donationDialog.data.message
|
||||||
sats: self.formDialog.data.sats
|
|
||||||
})
|
})
|
||||||
.then(function (response) {
|
.then(function (response) {
|
||||||
self.paymentReq = response.data.payment_request
|
self.redirect_url = response.data.redirect_url
|
||||||
self.paymentCheck = response.data.payment_hash
|
console.log(self.redirect_url)
|
||||||
|
window.location.href = self.redirect_url
|
||||||
dismissMsg = self.$q.notify({
|
|
||||||
timeout: 0,
|
|
||||||
message: 'Waiting for payment...'
|
|
||||||
})
|
|
||||||
|
|
||||||
self.receive = {
|
|
||||||
show: true,
|
|
||||||
status: 'pending',
|
|
||||||
paymentReq: self.paymentReq
|
|
||||||
}
|
|
||||||
|
|
||||||
paymentChecker = setInterval(function () {
|
|
||||||
axios
|
|
||||||
.get('/lnticket/api/v1/tickets/' + self.paymentCheck)
|
|
||||||
.then(function (res) {
|
|
||||||
if (res.data.paid) {
|
|
||||||
clearInterval(paymentChecker)
|
|
||||||
self.receive = {
|
|
||||||
show: false,
|
|
||||||
status: 'complete',
|
|
||||||
paymentReq: null
|
|
||||||
}
|
|
||||||
dismissMsg()
|
|
||||||
|
|
||||||
self.formDialog.data.name = ''
|
|
||||||
self.formDialog.data.email = ''
|
|
||||||
self.formDialog.data.text = ''
|
|
||||||
self.$q.notify({
|
|
||||||
type: 'positive',
|
|
||||||
message: 'Sent, thank you!',
|
|
||||||
icon: 'thumb_up'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(function (error) {
|
|
||||||
LNbits.utils.notifyApiError(error)
|
|
||||||
})
|
|
||||||
}, 2000)
|
|
||||||
})
|
|
||||||
.catch(function (error) {
|
|
||||||
LNbits.utils.notifyApiError(error)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -96,19 +96,19 @@ async def api_authenticate_service(service_id):
|
|||||||
|
|
||||||
|
|
||||||
@twitchalerts_ext.route("/api/v1/donations", methods=["POST"])
|
@twitchalerts_ext.route("/api/v1/donations", methods=["POST"])
|
||||||
@api_check_wallet_key("invoice")
|
|
||||||
@api_validate_post_request(
|
@api_validate_post_request(
|
||||||
schema={
|
schema={
|
||||||
"name": {"type": "string"},
|
"name": {"type": "string"},
|
||||||
"sats": {"type": "integer", "required": True},
|
"sats": {"type": "integer", "required": True},
|
||||||
"service": {"type": "integer", "required": True},
|
"service": {"type": "integer", "required": True},
|
||||||
"cur_code": {"type": "string", "required": True},
|
"message": {"type": "string"}
|
||||||
"amount": {"type": "float", "required": True}
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
async def api_create_donation():
|
async def api_create_donation():
|
||||||
"""Takes data from donation form and creates+returns SatsPay charge"""
|
"""Takes data from donation form and creates+returns SatsPay charge"""
|
||||||
price = await btc_price("USD")
|
cur_code = "USD"
|
||||||
|
price = await btc_price(cur_code)
|
||||||
|
message = g.data.get("message", "")
|
||||||
amount = g.data["sats"] * (10 ** (-8)) * price
|
amount = g.data["sats"] * (10 ** (-8)) * price
|
||||||
webhook_base = request.scheme + "://" + request.headers["Host"]
|
webhook_base = request.scheme + "://" + request.headers["Host"]
|
||||||
service_id = g.data["service"]
|
service_id = g.data["service"]
|
||||||
@@ -124,13 +124,17 @@ async def api_create_donation():
|
|||||||
await create_donation(
|
await create_donation(
|
||||||
id=charge.id,
|
id=charge.id,
|
||||||
wallet=service.wallet,
|
wallet=service.wallet,
|
||||||
|
message=message,
|
||||||
name=name,
|
name=name,
|
||||||
cur_code=g.data["cur_code"],
|
cur_code=cur_code,
|
||||||
sats=g.data["sats"],
|
sats=g.data["sats"],
|
||||||
amount=amount,
|
amount=amount,
|
||||||
service=g.data["service"],
|
service=g.data["service"],
|
||||||
)
|
)
|
||||||
return redirect(f"/satspay/{charge.id}")
|
return (
|
||||||
|
jsonify({"redirect_url": f"/satspay/{charge.id}"}),
|
||||||
|
HTTPStatus.OK
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@twitchalerts_ext.route("/api/v1/postdonation", methods=["POST"])
|
@twitchalerts_ext.route("/api/v1/postdonation", methods=["POST"])
|
||||||
|
Reference in New Issue
Block a user