Merge pull request #108 from breez/webhooks

Webhooks documentation.
This commit is contained in:
Roei Erez
2023-12-17 14:42:44 +02:00
committed by GitHub
12 changed files with 394 additions and 2 deletions

View File

@@ -1,6 +1,6 @@
using Breez.Sdk;
public class ServiceStatusSnippets
public class WebhooksSnippets
{
public void HealthCheckStatus(BlockingBreezServices sdk)
{

View File

@@ -0,0 +1,32 @@
using Breez.Sdk;
public class ServiceStatusSnippets
{
public void Webhook(BlockingBreezServices sdk)
{
// ANCHOR: register-webook
try
{
sdk.RegisterWebhook("https://yourapplication.com");
}
catch (Exception)
{
// Handle error
}
// ANCHOR_END: register-webook
}
public void PaymentWebhook(BlockingBreezServices sdk)
{
// ANCHOR: register-payment-webook
try
{
sdk.RegisterWebhook("https://your-nds-service.com/notify?platform=ios&token=<PUSH_TOKEN>");
}
catch (Exception)
{
// Handle error
}
// ANCHOR_END: register-payment-webook
}
}

View File

@@ -0,0 +1,13 @@
import 'package:breez_sdk/breez_sdk.dart';
Future<void> webhook() async {
// ANCHOR: register-webook
await BreezSDK().registerWebhook(webhookUrl: "https://yourapplication.com");
// ANCHOR_END: register-webook
}
Future<void> paymentWebhook({required String paymentHash}) async {
// ANCHOR: register-payment-webook
await BreezSDK().registerWebhook(webhookUrl: "https://your-nds-service.com/notify?platform=ios&token=<PUSH_TOKEN>");
// ANCHOR_END: register-payment-webook
}

21
snippets/go/webhook.go Normal file
View File

@@ -0,0 +1,21 @@
package example
import (
"log"
)
func Webhook() {
// ANCHOR: register-webook
if err := sdk.RegisterWebhook("https://yourapplication.com"); err != nil {
log.Printf("Webhook registration failed: %v", err)
}
// ANCHOR_END: register-webook
}
func PaymentWebhook() {
// ANCHOR: register-payment-webook
if err := sdk.RegisterWebhook("https://your-nds-service.com/notify?platform=ios&token=<PUSH_TOKEN>"); err != nil {
log.Printf("Webhook registration failed: %v", err)
}
// ANCHOR_END: register-payment-webook
}

View File

@@ -0,0 +1,24 @@
package com.example.kotlinmpplib
import breez_sdk.*
class Webhooks {
fun Webhook(sdk: BlockingBreezServices) {
// ANCHOR: register-webook
try {
sdk.registerWebhook("https://yourapplication.com")
} catch (e: Exception) {
// Handle error
}
// ANCHOR_END: register-webook
}
fun paymentWebhook(sdk: BlockingBreezServices) {
// ANCHOR: register-payment-webook
try {
sdk.registerWebhook("https://your-nds-service.com/notify?platform=ios&token=<PUSH_TOKEN>")
} catch (e: Exception) {
// Handle error
}
// ANCHOR_END: register-payment-webook
}
}

View File

@@ -0,0 +1,19 @@
import breez_sdk
def webhook(sdk_services):
try:
# ANCHOR: register-webook
sdk_services.registerWebhook("https://yourapplication.com")
# ANCHOR_END: register-webook
except Exception as error:
print(error)
raise
def paymentWebhook(sdk_services):
try:
# ANCHOR: register-payment-webook
sdk_services.registerWebhook("https://your-nds-service.com/notify?platform=ios&token=<PUSH_TOKEN>")
# ANCHOR_END: register-payment-webook
except Exception as error:
print(error)
raise

View File

@@ -0,0 +1,13 @@
import { registerWebhook } from '@breeztech/react-native-breez-sdk'
const webhook = async () => {
// ANCHOR: register-webook
await registerWebhook('https://yourapplication.com')
// ANCHOR_END: register-webook
}
const paymentWebhook = async () => {
// ANCHOR: register-payment-webook
await registerWebhook('https://your-nds-service.com/notify?platform=ios&token=<PUSH_TOKEN>')
// ANCHOR_END: register-payment-webook
}

View File

@@ -14,6 +14,7 @@ mod send_payment;
mod send_spontaneous_payment;
mod service_status;
mod static_channel_backup;
mod webhook;
use anyhow::Result;
use breez_sdk_core::*;

View File

@@ -0,0 +1,19 @@
use std::sync::Arc;
use anyhow::Result;
use breez_sdk_core::*;
async fn webhook(sdk: Arc<BreezServices>) -> Result<()> {
// ANCHOR: register-webook
sdk.register_webhook("https://yourapplication.com".to_string()).await?;
// ANCHOR_END: register-webook
Ok(())
}
async fn payment_webhook(sdk: Arc<BreezServices>) -> Result<()> {
// ANCHOR: register-payment-webook
sdk.register_webhook("https://your-nds-service.com/notify?platform=ios&token=<PUSH_TOKEN>".to_string()).await?;
// ANCHOR_END: register-payment-webook
Ok(())
}

View File

@@ -0,0 +1,20 @@
//
// ServiceStatus.swift
//
//
//
import Foundation
import BreezSDK
func webhook(sdk: BlockingBreezServices) throws {
// ANCHOR: register-webook
try sdk.registerWebhook(webhookUrl: "https://yourapplication.com")
// ANCHOR_END: register-webook
}
func paymentWebhook(sdk: BlockingBreezServices) throws {
// ANCHOR: register-payment-webook
try sdk.registerWebhook(webhookUrl: "https://your-nds-service.com/notify?platform=ios&token=<PUSH_TOKEN>")
// ANCHOR_END: register-payment-webook
}

View File

@@ -21,4 +21,5 @@
- [Buy Bitcoin](guide/buy_btc.md)
- [Static Channel Backup](guide/static_channel_backup.md)
- [Service Status](guide/service_status.md)
- [Payment Notifications](guide/payment_notification.md)
- [Moving to Production](guide/production.md)

View File

@@ -0,0 +1,229 @@
# Receiving Payment Notifications via Webhook in Breez SDK
## Overview
The Breez SDK provides a robust feature for applications to receive real-time notifications for incoming payments over the Lightning Network. This is achieved through the use of webhooks. A webhook is a powerful tool that allows your application to be notified via a specified URL when a payment is about to be received.
## Setting Up the Webhook
To utilize this feature, you need to set up a webhook that the LSP can call when a payment is received.
### Step 1: Define Your Webhook URL
First, you need to define the URL endpoint in your application that will handle incoming payment notifications. This URL should be capable of receiving POST requests.
### Step 2: Register the Webhook with Breez
Next, register this URL with the Breez SDK. This step involves calling a specific SDK function.
<custom-tabs category="lang">
<div slot="title">Rust</div>
<section>
```rust,ignore
{{#include ../../snippets/rust/src/webhook.rs:register-webook}}
```
</section>
<div slot="title">Swift</div>
<section>
```swift,ignore
{{#include ../../snippets/swift/BreezSDKExamples/Sources/Webhook.swift:register-webook}}
```
</section>
<div slot="title">Kotlin</div>
<section>
```kotlin,ignore
{{#include ../../snippets/kotlin_mpp_lib/shared/src/commonMain/kotlin/com/example/kotlinmpplib/Webhook.kt:register-webook}}
```
</section>
<div slot="title">React Native</div>
<section>
```typescript
{{#include ../../snippets/react-native/webhook.ts:register-webook}}
```
</section>
<div slot="title">Dart</div>
<section>
```dart,ignore
{{#include ../../snippets/dart_snippets/lib/webhook.dart:register-webook}}
```
</section>
<div slot="title">Python</div>
<section>
```python,ignore
{{#include ../../snippets/python/src/webhook.py:register-webook}}
```
</section>
<div slot="title">Go</div>
<section>
```go,ignore
{{#include ../../snippets/go/webhook.go:register-webook}}
```
</section>
<div slot="title">C#</div>
<section>
```cs,ignore
{{#include ../../snippets/csharp/Webhook.cs:register-webook}}
```
</section>
</custom-tabs>
## Handling Incoming Notifications
When a payment is received, the LSP will send a POST request to your webhook URL. The request body will contain details about the payment.
### Expected Webhook Payload
The payment received webhook payload is json formatted and contains the following structure:
<section>
<pre>
{
"type": "payment_received",
"data": {
"payment_hash" : [payment hash]
}
}
</pre>
</section>
## Processing the Payload
Processing of the Payload can be done according to the application's needs. One of the major use cases that can be handled via webhooks is receiving a payment in a mobile app while the app is not running, or in short "offline receive"
## Webhook integration for "offline receive"
In the context of mobile applications using the Breez SDK for Lightning Network payments, a crucial architectural component involves the seamless flow of payment notifications to the user's mobile device. This process is facilitated through a Notification Delivery Service (NDS) acting as an intermediary. When a payment is made to a user, the LSP sends a notification to the NDS configured with a specific webhook URL. The NDS then processes this information and dispatches a push notification to the intended mobile device, ensuring the user receives timely updates about incoming payments. This architecture necessitates vendors setting up and maintaining their own NDS, tailored to handle and forward these notifications efficiently.
### Step 1: Run your own NDS
As written above you will need to run your own NDS because the NDS is configured to send push notifications to your app users, therefore configured with the required keys and certificates.
If you don't want to write it from scratch, you can use our own <a href="https://github.com/breez/notify">NDS</a> implementation.
Our NDS implementation expects URLs in the following format:
<section><i>https://your-nds-service.com/notify?platform=<ios|android>&token=[PUSH_TOKEN]</i></section>
Once the NDS has received such request it will send a push notification to the matched device.
### Step 2: Obtain a mobile push token
First, ensure that your mobile application is set up to receive push notifications and can generate a push token. This token uniquely identifies the device for push notifications.
* For iOS, use Apple Push Notification Service (APNs) to get the token.
* For Android, use Firebase Cloud Messaging (FCM) to obtain the token.
### Step 3: Register the Webhook with Breez
Register the constructed URL with the Breez SDK By calling an SDK function.
<custom-tabs category="lang">
<div slot="title">Rust</div>
<section>
```rust,ignore
{{#include ../../snippets/rust/src/webhook.rs:register-payment-webook}}
```
</section>
<div slot="title">Swift</div>
<section>
```swift,ignore
{{#include ../../snippets/swift/BreezSDKExamples/Sources/Webhook.swift:register-payment-webook}}
```
</section>
<div slot="title">Kotlin</div>
<section>
```kotlin,ignore
{{#include ../../snippets/kotlin_mpp_lib/shared/src/commonMain/kotlin/com/example/kotlinmpplib/Webhook.kt:register-payment-webook}}
```
</section>
<div slot="title">React Native</div>
<section>
```typescript
{{#include ../../snippets/react-native/webhook.ts:register-payment-webook}}
```
</section>
<div slot="title">Dart</div>
<section>
```dart,ignore
{{#include ../../snippets/dart_snippets/lib/webhook.dart:register-payment-webook}}
```
</section>
<div slot="title">Python</div>
<section>
```python,ignore
{{#include ../../snippets/python/src/webhook.py:register-payment-webook}}
```
</section>
<div slot="title">Go</div>
<section>
```go,ignore
{{#include ../../snippets/go/webhook.go:register-payment-webook}}
```
</section>
<div slot="title">C#</div>
<section>
```cs,ignore
{{#include ../../snippets/csharp/Webhook.cs:register-payment-webook}}
```
</section>
</custom-tabs>
## Step 4: Handling Notifications When the App is Not Running
To ensure that your mobile application can handle payment notifications even when it is not actively running, specific implementations are required for both iOS and Android platforms. This involves waking up the app upon receiving a push notification, connecting with the Breez SDK, and then waiting for the payment to be fully received.
### iOS Implementation Using NotificationServiceExtension
#### Overview
For iOS, the app must use NotificationServiceExtension to process notifications in the background.
#### Steps for Implementation
* Integrate NotificationServiceExtension: Add NotificationServiceExtension to your iOS project. This extension allows your app to process the incoming push notification data in the background before presenting it to the user.
* Wake Up the App: When a push notification is received, the NotificationServiceExtension will be triggered, waking up the app.
* Connect with Breez SDK: Inside the extension, implement the logic for establishing a connection with the Breez SDK to process the incoming payment.
* Wait for Payment Completion: Once connected, the app should wait for completion status from the Breez SDK that the payment has been received.
* Handle the Notification: After confirming the payment, handle the notification accordingly by updating the app's UI.
As a reference implementation, see how we did it in c-breez wallet: <a href="https://github.com/breez/c-breez/blob/main/ios/Breez%20Notification%20Service%20Extension/NotificationService.swift">NotificationService.swift</a>
### Android Implementation Using WorkManager
#### Overview
On Android, WorkManager is used to perform background tasks when the app is not active.
#### Steps for Implementation
* Integrate WorkManager: Add WorkManager to your Android project. This component allows the app to handle background tasks efficiently.
* Wake Up the App: Configure WorkManager to trigger a background task when a push notification for a payment is received.
* Connect with Breez SDK: In the background task, implement logic to establish a connection with the Breez SDK.
* Wait for Payment Completion: Once connected, the app should wait for completion status from the Breez SDK that the payment has been received.
* Handle the Notification: After confirming the payment, handle the notification accordingly by updating the app's UI.
## Conclusion
Implementing these mechanisms on both iOS and Android ensures that your application remains responsive to payment notifications via the Breez SDK, even when it is not running in the foreground.