Skip to content

Commit 84592d7

Browse files
committed
Handle invoice expiry, display timer, minor design improvments
1 parent 20b9b23 commit 84592d7

File tree

6 files changed

+70
-25
lines changed

6 files changed

+70
-25
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ That's it! The "Bitcoin Lightning" payment option should now be available in you
1919

2020
<img src="https://i.imgur.com/Q67y5l2.png" width="45%"></img>
2121
<img src="https://i.imgur.com/958Bm64.png" width="45%"></img>
22-
<img src="https://i.imgur.com/I6zP72M.png" width="45%"></img>
22+
<img src="https://i.imgur.com/QbWiks1.png" width="45%"></img>
2323
<a href="https://i.imgur.com/UBCdmLR.png"><img src="https://i.imgur.com/JgwuFSl.png" width="45%"></img></a>
2424

2525
## License

build.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
#!/bin/sh
22
composer install --no-dev
3-
zip -r woocommerce-gateway-lightning.zip composer.json woocommerce-gateway-lightning.php vendor templates css --exclude='vendor/bacon/bacon-qr-code/tests/*'
3+
zip -r woocommerce-gateway-lightning.zip composer.json woocommerce-gateway-lightning.php vendor templates css img --exclude='vendor/bacon/bacon-qr-code/tests/*'
44

css/payment.css

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1-
.order_details {
2-
display: none; /* Hide WooCommerce default payment details */
1+
/* Hide WooCommerce default title payment details */
2+
header.entry-header, .order_details {
3+
display: none;
4+
}
5+
6+
.woocommerce-breadcrumb {
7+
margin-bottom: 0;
38
}
49

510
.ln-pay { margin-bottom: 2em; }
@@ -28,6 +33,14 @@
2833
padding: 0.75em;
2934
}
3035

