From 3163aaa17789c3e3a75d477e15e1bedd092e788b Mon Sep 17 00:00:00 2001 From: ndeet Date: Tue, 23 Apr 2024 00:03:00 +0200 Subject: [PATCH 1/6] Restructure cURL API docs, add more examples. --- docs/Development/GreenFieldExample.md | 171 +++++++++++++++++++------- 1 file changed, 127 insertions(+), 44 deletions(-) diff --git a/docs/Development/GreenFieldExample.md b/docs/Development/GreenFieldExample.md index 014365c7a1..eed8fa2757 100644 --- a/docs/Development/GreenFieldExample.md +++ b/docs/Development/GreenFieldExample.md @@ -6,94 +6,177 @@ Note that you can partially generate clients in the language of your choice by u In this guide, we will show you how to use it via command line on linux using `curl` and `jq`. -## Create a new user +## Prerequisites -Creating a new user can be done by using [this endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#tag/Users/paths/~1api~1v1~1users/post). +Unless for a few endpoints like creating a store and API key on behalf of a specific user, Basic Auth should be avoided and an API key should be used instead. Make sure that API keys only have the needed permissions and not more. E.g. if you only create invoices you should not give the API key the permission to manage your stores. + +You can create a new API key in the BTCPay Server UI under `Account` -> `Manage account` -> `API keys` + +For the ecommerce examples below the API key needs the following permissions: +- View invoices +- Create invoice +- Modify invoices +- Modify stores webhooks +- View your stores +- Create non-approved pull payments + +For an overview of available permissions see the [API documentation](https://docs.btcpayserver.org/API/Greenfield/v1/#section/Authentication/API_Key) or the permissions documented on each endpoint. + +## eCommerce examples + +The following examples will show you how to create a basic eCommerce flow using the Greenfield API by creating an invoice, registering a webhook, processing webhooks, and issuing a full refund of an invoice. + +### Create an invoice + +We create an invoice using the [create invoice endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Invoices_CreateInvoice). This is a simple example but you can set a lot more data like order id, ```bash BTCPAY_INSTANCE="https://mainnet.demo.btcpayserver.org" -USER="MyTestUser@gmail.com" -PASSWORD="NOTVERYSECURE" -body="$(echo "{}" | jq --arg "a" "$USER" '. + {email:$a}' \ - | jq --arg "a" "$PASSWORD" '. + {password:$a}')" +API_KEY="YOUR_API_KEY" +STORE_ID="YOUR_STORE_ID" +AMOUNT="10" +CURRENCY="USD" + +BODY="$(echo "{}" | jq --arg "a" "$AMOUNT" '. + {amount:$a}' \ + | jq --arg "a" "$CURRENCY" '. + {currency:$a}')" + curl -s \ -H "Content-Type: application/json" \ + -H "Authorization: token $API_KEY" \ -X POST \ - -d "$body" \ - "$BTCPAY_INSTANCE/api/v1/users" + -d "$BODY" \ + "$BTCPAY_INSTANCE/api/v1/stores/$STORE_ID/invoices" ``` -## Create a new API key +### Register a webhook (optional) -While we can use basic authentication to access the greenfield API, it is recommended to use API Keys to limit the scope of the credentials. +Let's register a webhook to be notified when the invoice is paid. You can use the [create webhook endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Webhooks_CreateWebhook) to register a webhook. -For example: If we want to [create a new store](https://docs.btcpayserver.org/API/Greenfield/v1/#tag/Stores/paths/~1api~1v1~1stores/post) we need the `btcpay.store.canmodifystoresettings` permission for the API key. +```bash +BTCPAY_INSTANCE="https://mainnet.demo.btcpayserver.org" +API_KEY="YOUR_API_KEY" +STORE_ID="YOUR_STORE_ID" -You can do it through BTCPay Server UI (by browsing `/account/apikeys` of your instance), but let's do it via command line using [this endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#tag/API-Keys/paths/~1api~1v1~1api-keys/post). +URL="https://example.com/your-webhook-endpoint" + +BODY="$(echo "{}" | jq --arg "a" "$URL" '. + {url:$a}')" + +curl -s \ + -H "Content-Type: application/json" \ + -H "Authorization: token $API_KEY" \ + -X POST \ + -d "$BODY" \ + "$BTCPAY_INSTANCE/api/v1/stores/$STORE_ID/webhooks" +``` + +This step is optional, you can also manually create a webhook in the BTCPay Server UI in your store `Settings` -> `Webhooks`. + +### Process webhooks + +This is not really possible with curl in bash but when you run a webserver. You can check the examples for NodeJS and PHP. + +### Issue a full refund of an invoice + +Using the [invoice refund endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Invoices_Refund) you can issue a full (or even partial) refund of an invoice. ```bash -permission="btcpay.store.canmodifystoresettings" -body="$(echo "{}" | jq --arg "a" "$permission" '. + {permissions:[$a]}')" -apikey="$(curl -s \ +BTCPAY_INSTANCE="https://mainnet.demo.btcpayserver.org" +API_KEY="YOUR_API_KEY" +STORE_ID="YOUR_STORE_ID" + +INVOICE_ID="EXISTING_INVOICE_ID" +PAYMENT_METHOD="BTC" +REFUND_VARIANT="CurrentRate" + +BODY="$(echo "{}" | jq --arg "a" "$REFUND_VARIANT" '. + {refundVariant:$a}' \ + | jq --arg "a" "$PAYMENT_METHOD" '. + {paymentMethod:$a}')" + +curl -s \ -H "Content-Type: application/json" \ - --user "$USER:$PASSWORD" \ + -H "Authorization: token $API_KEY" \ -X POST \ - -d "$body" \ - "$BTCPAY_INSTANCE/api/v1/api-keys" | jq -r .apiKey)" + -d "$BODY" \ + "$BTCPAY_INSTANCE/api/v1/stores/$STORE_ID/invoices/$INVOICE_ID/refund" ``` -You can then provide the API key via the `Authorization: token $apikey` header, as shown in the examples below. +## BTCPay Server management examples + +Here we assume you are an ambassador and host BTCPay Server for your users. You manage your users on your own system and want to create a user and set email and password for their BTCPay Server login. Then using the same credentials to create a store and an API key on behalf of that user. -## Create a new store +### Create a new user -Now, we can use the api key to [create a new store](https://docs.btcpayserver.org/API/Greenfield/v1/#tag/Stores/paths/~1api~1v1~1stores/post). +Creating a new user can be done by using [this endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Users_CreateUser). ```bash -store_name="My awesome store" -body="$(echo "{}" | jq --arg "a" "$store_name" '. + {name:$a}')" -store_id="$(curl -s \ +BTCPAY_INSTANCE="https://mainnet.demo.btcpayserver.org" +API_KEY="YOUR_ADMIN_API_KEY" + +USER="satoshi.nakamoto@example.com" +PASSWORD="SuperSecurePassword123" + +BODY="$(echo "{}" | jq --arg "a" "$USER" '. + {email:$a}' \ + | jq --arg "a" "$PASSWORD" '. + {password:$a}')" +curl -s \ -H "Content-Type: application/json" \ - -H "Authorization: token $apikey" \ + -H "Authorization: token $API_KEY" \ -X POST \ - -d "$body" \ - "$BTCPAY_INSTANCE/api/v1/stores" | jq -r .id)" + -d "$BODY" \ + "$BTCPAY_INSTANCE/api/v1/users" ``` -## Create a new API key with limiting permissions on the new store, for example read only +### Create a store on behalf of the user -You can set specific permissions per user, for your new store: +Now we create a store with the new users credentials the user becomes the owner [create a new store](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Stores_CreateStore). ```bash -old_apikey="$apikey" -permission="btcpay.store.canviewstoresettings:$store_id" -body="$(echo "{}" | jq --arg "a" "$permission" '. + {permissions:[$a]}')" -apikey="$(curl -s \ +STORE_NAME="My awesome store" + +BODY="$(echo "{}" | jq --arg "a" "$STORE_NAME" '. + {name:$a}')" + +NEW_STORE_ID="$(curl -s \ -H "Content-Type: application/json" \ --user "$USER:$PASSWORD" \ -X POST \ - -d "$body" \ - "$BTCPAY_INSTANCE/api/v1/api-keys" | jq -r .apiKey)" + -d "$BODY" \ + "$BTCPAY_INSTANCE/api/v1/stores" | jq -r .id)" + +echo "New store id: $NEW_STORE_ID" ``` -After creating the new API key, this is to [revoke our old apikey](https://docs.btcpayserver.org/API/Greenfield/v1/#tag/API-Keys/paths/~1api~1v1~1api-keys~1current/delete). -Don't forget this step! +### Create a new API key on behalf of the user + +Now we can create an API key and limit it to the new store with e.g. the `btcpay.store.canmodifystoresettings` permission. Likely you also want to allow API key to create invoices, but for this example we keep it simple. + +You can find the needed permissions for endpoints on the endpoint docs under "Authorization" or an overview of permissions in the [authorization section](https://docs.btcpayserver.org/API/Greenfield/v1/#section/Authentication/API_Key). ```bash -curl -s \ +API_KEY="YOUR_ADMIN_API_KEY" +USER="satoshi.nakamoto@example.com" +PERMISSION="btcpay.store.canmodifystoresettings" +NEW_STORE_ID="NEW_STORE_ID_FROM_PREVIOUS_STEP" + +BODY="$(echo "{}" | jq --arg "a" "$PERMISSION:$NEW_STORE_ID" '. + {permissions:[$a]}')" +USER_API_KEY="$(curl -s \ -H "Content-Type: application/json" \ - -H "Authorization: token $old_apikey" \ - -X DELETE \ - "$BTCPAY_INSTANCE/api/v1/api-keys/current" + -H "Authorization: token $API_KEY" \ + -X POST \ + -d "$BODY" \ + "$BTCPAY_INSTANCE/api/v1/users/$USER/api-keys" | jq -r .apiKey)" + +echo "New user api key: $USER_API_KEY" ``` -## Read store information +### Read store information We can use the new apikey to [read store](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Stores_GetStore) information: ```bash +USER_API_KEY="API_KEY_FROM_PREVIOUS_STEP" +NEW_STORE_ID="NEW_STORE_ID_FROM_BEFORE_PREVIOUS_STEP" + curl -s \ -H "Content-Type: application/json" \ - -H "Authorization: token $apikey" \ + -H "Authorization: token $USER_API_KEY" \ -X GET \ - "$BTCPAY_INSTANCE/api/v1/stores/$store_id" + "$BTCPAY_INSTANCE/api/v1/stores/$NEW_STORE_ID" ``` From 35945e36f57bef1163afc8321b5a4acdf27034dc Mon Sep 17 00:00:00 2001 From: ndeet Date: Tue, 23 Apr 2024 13:17:32 +0200 Subject: [PATCH 2/6] PHP restructuring and more examples. --- docs/Development/GreenFieldExample.md | 16 +- docs/Development/GreenfieldExample-PHP.md | 242 +++++++++++++++------- 2 files changed, 180 insertions(+), 78 deletions(-) diff --git a/docs/Development/GreenFieldExample.md b/docs/Development/GreenFieldExample.md index eed8fa2757..49c6d96e31 100644 --- a/docs/Development/GreenFieldExample.md +++ b/docs/Development/GreenFieldExample.md @@ -71,13 +71,13 @@ curl -s \ This step is optional, you can also manually create a webhook in the BTCPay Server UI in your store `Settings` -> `Webhooks`. -### Process webhooks +### Validate and process webhooks -This is not really possible with curl in bash but when you run a webserver. You can check the examples for NodeJS and PHP. +This is not really possible with curl in bash but when you run a webserver. You can check the examples for [NodeJS](./GreenFieldExample-NodeJS.md) and [PHP](./GreenfieldExample-PHP.md). ### Issue a full refund of an invoice -Using the [invoice refund endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Invoices_Refund) you can issue a full (or even partial) refund of an invoice. +Using the [invoice refund endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Invoices_Refund) you can issue a full (or even partial) refund of an invoice. This will return a link where the customer can claim the refund. ```bash BTCPAY_INSTANCE="https://mainnet.demo.btcpayserver.org" @@ -109,16 +109,16 @@ Creating a new user can be done by using [this endpoint](https://docs.btcpayserv ```bash BTCPAY_INSTANCE="https://mainnet.demo.btcpayserver.org" -API_KEY="YOUR_ADMIN_API_KEY" +ADMIN_API_KEY="YOUR_ADMIN_API_KEY" USER="satoshi.nakamoto@example.com" -PASSWORD="SuperSecurePassword123" +PASSWORD="SuperSecurePasswordsShouldBeQuiteLong123" BODY="$(echo "{}" | jq --arg "a" "$USER" '. + {email:$a}' \ | jq --arg "a" "$PASSWORD" '. + {password:$a}')" curl -s \ -H "Content-Type: application/json" \ - -H "Authorization: token $API_KEY" \ + -H "Authorization: token $ADMIN_API_KEY" \ -X POST \ -d "$BODY" \ "$BTCPAY_INSTANCE/api/v1/users" @@ -150,7 +150,7 @@ Now we can create an API key and limit it to the new store with e.g. the `btcpay You can find the needed permissions for endpoints on the endpoint docs under "Authorization" or an overview of permissions in the [authorization section](https://docs.btcpayserver.org/API/Greenfield/v1/#section/Authentication/API_Key). ```bash -API_KEY="YOUR_ADMIN_API_KEY" +ADMIN_API_KEY="YOUR_ADMIN_API_KEY" USER="satoshi.nakamoto@example.com" PERMISSION="btcpay.store.canmodifystoresettings" NEW_STORE_ID="NEW_STORE_ID_FROM_PREVIOUS_STEP" @@ -158,7 +158,7 @@ NEW_STORE_ID="NEW_STORE_ID_FROM_PREVIOUS_STEP" BODY="$(echo "{}" | jq --arg "a" "$PERMISSION:$NEW_STORE_ID" '. + {permissions:[$a]}')" USER_API_KEY="$(curl -s \ -H "Content-Type: application/json" \ - -H "Authorization: token $API_KEY" \ + -H "Authorization: token $ADMIN_API_KEY" \ -X POST \ -d "$BODY" \ "$BTCPAY_INSTANCE/api/v1/users/$USER/api-keys" | jq -r .apiKey)" diff --git a/docs/Development/GreenfieldExample-PHP.md b/docs/Development/GreenfieldExample-PHP.md index 648f7d5f86..ace48971e3 100644 --- a/docs/Development/GreenfieldExample-PHP.md +++ b/docs/Development/GreenfieldExample-PHP.md @@ -2,128 +2,111 @@ The **[Greenfield API](https://docs.btcpayserver.org/API/Greenfield/v1/)** (also available on your instance on `/docs`) allows you to operate BTCPay Server via an easy-to-use REST API. +Note that you can partially generate clients in the language of your choice by using the [Swagger file](https://docs.btcpayserver.org/API/Greenfield/v1/swagger.json). + For PHP we have a client library available which can be found [here](https://github.com/btcpayserver/btcpayserver-greenfield-php) and is also available for installation via Composer `composer require btcpayserver/btcpayserver-greenfield-php` -In this guide, we will give some examples how to use the Greenfield API with our PHP library. Additional examples can be found [here](https://github.com/btcpayserver/btcpayserver-greenfield-php/tree/master/examples). +In this guide, we will give some examples how to use the Greenfield API with our PHP library for eCommerce and BTCPay management. Additional examples can be found [here](https://github.com/btcpayserver/btcpayserver-greenfield-php/tree/master/examples). -You can generate your API key in the BTCPay Server UI under "Account" -> "Manage Account" -> "API Keys" (path `/account/apikeys`). Make sure that the API key you are using has the permissions to execute the needed requests. -## Create a new user +## Prerequisites -Creating a new user can be done by using [this endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Users_CreateUser). +Unless for a few endpoints like creating a store and API key on behalf of a specific user, Basic Auth should be avoided and an API key should be used instead. Make sure that API keys only have the needed permissions and not more. E.g. if you only create invoices you should not give the API key the permission to manage your stores. -```php -require __DIR__ . './vendor/autoload.php'; +You can create a new API key in the BTCPay Server UI under `Account` -> `Manage account` -> `API keys` -$host = 'https://mainnet.demo.btcpayserver.org'; -$apiKey = 'pQc2FYhYwNzhf4DF7Foo6YpQc2FYhYwNzhf4DF7Foo6Y'; -$email = 'test@test.com'; -$password = 'Testing##123'; -$isAdministrator = false; +For the ecommerce examples below the API key needs the following permissions: +- View invoices +- Create invoice +- Modify invoices +- Modify stores webhooks +- View your stores +- Create non-approved pull payments -try { - $client = new \BTCPayServer\Client\User($host, $apiKey); - var_dump($client->createUser($email, $password, $isAdministrator)); -} catch (\Throwable $e) { - echo "Error: " . $e->getMessage(); -} -``` +For an overview of available permissions see the [API documentation](https://docs.btcpayserver.org/API/Greenfield/v1/#section/Authentication/API_Key) or the permissions documented on each endpoint. -## Create a new API key +## eCommerce examples -While we can use basic authentication to access the greenfield API, it is recommended to use API Keys to limit the scope of the credentials. +The following examples will show you how to create a basic eCommerce flow using the Greenfield API by creating an invoice, registering a webhook, processing webhooks, and issuing a full refund of an invoice. -For example: If we want to [create a new store](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Stores_CreateStore) we need the `btcpay.store.canmodifystoresettings` permission for the API key. Warning: If you do not pass any permission then the API key will have unrestricted access. +### Create an invoice -As mentioned above, you can do this through the BTCPay Server UI of your instance, but let's do it through the API using [this endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/ApiKeys_CreateApiKey). +We create an invoice using the [create invoice endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Invoices_CreateInvoice). This is a simple example but you can set a lot more data like order id, -```php +```PHP require __DIR__ . './vendor/autoload.php'; $host = 'https://mainnet.demo.btcpayserver.org'; $apiKey = 'API_KEY'; +$storeId = 'STORE_ID'; +$amount = 10; +$currency = 'USD'; +$orderId = 'SN21420'; +$buyerEmail = 'satoshi.nakamoto@example.com'; try { - $client = new \BTCPayServer\Client\Apikey($host, $apiKey); - var_dump($client->createApiKey('api generated', ['btcpay.store.canmodifystoresettings'])); + $client = new \BTCPayServer\Client\Invoice($host, $apiKey); + var_dump( + $client->createInvoice( + $storeId, + $currency, + \BTCPayServer\Util\PreciseNumber::parseString($amount), + $orderId, + $buyerEmail + ) + ); } catch (\Throwable $e) { echo "Error: " . $e->getMessage(); } ``` -## Create a new store +### Register a webhook (optional) -Now, we can use the api key to [create a new store](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Stores_CreateStore). +Let's register a webhook to be notified when the invoice is paid. You can use the [create webhook endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Webhooks_CreateWebhook) to register a webhook. -```php -require __DIR__ . './vendor/autoload.php'; - -$host = 'https://mainnet.demo.btcpayserver.org'; -$apiKey = 'API_KEY'; - -// Create a new store. -try { - $client = new \BTCPayServer\Client\Store($host, $apiKey); - var_dump($client->createStore('my new store')); -} catch (\Throwable $e) { - echo "Error: " . $e->getMessage(); -} -``` - -## Create a simple invoice - -```php +```PHP require __DIR__ . './vendor/autoload.php'; $host = 'https://mainnet.demo.btcpayserver.org'; $apiKey = 'API_KEY'; $storeId = 'STORE_ID'; -$amount = 5.15 + mt_rand(0, 20); -$currency = 'USD'; -$orderId = 'Test39939' . mt_rand(0, 1000); -$buyerEmail = 'john@example.com'; +$url = 'https://example.com/webhook'; +$subscribedEvents = null; // Will subscribe to all events. -// Create a basic invoice. try { - $client = new \BTCPayServer\Client\Invoice($host, $apiKey); + $client = new \BTCPayServer\Client\Webhook($host, $apiKey); var_dump( - $client->createInvoice( - $storeId, - $currency, - PreciseNumber::parseString($amount), - $orderId, - $buyerEmail - ) + $client->createWebhook($storeId, $url, $subscribedEvents, null) ); } catch (\Throwable $e) { echo "Error: " . $e->getMessage(); } ``` -You can find a more advanced example with metadata and checkout options [here](https://github.com/btcpayserver/btcpayserver-greenfield-php/blob/master/examples/create_invoice.php) +This step is optional, you can also manually create a webhook in the BTCPay Server UI in your store `Settings` -> `Webhooks`. -## Webhook implementation and validation with PHP - -You can register a webhook for [invoice events](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Webhook_InvoiceCreated) through your Store settings UI ("Settings" -> "Webhooks") or via [this endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Webhooks_CreateWebhook). +## Validate and process webhooks The webhook payloads of BTCPay Server are signed, and therefore you can trust its content - but only after proper request validation. The validation of the provided `BTCPay-Sig` HTTP-header and payload, is done by the library. -On webhook creation, you provide an `url` that points to an endpoint route on your PHP site. e.g. `https://example.com/mywebhookcallback`. If you did not provide the `secret` yourself it will be autogenerated for you. +On webhook registration step (see above), you provided an `url` that points to an endpoint route on your PHP site. e.g. `https://example.com/webhook`. The `secret` which is used to sign the request was returned in our example above. -On that endpoint you can read and validate the webhook payload of your BTCPay Server instance like this: +On your eCommerce site you can now validate and process the payload of your BTCPay Server webhook like this: -```php +```PHP require __DIR__ . './vendor/autoload.php'; $host = 'https://mainnet.demo.btcpayserver.org'; $apiKey = 'API_KEY'; $storeId = 'STORE_ID'; -$webhookSecret = 'WEBHOOK_SECRET' +$webhookSecret = 'WEBHOOK_SECRET'; // From previous step +// Get the data sent by BTCPay Server. $raw_post_data = file_get_contents('php://input'); $payload = json_decode($raw_post_data, false, 512, JSON_THROW_ON_ERROR); // Get the BTCPay signature header. +// This is needed as some webservers camel-case the headers, some not. $headers = getallheaders(); foreach ($headers as $key => $value) { if (strtolower($key) === 'btcpay-sig') { @@ -136,13 +119,132 @@ $webhookClient = new \BTCPayServer\Client\Webhook($host, $apiKey); // Validate the webhook request. if (!$webhookClient->isIncomingWebhookRequestValid($raw_post_data, $sig, $secret)) { throw new \RuntimeException( - 'Invalid BTCPayServer payment notification message received - signature did not match.' + 'Invalid BTCPay Server payment webhook message received - signature did not match.' ); } -// Your own processing code goes here. +echo 'Validation OK'; + +// Your own processing code goes here. E.g. update your internal order id depending on the invoice payment status. -echo 'OK'; ``` -You can find many more examples [here](https://github.com/btcpayserver/btcpayserver-greenfield-php/blob/master/examples/) +### Issue a full refund of an invoice + +Using the [invoice refund endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Invoices_Refund) you can issue a full (or even partial) refund of an invoice. This will return a link where the customer can claim the refund. + +```PHP +require __DIR__ . './vendor/autoload.php'; + +$host = 'https://mainnet.demo.btcpayserver.org'; +$apiKey = 'API_KEY'; +$storeId = 'STORE_ID'; +$invoiceId = 'EXISTING_INVOICE_ID'; +$paymentMethod = 'BTC'; +$refundVariant = 'CurrentRate'; + +try { + $client = new \BTCPayServer\Client\Invoice($host, $apiKey); + + $refund = $client->refundInvoice( + $storeId, + $invoiceId, + $refundVariant, + $paymentMethod + ); + + echo $refund->getViewLink(); +} catch (\Throwable $e) { + echo "Error: " . $e->getMessage(); +} +``` + + +## BTCPay Server management examples + +Here we assume you are an ambassador and host BTCPay Server for your users. You manage your users on your own system and want to create a user and set email and password for their BTCPay Server login. Then using the same credentials to create a store and an API key on behalf of that user. + +### Create a new user + +Creating a new user can be done by using [this endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Users_CreateUser). + +```PHP +require __DIR__ . './vendor/autoload.php'; + +$host = 'https://mainnet.demo.btcpayserver.org'; +$adminApiKey = 'ADMIN_API_KEY'; +$email = 'satoshi.nakamoto@example.com'; +$password = 'SuperSecurePasswordsShouldBeQuiteLong123'; +$isAdministrator = false; + +try { + $client = new \BTCPayServer\Client\User($host, $apiKey); + var_dump($client->createUser($email, $password, $isAdministrator)); +} catch (\Throwable $e) { + echo "Error: " . $e->getMessage(); +} +``` + +## Create a new API key + +While we can use basic authentication to access the greenfield API, it is recommended to use API Keys to limit the scope of the credentials. + +For example: If we want to [create a new store](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Stores_CreateStore) we need the `btcpay.store.canmodifystoresettings` permission for the API key. Warning: If you do not pass any permission then the API key will have unrestricted access. + +As mentioned above, you can do this through the BTCPay Server UI of your instance, but let's do it through the API using [this endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/ApiKeys_CreateApiKey). + +```PHP +require __DIR__ . './vendor/autoload.php'; + +$host = 'https://mainnet.demo.btcpayserver.org'; +$userEmail = 'satoshi.nakamoto@example.com'; +$adminApiKey = 'ADMIN_API_KEY'; + +try { + $client = new \BTCPayServer\Client\Apikey($host, $adminApiKey); + $generatedApiKey = $client->createApiKeyForUser($userEmail, 'api generated', ['btcpay.store.canmodifystoresettings']); +} catch (\Throwable $e) { + echo "Error: " . $e->getMessage(); +} + +echo $generatedApiKey->getData()['apiKey']; +``` + +## Create a new store + +Now, we can use the users API key to [create a new store](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Stores_CreateStore). + +```PHP +require __DIR__ . './vendor/autoload.php'; + +$host = 'https://mainnet.demo.btcpayserver.org'; +$userApiKey = 'USER_API_KEY'; // From previous step + +try { + $client = new \BTCPayServer\Client\Store($host, $userApiKey); + var_dump($client->createStore('my new store')); +} catch (\Throwable $e) { + echo "Error: " . $e->getMessage(); +} +``` + +### Read store information + +We can use the new apikey to [read store](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Stores_GetStore) information: + +```PHP +require __DIR__ . './vendor/autoload.php'; + +$host = 'https://mainnet.demo.btcpayserver.org'; +$userApiKey = 'USER_API_KEY'; // From previous step +$storeId = 'STORE_ID'; // From previous step + +try { + $client = new \BTCPayServer\Client\Store($host, $userApiKey); + var_dump($client->getStore($storeId); +} catch (\Throwable $e) { + echo "Error: " . $e->getMessage(); +} +``` + +Looking for more examples, you can find them [here](https://github.com/btcpayserver/btcpayserver-greenfield-php/tree/master/examples). From 1601aa097fa929bdd1e31b7d5b86754cc9a1f444 Mon Sep 17 00:00:00 2001 From: ndeet Date: Wed, 24 Apr 2024 10:52:05 +0200 Subject: [PATCH 3/6] Adding Node.js examples. --- docs/Development/GreenFieldExample-NodeJS.md | 302 ++++++++++++++----- docs/Development/GreenfieldExample-PHP.md | 18 +- 2 files changed, 236 insertions(+), 84 deletions(-) diff --git a/docs/Development/GreenFieldExample-NodeJS.md b/docs/Development/GreenFieldExample-NodeJS.md index 3de772fc00..ae509a1047 100644 --- a/docs/Development/GreenFieldExample-NodeJS.md +++ b/docs/Development/GreenFieldExample-NodeJS.md @@ -1,68 +1,57 @@ -# Greenfield API example with Node.JS (JavaScript) +# Greenfield API example with Node.js (JavaScript) + The **[Greenfield API](https://docs.btcpayserver.org/API/Greenfield/v1/)** (also available on your instance on `/docs`) allows you to operate BTCPay Server via an easy-to-use REST API. Note that you can partially generate clients in the language of your choice by using the [Swagger file](https://docs.btcpayserver.org/API/Greenfield/v1/swagger.json). -In this guide, we will give some examples how to use the Greenfield API with Node.JS. +In this guide, we will show you how to use it using Node.js/JavaScript. -You can generate your API key in the BTCPay Server UI under "Account" -> "Manage Account" -> "API Keys" (path `/account/apikeys`). Make sure that the API key you are using has the permissions to execute the needed requests. +## Prerequisites -## Create a new user +Unless for a few endpoints like creating a store and API key on behalf of a specific user, Basic Auth should be avoided and an API key should be used instead. Make sure that API keys only have the needed permissions and not more. E.g. if you only create invoices you should not give the API key the permission to manage your stores. -Creating a new user can be done by using [this endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Users_CreateUser). +You can create a new API key in the BTCPay Server UI under `Account` -> `Manage account` -> `API keys` -```js -const btcpayserverurl = 'https://mainnet.demo.btcpayserver.org' -const apiendpoint = '/api/v1/users' -const token = 'APIKEYTOKEN' -const headers = { - 'Content-Type': 'application/json', - Authorization: 'token ' + token -} -const user = { - email: 'MyTestUser@gmail.com', - password: 'NOTVERYSECURE', - isAdministrator: false -} +For the ecommerce examples below the API key needs the following permissions: +- View invoices +- Create invoice +- Modify invoices +- Modify stores webhooks +- View your stores +- Create non-approved pull payments -fetch(btcpayserverurl + apiendpoint, { - method: 'POST', - headers: headers, - body: JSON.stringify(user) -}) - .then(response => response.json()) - .then(data => { - console.log(data) - }) -``` +For an overview of available permissions see the [API documentation](https://docs.btcpayserver.org/API/Greenfield/v1/#section/Authentication/API_Key) or the permissions documented on each endpoint. -## Create a new API key +## eCommerce examples -While we can use basic authentication to access the greenfield API, it is recommended to use API Keys to limit the scope of the credentials. +The following examples will show you how to create a basic eCommerce flow using the Greenfield API by creating an invoice, registering a webhook, processing webhooks, and issuing a full refund of an invoice. -For example: If we want to [create a new store](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Stores_CreateStore) we need the `btcpay.store.canmodifystoresettings` permission for the API key. +### Create an invoice -As mentioned above, you can do through BTCPay Server UI of your instance, but let's do it through the API using [this endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/ApiKeys_CreateApiKey). +We create an invoice using the [create invoice endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Invoices_CreateInvoice). This is a simple example but you can set a lot more data like order id, + +```JS +const btcpayServerUrl = 'https://mainnet.demo.btcpayserver.org' +const storeId = 'YOUR_STORE_ID' +const apiKey = 'YOUR_API_KEY' +const amount = 10 +const currency = 'USD' + +const apiEndpoint = `/api/v1/stores/${storeId}/invoices` -```js -const btcpayserverUrl = 'https://mainnet.demo.btcpayserver.org' -const apiEndpoint = '/api/v1/api-keys' -const permission = 'btcpay.store.canmodifystoresettings' -const token = 'APIKEYTOKEN' const headers = { 'Content-Type': 'application/json', - Authorization: 'token ' + token + Authorization: 'token ' + apiKey } -const apikey = { - label: 'LABELNAME', - permissions: [permission] +const payload = { + amount: amount, + currency: currency } - -fetch(btcpayserverUrl + apiEndpoint, { +fetch(btcpayServerUrl + apiEndpoint, { method: 'POST', headers: headers, - body: JSON.stringify(apikey) + body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => { @@ -70,26 +59,29 @@ fetch(btcpayserverUrl + apiEndpoint, { }) ``` -## Create a new store +### Register a webhook (optional) -Now, we can use the api key to [create a new store](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Stores_CreateStore). +Let's register a webhook to be notified when the invoice is paid. You can use the [create webhook endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Webhooks_CreateWebhook) to register a webhook. + +```JS +const btcpayServerUrl = 'https://mainnet.demo.btcpayserver.org' +const storeId = 'YOUR_STORE_ID' +const apiKey = 'YOUR_API_KEY' + +const apiEndpoint = `/api/v1/stores/${storeId}/webhooks` -```js -const btcpayserverUrl = 'https://mainnet.demo.btcpayserver.org' -const apiEndpoint = '/api/v1/stores' -const token = 'APIKEYTOKEN' const headers = { 'Content-Type': 'application/json', - Authorization: 'token ' + token -} -const store = { - Name: 'STORENAME' + Authorization: 'token ' + apiKey } -fetch(btcpayserverurl + apiendpoint, { +const payload = { + url: 'https://example.com/your-webhook-endpoint' +} +fetch(btcpayServerUrl + apiEndpoint, { method: 'POST', headers: headers, - body: JSON.stringify(store) + body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => { @@ -97,30 +89,29 @@ fetch(btcpayserverurl + apiendpoint, { }) ``` -## Webhook implementation with Node.JS + Express +This step is optional, you can also manually create a webhook in the BTCPay Server UI in your store `Settings` -> `Webhooks`. -You can use your Node.JS Express web application to receive webhook requests from your BTCPay Server. +### Validate and process webhooks -First you need a route so that your Node.JS application can receive POST requests. -Based on how you set up the express server this should look somthing like underneath. +You can use your Node.js Express web application to receive webhook requests from your BTCPay Server. -```js -app.post('/btcpayserverwebhook', (req, res) => { - //do stuff here +First you need a route so that your Node.js application can receive POST requests. +Based on how you set up the express server this should look something like this: + +```JS +app.post('/your-webhook-endpoint', (req, res) => { + // Do stuff here }) ``` -What's important is that the webhook (as statet in the documentation) delivers an HTTP-Header `BTCPAY-SIG`. -You should in above function compare the `BTCPAY-SIG` with the actual data from the request body (as bytes). -In your app.js (or similar) add following where you include requirements: - +What's important is that the webhook sends a HTTP-header `BTCPAY-SIG` which is the signed request using the `secret` you got back from the preivous step when registering the webhook. You can use that `secret` and the raw payload (as bytes) you get from the webhook, hash it and compare it to `BTCPAY-SIG`. Therefore you need `body-parser` which is a middleware to parse the raw body of the request. ```js const bodyParser = require('body-parser') ``` -and add following +You can parse the raw body of the request like this: -```js +```JS app.use( bodyParser.json({ verify: (req, res, buf) => { @@ -132,13 +123,13 @@ app.use( This makes sure that in req.rawBody the correct content is parsed so that you can compare the hashed req.rawBody with the `BTCPAY-SIG` header value. -Edit your router function like this: (Obviously change `webhookSecret`) +In your router it looks like this put all together: (Change `webhookSecret` with the `secret` you got back from the previous step when registering the webhook). -```js -app.post('/btcpayserverwebhook', (req, res) => { +```JS +app.post('/your-webhook-endpoint', (req, res) => { const sigHashAlg = 'sha256' const sigHeaderName = 'BTCPAY-SIG' - const webhookSecret = 'VERYVERYSECRET' + const webhookSecret = 'SECRET_FROM_REGISTERING_WEBHOOK' // see previous step if (!req.rawBody) { return next('Request body empty') } @@ -148,7 +139,9 @@ app.post('/btcpayserverwebhook', (req, res) => { sigHashAlg + '=' + hmac.update(req.rawBody).digest('hex'), 'utf8' ) + const checksum = Buffer.from(sig, 'utf8') + if ( checksum.length !== digest.length || !crypto.timingSafeEqual(digest, checksum) @@ -160,8 +153,169 @@ app.post('/btcpayserverwebhook', (req, res) => { `Request body digest (${digest}) did not match ${sigHeaderName} (${checksum})` ) } else { - // Do More Stuff here + + // Your own processing code goes here. E.g. update your internal order id depending on the invoice payment status. + res.status(200).send('Request body was signed') } }) ``` + +### Issue a full refund of an invoice + +Using the [invoice refund endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Invoices_Refund) you can issue a full (or even partial) refund of an invoice. This will return a link where the customer can claim the refund. + +```JS +const btcpayServerUrl = 'https://mainnet.demo.btcpayserver.org' +const storeId = 'YOUR_STORE_ID' +const apiKey = 'YOUR_API_KEY' +const invoiceId = 'EXISTING_INVOICE_ID' + +const apiEndpoint = `/api/v1/stores/${storeId}/invoices/${invoiceId}/refund` + +const headers = { + 'Content-Type': 'application/json', + Authorization: 'token ' + apiKey +} + +const payload = { + refundVariant: 'BTC', + paymentMethod: 'CurrentRate' +} +fetch(btcpayServerUrl + apiEndpoint, { + method: 'POST', + headers: headers, + body: JSON.stringify(payload) +}) + .then(response => response.json()) + .then(data => { + console.log(data) + }) +``` + +## BTCPay Server management examples + +Here we assume you are an ambassador and host BTCPay Server for your users. You manage your users on your own system and want to create a user and set email and password for their BTCPay Server login. Then using the same credentials to create a store and an API key on behalf of that user. + +## Create a new user + +Creating a new user can be done by using [this endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Users_CreateUser). + +```JS +const btcpayServerUrl = 'https://mainnet.demo.btcpayserver.org' +const AdminApiKey = 'YOUR_ADMIN_API_KEY' + +const apiEndpoint = '/api/v1/users' + +const headers = { + 'Content-Type': 'application/json', + Authorization: 'token ' + apiKey +} + +const payload = { + email: 'satoshi.nakamoto@example.com', + password: 'SuperSecurePasswordsShouldBeQuiteLong123', + isAdministrator: false +} + +fetch(btcpayServerUrl + apiEndpoint, { + method: 'POST', + headers: headers, + body: JSON.stringify(payload) +}) + .then(response => response.json()) + .then(data => { + console.log(data) + }) +``` + +### Create a new API key (for the user) + +While we can use basic authentication to access the greenfield API, it is recommended to use API Keys to limit the scope of the credentials. + +For example: If we want to [create a new store](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Stores_CreateStore) we need the `btcpay.store.canmodifystoresettings` permission for the API key. Warning: If you do not pass any permission then the API key will have unrestricted access. + +As mentioned above, you can do this through the BTCPay Server UI of your instance, but let's do it through the API using [this endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/ApiKeys_CreateUserApiKey) where we with our admin API key create an API key for our new user. + +```js +const btcpayserverUrl = 'https://mainnet.demo.btcpayserver.org' +const AdminApiKey = 'YOUR_ADMIN_API_KEY' +const email = 'satoshi.nakamoto@example.com' + +const apiEndpoint = `/api/v1/users/${email}/api-keys` + +const headers = { + 'Content-Type': 'application/json', + Authorization: 'token ' + adminApiKey +} + +const payload = { + label: 'Satoshi Nakamoto API Key', + permissions: ['btcpay.store.canmodifystoresettings'] +} + +fetch(btcpayserverUrl + apiEndpoint, { + method: 'POST', + headers: headers, + body: JSON.stringify(payload) +}) + .then(response => response.json()) + .then(data => { + console.log(data) // returns apiKey + }) +``` + +## Create a new store + +Now, we can use the api key to [create a new store](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Stores_CreateStore). + +```JS +const btcpayserverUrl = 'https://mainnet.demo.btcpayserver.org' +const userApiKey = 'USER_API_KEY' // From previous step + +const apiEndpoint = '/api/v1/stores' + +const headers = { + 'Content-Type': 'application/json', + Authorization: 'token ' + userApiKey +} +const payload = { + name: 'Satoshi Store' +} + +fetch(btcpayServerUrl + apiEndpoint, { + method: 'POST', + headers: headers, + body: JSON.stringify(payload) +}) + .then(response => response.json()) + .then(data => { + console.log(data) + }) +``` + +### Read store information + +We can use the new apikey to [read store](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Stores_GetStore) information: + +```JS +const btcpayserverUrl = 'https://mainnet.demo.btcpayserver.org' +const userApiKey = 'USER_API_KEY' // From previous step +const storeId = 'STORE_ID' // From previous step + +const apiEndpoint = `/api/v1/stores/${storeId}` + +const headers = { + 'Content-Type': 'application/json', + Authorization: 'token ' + userApiKey +} + +fetch(btcpayServerUrl + apiEndpoint, { + method: 'GET', + headers: headers +}) + .then(response => response.json()) + .then(data => { + console.log(data) + }) +``` diff --git a/docs/Development/GreenfieldExample-PHP.md b/docs/Development/GreenfieldExample-PHP.md index ace48971e3..7350b3ff9c 100644 --- a/docs/Development/GreenfieldExample-PHP.md +++ b/docs/Development/GreenfieldExample-PHP.md @@ -85,7 +85,7 @@ try { This step is optional, you can also manually create a webhook in the BTCPay Server UI in your store `Settings` -> `Webhooks`. -## Validate and process webhooks +### Validate and process webhooks The webhook payloads of BTCPay Server are signed, and therefore you can trust its content - but only after proper request validation. The validation of the provided `BTCPay-Sig` HTTP-header and payload, is done by the library. @@ -140,17 +140,13 @@ $host = 'https://mainnet.demo.btcpayserver.org'; $apiKey = 'API_KEY'; $storeId = 'STORE_ID'; $invoiceId = 'EXISTING_INVOICE_ID'; -$paymentMethod = 'BTC'; -$refundVariant = 'CurrentRate'; try { $client = new \BTCPayServer\Client\Invoice($host, $apiKey); $refund = $client->refundInvoice( $storeId, - $invoiceId, - $refundVariant, - $paymentMethod + $invoiceId ); echo $refund->getViewLink(); @@ -179,19 +175,21 @@ $isAdministrator = false; try { $client = new \BTCPayServer\Client\User($host, $apiKey); - var_dump($client->createUser($email, $password, $isAdministrator)); + var_dump( + $client->createUser($email, $password, $isAdministrator) + ); } catch (\Throwable $e) { echo "Error: " . $e->getMessage(); } ``` -## Create a new API key +### Create a new API key (for the user) While we can use basic authentication to access the greenfield API, it is recommended to use API Keys to limit the scope of the credentials. For example: If we want to [create a new store](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Stores_CreateStore) we need the `btcpay.store.canmodifystoresettings` permission for the API key. Warning: If you do not pass any permission then the API key will have unrestricted access. -As mentioned above, you can do this through the BTCPay Server UI of your instance, but let's do it through the API using [this endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/ApiKeys_CreateApiKey). +As mentioned above, you can do this through the BTCPay Server UI of your instance, but let's do it through the API using [this endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/ApiKeys_CreateUserApiKey) where we with our admin API key create an API key for our new user. ```PHP require __DIR__ . './vendor/autoload.php'; @@ -210,7 +208,7 @@ try { echo $generatedApiKey->getData()['apiKey']; ``` -## Create a new store +### Create a new store Now, we can use the users API key to [create a new store](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Stores_CreateStore). From 82f97bc5d9340360df6cd75493f5a100c243087f Mon Sep 17 00:00:00 2001 From: ndeet Date: Wed, 24 Apr 2024 22:58:42 +0200 Subject: [PATCH 4/6] Node.js fixes after testing. --- docs/Development/GreenFieldExample-NodeJS.md | 39 +++++++++++--------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/docs/Development/GreenFieldExample-NodeJS.md b/docs/Development/GreenFieldExample-NodeJS.md index ae509a1047..e729de3a94 100644 --- a/docs/Development/GreenFieldExample-NodeJS.md +++ b/docs/Development/GreenFieldExample-NodeJS.md @@ -104,9 +104,10 @@ app.post('/your-webhook-endpoint', (req, res) => { }) ``` -What's important is that the webhook sends a HTTP-header `BTCPAY-SIG` which is the signed request using the `secret` you got back from the preivous step when registering the webhook. You can use that `secret` and the raw payload (as bytes) you get from the webhook, hash it and compare it to `BTCPAY-SIG`. Therefore you need `body-parser` which is a middleware to parse the raw body of the request. -```js +What's important is that the webhook sends a HTTP-header `BTCPAY-SIG` which is the signed request using the `secret` you got back from the previous step when registering the webhook. You can use that `secret` and the raw payload (as bytes) you get from the webhook, hash it and compare it to `BTCPAY-SIG`. Therefore, you need `body-parser` which is a middleware to parse the raw body of the request. For comparing the hashes you also need `crypto` which is a built-in Node.js module. +```JS const bodyParser = require('body-parser') +const crypto = require('crypto') ``` You can parse the raw body of the request like this: @@ -131,7 +132,7 @@ app.post('/your-webhook-endpoint', (req, res) => { const sigHeaderName = 'BTCPAY-SIG' const webhookSecret = 'SECRET_FROM_REGISTERING_WEBHOOK' // see previous step if (!req.rawBody) { - return next('Request body empty') + res.status(500).send('Request body empty') } const sig = Buffer.from(req.get(sigHeaderName) || '', 'utf8') const hmac = crypto.createHmac(sigHashAlg, webhookSecret) @@ -146,17 +147,13 @@ app.post('/your-webhook-endpoint', (req, res) => { checksum.length !== digest.length || !crypto.timingSafeEqual(digest, checksum) ) { - console.log( - `Request body digest (${digest}) did not match ${sigHeaderName} (${checksum})` - ) - return next( - `Request body digest (${digest}) did not match ${sigHeaderName} (${checksum})` - ) + console.log(`Request body digest (${digest}) did not match ${sigHeaderName} (${checksum})`) + res.status(500).send(`Request body digest (${digest}) did not match ${sigHeaderName} (${checksum})`) } else { // Your own processing code goes here. E.g. update your internal order id depending on the invoice payment status. - res.status(200).send('Request body was signed') + res.status(200).send('Success: request body was signed') } }) ``` @@ -179,9 +176,10 @@ const headers = { } const payload = { - refundVariant: 'BTC', - paymentMethod: 'CurrentRate' + refundVariant: 'CurrentRate', + paymentMethod: 'BTC' } + fetch(btcpayServerUrl + apiEndpoint, { method: 'POST', headers: headers, @@ -190,6 +188,7 @@ fetch(btcpayServerUrl + apiEndpoint, { .then(response => response.json()) .then(data => { console.log(data) + res.send(data) }) ``` @@ -203,13 +202,13 @@ Creating a new user can be done by using [this endpoint](https://docs.btcpayserv ```JS const btcpayServerUrl = 'https://mainnet.demo.btcpayserver.org' -const AdminApiKey = 'YOUR_ADMIN_API_KEY' +const adminApiKey = 'YOUR_ADMIN_API_KEY' const apiEndpoint = '/api/v1/users' const headers = { 'Content-Type': 'application/json', - Authorization: 'token ' + apiKey + Authorization: 'token ' + adminApiKey } const payload = { @@ -226,6 +225,7 @@ fetch(btcpayServerUrl + apiEndpoint, { .then(response => response.json()) .then(data => { console.log(data) + res.send(data) }) ``` @@ -238,8 +238,8 @@ For example: If we want to [create a new store](https://docs.btcpayserver.org/AP As mentioned above, you can do this through the BTCPay Server UI of your instance, but let's do it through the API using [this endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/ApiKeys_CreateUserApiKey) where we with our admin API key create an API key for our new user. ```js -const btcpayserverUrl = 'https://mainnet.demo.btcpayserver.org' -const AdminApiKey = 'YOUR_ADMIN_API_KEY' +const btcpayServerUrl = 'https://mainnet.demo.btcpayserver.org' +const adminApiKey = 'YOUR_ADMIN_API_KEY' const email = 'satoshi.nakamoto@example.com' const apiEndpoint = `/api/v1/users/${email}/api-keys` @@ -254,7 +254,7 @@ const payload = { permissions: ['btcpay.store.canmodifystoresettings'] } -fetch(btcpayserverUrl + apiEndpoint, { +fetch(btcpayServerUrl + apiEndpoint, { method: 'POST', headers: headers, body: JSON.stringify(payload) @@ -262,6 +262,7 @@ fetch(btcpayserverUrl + apiEndpoint, { .then(response => response.json()) .then(data => { console.log(data) // returns apiKey + res.send(data) }) ``` @@ -291,6 +292,7 @@ fetch(btcpayServerUrl + apiEndpoint, { .then(response => response.json()) .then(data => { console.log(data) + res.send(data) }) ``` @@ -299,7 +301,7 @@ fetch(btcpayServerUrl + apiEndpoint, { We can use the new apikey to [read store](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Stores_GetStore) information: ```JS -const btcpayserverUrl = 'https://mainnet.demo.btcpayserver.org' +const btcpayServerUrl = 'https://mainnet.demo.btcpayserver.org' const userApiKey = 'USER_API_KEY' // From previous step const storeId = 'STORE_ID' // From previous step @@ -317,5 +319,6 @@ fetch(btcpayServerUrl + apiEndpoint, { .then(response => response.json()) .then(data => { console.log(data) + res.send(data) }) ``` From e5b6fab5089d4e3690f877aee471dfeeb362ad9e Mon Sep 17 00:00:00 2001 From: ndeet Date: Thu, 25 Apr 2024 10:56:41 +0200 Subject: [PATCH 5/6] Fixing bugs during PHP examples testing. --- docs/Development/GreenfieldExample-PHP.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/docs/Development/GreenfieldExample-PHP.md b/docs/Development/GreenfieldExample-PHP.md index 7350b3ff9c..803c4fa45a 100644 --- a/docs/Development/GreenfieldExample-PHP.md +++ b/docs/Development/GreenfieldExample-PHP.md @@ -42,7 +42,6 @@ $storeId = 'STORE_ID'; $amount = 10; $currency = 'USD'; $orderId = 'SN21420'; -$buyerEmail = 'satoshi.nakamoto@example.com'; try { $client = new \BTCPayServer\Client\Invoice($host, $apiKey); @@ -51,8 +50,7 @@ try { $storeId, $currency, \BTCPayServer\Util\PreciseNumber::parseString($amount), - $orderId, - $buyerEmail + $orderId ) ); } catch (\Throwable $e) { @@ -174,7 +172,7 @@ $password = 'SuperSecurePasswordsShouldBeQuiteLong123'; $isAdministrator = false; try { - $client = new \BTCPayServer\Client\User($host, $apiKey); + $client = new \BTCPayServer\Client\User($host, $adminApiKey); var_dump( $client->createUser($email, $password, $isAdministrator) ); @@ -199,7 +197,7 @@ $userEmail = 'satoshi.nakamoto@example.com'; $adminApiKey = 'ADMIN_API_KEY'; try { - $client = new \BTCPayServer\Client\Apikey($host, $adminApiKey); + $client = new \BTCPayServer\Client\ApiKey($host, $adminApiKey); $generatedApiKey = $client->createApiKeyForUser($userEmail, 'api generated', ['btcpay.store.canmodifystoresettings']); } catch (\Throwable $e) { echo "Error: " . $e->getMessage(); @@ -239,7 +237,7 @@ $storeId = 'STORE_ID'; // From previous step try { $client = new \BTCPayServer\Client\Store($host, $userApiKey); - var_dump($client->getStore($storeId); + var_dump($client->getStore($storeId)); } catch (\Throwable $e) { echo "Error: " . $e->getMessage(); } From 35ed531616a1bd934024f7227d41cce090d09b69 Mon Sep 17 00:00:00 2001 From: ndeet Date: Thu, 25 Apr 2024 11:08:44 +0200 Subject: [PATCH 6/6] Fixes after review. --- docs/Development/GreenFieldExample-NodeJS.md | 6 +++--- docs/Development/GreenFieldExample.md | 2 +- docs/Development/GreenfieldExample-PHP.md | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/Development/GreenFieldExample-NodeJS.md b/docs/Development/GreenFieldExample-NodeJS.md index e729de3a94..09405e3c37 100644 --- a/docs/Development/GreenFieldExample-NodeJS.md +++ b/docs/Development/GreenFieldExample-NodeJS.md @@ -29,7 +29,7 @@ The following examples will show you how to create a basic eCommerce flow using ### Create an invoice -We create an invoice using the [create invoice endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Invoices_CreateInvoice). This is a simple example but you can set a lot more data like order id, +We create an invoice using the [create invoice endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Invoices_CreateInvoice). This is a simple example but you can set a lot more data like order id, buyer email or custom metadata. That said, don't store redundant data on the invoice to prevent data leaks in case of a hack. E.g. in most cases it makes no sense to store the customer address on your eCommerce system and also on the BTCPay invoice. ```JS const btcpayServerUrl = 'https://mainnet.demo.btcpayserver.org' @@ -196,7 +196,7 @@ fetch(btcpayServerUrl + apiEndpoint, { Here we assume you are an ambassador and host BTCPay Server for your users. You manage your users on your own system and want to create a user and set email and password for their BTCPay Server login. Then using the same credentials to create a store and an API key on behalf of that user. -## Create a new user +### Create a new user Creating a new user can be done by using [this endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Users_CreateUser). @@ -266,7 +266,7 @@ fetch(btcpayServerUrl + apiEndpoint, { }) ``` -## Create a new store +### Create a new store Now, we can use the api key to [create a new store](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Stores_CreateStore). diff --git a/docs/Development/GreenFieldExample.md b/docs/Development/GreenFieldExample.md index 49c6d96e31..ff73c0f042 100644 --- a/docs/Development/GreenFieldExample.md +++ b/docs/Development/GreenFieldExample.md @@ -28,7 +28,7 @@ The following examples will show you how to create a basic eCommerce flow using ### Create an invoice -We create an invoice using the [create invoice endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Invoices_CreateInvoice). This is a simple example but you can set a lot more data like order id, +We create an invoice using the [create invoice endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Invoices_CreateInvoice). This is a simple example but you can set a lot more data like order id, buyer email or custom metadata. That said, don't store redundant data on the invoice to prevent data leaks in case of a hack. E.g. in most cases it makes no sense to store the customer address on your eCommerce system and also on the BTCPay invoice. ```bash BTCPAY_INSTANCE="https://mainnet.demo.btcpayserver.org" diff --git a/docs/Development/GreenfieldExample-PHP.md b/docs/Development/GreenfieldExample-PHP.md index 803c4fa45a..8655f5ce4c 100644 --- a/docs/Development/GreenfieldExample-PHP.md +++ b/docs/Development/GreenfieldExample-PHP.md @@ -31,7 +31,7 @@ The following examples will show you how to create a basic eCommerce flow using ### Create an invoice -We create an invoice using the [create invoice endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Invoices_CreateInvoice). This is a simple example but you can set a lot more data like order id, +We create an invoice using the [create invoice endpoint](https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Invoices_CreateInvoice). This is a simple example but you can set a lot more data like order id, buyer email or custom metadata. That said, don't store redundant data on the invoice to prevent data leaks in case of a hack. E.g. in most cases it makes no sense to store the customer address on your eCommerce system and also on the BTCPay invoice. ```PHP require __DIR__ . './vendor/autoload.php';