36+
.ln-pay p {
37+
margin: 1em 0;
38+
}
39+
40+
.ln-pay .loader {
41+
display: inline;
42+
}
43+
3144
@media (max-width: 550px) {
3245
.ln-pay { text-align: center; }
3346
.ln-pay .qr { float: none; margin: 0 auto; }

img/loader.gif

673 Bytes
Loading

templates/payment.php

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
11
<link rel="stylesheet" href="<?php echo plugins_url('css/payment.css', dirname(__FILE__))?>" type="text/css">
2+
<noscript><style>.yesscript{display:none}</style></noscript>
3+
4+
<?php $expiry_datestr = date('r', $invoice->expires_at); ?>
25

36
<div class="ln-pay">
4-
<h4>
5-
<strong>Pay <?php echo $order->get_formatted_order_total() ?> with Lightning</strong>
6-
(<?php echo number_format($invoice->msatoshi/100000000, 8) ?> mBTC)
7-
</h4>
7+
<h1>Pay with Lightning</h1>
8+
<h3><?php echo $order->get_formatted_order_total() ?> = <?php echo number_format($invoice->msatoshi/100000000, 8) ?> mBTC</h3>
89
<img class="qr" src="<?php echo $qr_uri ?>">
9-
<div class="payreq">
10-
<code><?php echo $invoice->payreq ?></code>
11-
<a class="checkout-button button alt" href="lightning:<?php echo $invoice->payreq ?>">Pay with Lightning</a>
12-
</div>
13-
10+
<code class="payreq"><?php echo $invoice->payreq ?></code>
11+
<p>
12+
<noscript>Your browser has JavaScript turned off. Please refresh the page manually after making the payment.</noscript>
13+
<span class="yesscript"><img src="<?php echo plugins_url( '../img/loader.gif', __FILE__ ) ?>" class="loader" alt="loading"> Awaiting payment.</span>
14+
The invoice expires <span id="expiry-timer" title="<?php echo $expiry_datestr ?>"><?php echo $expiry_datestr ?></span>.
15+
</p>
16+
<a class="checkout-button button alt" href="lightning:<?php echo $invoice->payreq ?>">Pay with Lightning</a>
1417
</div>
1518

1619
<script>
17-
(function($, ajax_url, invoice_id, redir_url){
20+
(function($, ajax_url, invoice_id, redir_url, expires_at){
1821
$(function poll() {
1922
$.post(ajax_url, { action: 'ln_wait_invoice', invoice_id: invoice_id })
2023
.success((code, state, res) => {
@@ -24,16 +27,30 @@
2427
throw new Error('succesful response, but not the expected one')
2528
})
2629
.fail(res => {
27-
// immediatly re-poll on 402 Payment Required
30+
// 402 Payment Required: timeout reached without payment, invoice is still payable
2831
if (res.status === 402) return poll()
32+
// 410 Gone: invoice expired and can not longer be paid
33+
if (res.status === 410) return location.reload()
2934

3035
// for unknown errors, wait for a little while, then try again
3136
setTimeout(poll, 10000);
3237
throw new Error('unexpected status code '+res.status)
3338
})
3439
})
40+
41+
;(function updateExpiry() {
42+
var left = expires_at - (+new Date()/1000|0)
43+
if (left <= 0) return location.reload()
44+
$('#expiry-timer').text('in '+formatDur(left))
45+
setTimeout(updateExpiry, 1000)
46+
})()
47+
48+
function formatDur(x) {
49+
var h=x/3600|0, m=x%3600/60|0, s=x%60
50+
return ''+(h>0?h+':':'')+(m<10&&h>0?'0':'')+m+':'+(s<10?'0':'')+s
51+
}
3552
})(jQuery, <?php echo json_encode(admin_url( 'admin-ajax.php' )) ?>, <?php echo json_encode($invoice->id) ?>,
36-
<?php echo json_encode($order->get_checkout_order_received_url()) ?>)
53+
<?php echo json_encode($order->get_checkout_order_received_url()) ?>, <?php echo $invoice->expires_at ?>)
3754

3855
</script>
3956

woocommerce-gateway-lightning.php

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -146,13 +146,14 @@ public function webhook_callback() {
146146
* JSON endpoint for long polling payment updates.
147147
*/
148148
public function wait_invoice() {
149-
$invoice = $this->charge->wait($_POST['invoice_id'], LIGHTNING_LONGPOLL_TIMEOUT);
150-
if ($invoice && $invoice->completed) {
151-
$order = wc_get_order($invoice->metadata->order_id);
152-
$this->update_invoice($order, $invoice);
149+
$paid_inv = $this->charge->wait($_POST['invoice_id'], LIGHTNING_LONGPOLL_TIMEOUT);
150+
151+
if ($paid_inv) {
152+
$order = wc_get_order($paid_inv->metadata->order_id);
153+
$this->update_invoice($order, $paid_inv);
153154
wp_send_json(true);
154155
} else {
155-
status_header(402);
156+
status_header($paid_inv === false ? 410 : 402);
156157
wp_send_json(false);
157158
}
158159
}
@@ -164,17 +165,29 @@ public function show_payment_info($order_id) {
164165
global $wp;
165166

166167
$order = wc_get_order($order_id);
167-
$invoice = $order->get_meta('_lightning_invoice');
168168

169169
if (!empty($wp->query_vars['order-received']) && $order->needs_payment()) {
170+
// thankyou page requested, but order is still unpaid
171+
wp_redirect($order->get_checkout_payment_url(true));
172+
exit;
173+
}
174+
175+
$invoice = $order->get_meta('_lightning_invoice');
176+
if ($invoice->status == 'unpaid') {
177+
$invoice = $this->charge->fetch($invoice->id);
178+
$this->update_invoice($order, $invoice);
179+
}
180+
181+
if ($order->has_status('cancelled')) {
182+
// invoice expired, reload page to display expiry message
170183
wp_redirect($order->get_checkout_payment_url(true));
171184
exit;
172185
}
173186

174187
if ($order->needs_payment()) {
175188
$qr_uri = self::get_qr_uri($invoice);
176189
require __DIR__.'/templates/payment.php';
177-
} else {
190+
} elseif ($order->has_status(array('processing', 'completed'))) {
178191
require __DIR__.'/templates/completed.php';
179192
}
180193
}
@@ -191,8 +204,10 @@ protected function update_invoice($order, $invoice) {
191204
$order->update_meta_data('_lightning_invoice', $invoice);
192205
$order->save_meta_data();
193206

194-
if ($order->needs_payment() && $invoice->completed) {
195-
$order->payment_complete();
207+
if ($invoice->status == 'paid' && $order->needs_payment()) {
208+
$order->payment_complete($invoice->id);
209+
} else if ($invoice->status == 'expired' && $order->has_status(array('pending', 'on-hold'))) {
210+
$order->update_status('cancelled', 'Lightning invoice expired');
196211
}
197212
}
198213

0 commit comments

Comments
 (0)