Compare commits

..

No commits in common. "master" and "old-master" have entirely different histories.

42 changed files with 5092 additions and 837 deletions

1
.gitignore vendored
View File

@ -11,4 +11,3 @@
.buildpath
composer.lock
composer.phar
/.idea

View File

@ -1,7 +1,3 @@
# === Warning ===
This is the old BitPay based PHP client and should be considered deprecated (even though it currently still works). If you are building something from scratch, [use the new Greenfield API](https://github.com/btcpayserver/btcpayserver-greenfield-php).
btcpayserver/btcpayserver-php-client
=================
@ -16,24 +12,12 @@ btcpayserver/btcpayserver-php-client
[![Total Downloads](https://poser.pugx.org/btcpayserver/btcpayserver-php-client/downloads.svg)](https://packagist.org/packages/btcpayserver/btcpayserver-php-client)
[![Latest Unstable Version](https://poser.pugx.org/btcpayserver/btcpayserver-php-client/v/unstable.svg)](https://packagist.org/packages/btcpayserver/btcpayserver-php-client)
This is a self-contained PHP implementation of BTCPayServer's cryptographically secure API: https://github.com/btcpayserver/btcpayserver-doc/blob/master/docs/CustomIntegration.md
This is a self-contained PHP implementation of BTCPayServer's cryptographically secure API: https://github.com/btcpayserver/btcpayserver-doc/blob/master/CustomIntegration.md
# Before you start
If your application requires BitPay compatibility go to this repository instead https://github.com/btcpayserver/php-bitpay-client
The files in "examples" are migrated from previous versions and are UNTESTED. If someone can review the example files and improve them, please help out.
# Important upgrade notes
## Version 0.2.0
- The latest changes made in BitPay's v4 API are now reflected in this API.
- If you previously had "401 unauthorized" issues with this API, these should now be fixed.
- This PHP API no longer depends on Symfony, making this framework independent. If you were using this API in combination with Symfony and require a Symfony service, you can get the old files from the `old-master` branch. We recommended you to keep the Symfony stuff separate.
## Version 0.1.2
- Previous versions were not numbered.
# Installation
## Composer
@ -56,6 +40,24 @@ See https://github.com/btcpayserver/btcpayserver-php-client/tree/master/examples
# Usage
## Autoloader
To use the library's autoloader (which doesn't include composer dependencies)
instead of composer's autoloader, use the following code:
```php
<?php
$autoloader = __DIR__ . '/relative/path/to/src/BTCPayServer/Autoloader.php';
if (true === file_exists($autoloader) &&
true === is_readable($autoloader))
{
require_once $autoloader;
\BTCPayServer\Autoloader::register();
} else {
throw new Exception('BTCPayServer Library could not be loaded');
}
```
## Documentation
Please see the ``docs`` directory for information on how to use this library
@ -68,3 +70,27 @@ https://github.com/btcpayserver/btcpayserver-php-client/blob/master/examples/tut
# Support
* https://github.com/btcpayserver/btcpayserver-php-client/issues
# License
The MIT License (MIT)
Copyright (c) 2017 BTCPayServer, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1 +1 @@
1.0.0
UPDATE THIS ACCORDINGLY

View File

@ -25,7 +25,9 @@
"ext-bcmath": "*",
"ext-curl": "*",
"ext-json": "*",
"ext-openssl": "*"
"ext-openssl": "*",
"symfony/config": "^2.3 || ^3.0 || ^4.0",
"symfony/dependency-injection": "^2.3 || ^3.0 || ^4.0"
},
"require-dev": {
"behat/behat": "2.5.*@stable",
@ -35,12 +37,11 @@
"fabpot/goutte": "~1.0.4",
"behat/mink-goutte-driver": "1.*",
"phpmd/phpmd": "~2.1.3",
"phpunit/phpunit": "~4.8.35",
"phpunit/phpunit": "~4.3.1",
"fzaninotto/faker": "~1.4.0",
"mikey179/vfsstream": "~1.4.0",
"mikey179/vfsStream": "~1.4.0",
"squizlabs/php_codesniffer": "~1.5.5",
"satooshi/php-coveralls": "~0.6.1",
"symfony/phpunit-bridge": "^4.0"
"satooshi/php-coveralls": "~0.6.1"
},
"suggest": {
"ext-gmp": "Quickest PHP math extension for doing computationally-expensive work."

View File

@ -16,16 +16,30 @@ require __DIR__ . '/../vendor/autoload.php';
* Create an Item object that will be used later
*/
$item = new \BTCPayServer\Item();
$item->setCode('skuNumber')->setDescription('General Description of Item')->setPrice('1.99');
$item
->setCode('skuNumber')
->setDescription('General Description of Item')
->setPrice('1.99');
/**
* Create Buyer object that will be used later.
*/
$buyer = new \BTCPayServer\Buyer();
$buyer->setFirstName('Some')->setLastName('Customer')->setPhone('555-5555-5555')->setEmail('test@test.com')->setAddress(array(
$buyer
->setFirstName('Some')
->setLastName('Customer')
->setPhone('555-5555-5555')
->setEmail('test@test.com')
->setAddress(
array(
'123 Main St',
'Suite 1',
))->setCity('Atlanta')->setState('GA')->setZip('30120')->setCountry('US');
)
)
->setCity('Atlanta')
->setState('GA')
->setZip('30120')
->setCountry('US');
/**
* Create the invoice
@ -36,7 +50,8 @@ $invoice->setItem($item);
// Add the buyers info to invoice
$invoice->setBuyer($buyer);
// Configure the rest of the invoice
$invoice->setOrderId('OrderIdFromYourSystem')
$invoice
->setOrderId('OrderIdFromYourSystem')
// You will receive IPN's at this URL, should be HTTPS for security purposes!
->setNotificationUrl('https://store.example.com/btcpayserver/callback');
@ -51,16 +66,31 @@ $currency->setCode('USD');
$invoice->setCurrency($currency);
/**
* Create a new client. You can see the example of how to configure this using
* a yml file as well.
* To load up keys that you have previously saved, you need to use the same
* storage engine. You also need to tell it the location of the key you want
* to load.
*/
$btcpay = new \BTCPayServer\BTCPayServer(__DIR__ . '/config.yml');
$storageEngine = new \BTCPayServer\Storage\FilesystemStorage();
$privateKey = $storageEngine->load('/tmp/private.key');
$publicKey = $storageEngine->load('/tmp/public.key');
/**
* Create the client that will be used to send requests to BitPay's API
* Create a new client.
*/
$btcpay = new \BTCPayServer\BTCPayServer();
/**
* Create the client that will be used to send requests to BTCPayServer's API
*/
$client = $btcpay->get('client');
$client->setPrivateKey($privateKey);
$client->setPublicKey($publicKey);
/**
* Add your btcpayserver url
*/
$client->setUri('https://btcpay.server/');
/**
* You will need to set the token that was returned when you paired your
* keys.
@ -73,4 +103,8 @@ $client->setToken($token);
// Send invoice
$client->createInvoice($invoice);
var_dump((string)$client->getRequest(), (string)$client->getResponse(), $invoice);
var_dump(
(string) $client->getRequest(),
(string) $client->getResponse(),
$invoice
);

View File

@ -1,6 +1,6 @@
<?php
/**
* Copyright (c) 2014-2015 BitPay
* Copyright (c) 2014-2015 BTCPayServer
*/
require __DIR__ . '/../vendor/autoload.php';
@ -11,9 +11,9 @@ require __DIR__ . '/../vendor/autoload.php';
* examples can be used to store keys in the database or other places. In
* this example, however, the keys are not persisted on disk or in a database.
*/
$private = new \BTCPayServer\PrivateKey('/tmp/private_key.key');
$public = new \BTCPayServer\PublicKey('/tmp/public_key.key');
$sin = new \BTCPayServer\SinKey('/tmp/sin.key');
$private = new \BTCPayServer\PrivateKey('/tmp/private.key');
$public = new \BTCPayServer\PublicKey('/tmp/public.key');
$sin = new \BTCPayServer\SinKey('/tmp/sin.key');
// Generate Private Key values
$private->generate();
@ -30,7 +30,7 @@ printf("Public Key: %s\n", $public);
printf("Private Key: %s\n", $private);
printf("Sin Key: %s\n\n", $sin);
$manager = new \BTCPayServer\KeyManager(new \BTCPayServer\Storage\EncryptedFilesystemStorage('TopSecretPassword'));
$manager = new \BTCPayServer\KeyManager(new \BTCPayServer\Storage\EncryptedFilesystemStorage('dN$8WNaT}j<gD3*q'));
$manager->persist($private);
$manager->persist($public);

View File

@ -1,6 +1,6 @@
<?php
/**
* Copyright (c) 2014-2015 BitPay
* Copyright (c) 2014-2015 BTCPayServer
*/
/**
@ -13,39 +13,45 @@
require __DIR__ . '/../vendor/autoload.php';
$time = gmdate("Y-m-d\TH:i:s\.", 1414691179) . "000Z";
$time = gmdate("Y-m-d\TH:i:s\.", 1414691179)."000Z";
$token = new \BTCPayServer\Token();
$token->setFacade('payroll')->setToken('<api token>'); //this is a special api that requires a explicit payroll relationship with BitPay
$token
->setFacade('payroll')
->setToken('<your payroll facade-enable token>'); //this is a special api that requires a explicit payroll relationship with BTCPayServer
$instruction1 = new \BTCPayServer\PayoutInstruction();
$instruction1->setAmount(100)->setAddress('2NA5EVH9HHHhM5RxSEWf54gP4v397EmFTxi')->setLabel('Paying Someone');
$instruction1
->setAmount(100)
->setAddress('2NA5EVH9HHHhM5RxSEWf54gP4v397EmFTxi')
->setLabel('Paying Chris');
$payout = new \BTCPayServer\Payout();
$payout->setEffectiveDate($time)->setAmount(100)->setCurrency(new \BTCPayServer\Currency('USD'))->setPricingMethod('bitcoinbestbuy')->setReference('a reference, can be json')->setNotificationEmail('joshlewis@gmail.com')->setNotificationUrl('https://example.com/ipn.php')->setToken($token)->addInstruction($instruction1);
$payout
->setEffectiveDate($time)
->setAmount(100)
->setCurrency(new \BTCPayServer\Currency('USD'))
->setPricingMethod('bitcoinbestbuy')
->setReference('a reference, can be json')
->setNotificationEmail('me@example.com')
->setNotificationUrl('https://example.com/ipn.php')
->setToken($token)
->addInstruction($instruction1);
#$private = new \BTCPayServer\PrivateKey();
#$private->setHex('5555550968bc659873d723374213fa5bf7a30c24f0f0713aa798eb7daa7230fc');
//this is your private key in some form (see GetKeys.php)
$private = new \BTCPayServer\PrivateKey();
$private->setHex('662be90968bc659873d723374213fa5bf7a30c24f0f0713aa798eb7daa7230fc'); //this is your private key in some form (see GetKeys.php)
#$public = new \BTCPayServer\PublicKey();
#$public->generate($private);
$storageEngine = new \BTCPayServer\Storage\EncryptedFilesystemStorage('TopSecretPassword');
$private = $storageEngine->load('/tmp/private_key.key');
#$public = $storageEngine->load('/tmp/public_key.key');
#error_log('$private '.$private);
$public = new \BTCPayServer\PublicKey();
$public->generate($private);
$adapter = new \BTCPayServer\Client\Adapter\CurlAdapter();
$btcpay = new \BTCPayServer\BTCPayServer();
$client = new \BTCPayServer\Client\Client();
$client->setPrivateKey($private);
$client->setPublicKey($public);
$client->setUri('https://btcpay.server/');
$client->setAdapter($adapter);
$client->createPayout($payout);

View File

@ -1,13 +1,14 @@
<?php
/**
* Copyright (c) 2014-2015 BitPay
* Copyright (c) 2014-2015 BTCPayServer
*/
require __DIR__ . '/../vendor/autoload.php';
$btcpay = new \BTCPayServer\BTCPayServer(__DIR__ . '/config.yml');
$client = $btcpay->get('client');
$btcpay = new \BTCPayServer\BTCPayServer(__DIR__ . '/config.yml');
$client = $btcpay->get('client');
$client->setUri('https://btcpay.server/');
$currencies = $client->getCurrencies();
/** @var \BTCPayServer\Currency $currencies [0] * */
/** @var \BTCPayServer\Currency $currencies[0] **/
var_dump($currencies[0]);

View File

@ -1,13 +1,13 @@
<?php
/**
* Copyright (c) 2014-2016 BitPay
* Copyright (c) 2014-2016 BTCPayServer
*/
require __DIR__ . '/../vendor/autoload.php';
$private = new \BTCPayServer\PrivateKey();
//if you've got a hex-encoded private key string, you can use it to create a private key
$private->setHex('5555550968bc659873d723374213fa5bf7a30c24f0f0713aa798eb7daa7230fc');
$private->setHex('662be90968bc659873d723374213fa5bf7a30c24f0f0713aa798eb7daa7230fc');
$public = new \BTCPayServer\PublicKey();
$public->generate($private);
$sin = $public->getSin();
@ -16,17 +16,14 @@ printf("Public Key: %s\n", $public);
printf("Private Key: %s\n", $private);
printf("Sin Key: %s\n\n", $sin);
$keypair = array(
$private->getHex(),
$public->getHex()
);
$keypair = array($private->getHex(), $public->getHex());
printf("PEM keypair: %s\n", $private->pemEncode($keypair));
// -or- if you've got a PEM-encoded text file containing your key pair, we can use this
/*
$keys = file_get_contents(getenv('HOME') . '/.php-bitpay-client/key.pem');
$keys = file_get_contents(getenv('HOME') . '/.php-btcpay-client/key.pem');
if (isset($keys) && strlen($keys) > 0) {
$keys = chop($keys);
@ -37,4 +34,3 @@ if (isset($keys) && strlen($keys) > 0) {
printf("Private Key: %s\n", $private);
printf("Sin Key: %s\n\n", $private->getPublicKey()->getSin());
}
*/

View File

@ -1,6 +1,6 @@
<?php
/**
* Copyright (c) 2014-2015 BitPay
* Copyright (c) 2014-2015 BTCPayServer
*/
require __DIR__ . '/../vendor/autoload.php';
@ -8,7 +8,7 @@ require __DIR__ . '/../vendor/autoload.php';
$client = new \BTCPayServer\Client\Client();
$client->setAdapter(new \BTCPayServer\Client\Adapter\CurlAdapter());
$request = new \BTCPayServer\Client\Request();
$request->setHost('test.btcpayserver.com');
$request->setUri('https://btcpay.server/');
$request->setMethod(\BTCPayServer\Client\Request::METHOD_GET);
$request->setPath('rates/USD');

View File

@ -1,6 +1,6 @@
<?php
/**
* Copyright (c) 2014-2015 BitPay
* Copyright (c) 2014-2015 BTCPayServer
*/
/**
@ -14,25 +14,41 @@
require __DIR__ . '/../vendor/autoload.php';
/**
* To load up keys that you have previously saved, you need to use the same
* storage engine. You also need to tell it the location of the key you want
* to load.
*/
$storageEngine = new \BTCPayServer\Storage\FilesystemStorage();
$privateKey = $storageEngine->load('/tmp/btcpayserver.pri');
$publicKey = $storageEngine->load('/tmp/btcpayserver.pub');
/**
* Create a new client. You can see the example of how to configure this using
* a yml file as well.
*/
$btcpay = new \BTCPayServer\BTCPayServer(array(
$btcpay = new \BTCPayServer\BTCPayServer(
array(
'btcpay' => array(
'public_key' => '/tmp/btcpayserver.pub',
//see tutorial/001.php and 002.php
'public_key' => '/tmp/btcpayserver.pub', //see tutorial/001.php and 002.php
'private_key' => '/tmp/btcpayserver.pri',
'key_storage' => 'BTCPayServer\Storage\EncryptedFilesystemStorage',
'key_storage_password' => 'YourTopSecretPassword'
)
));
)
);
/**
* Create the client that will be used to send requests to BitPay's API
* Create the client that will be used to send requests to BTCPayServer's API
*/
$client = $btcpay->get('client');
$client->setPrivateKey($privateKey);
$client->setPublicKey($publicKey);
/**
* Add your btcpayserver url
*/
$client->setUri('https://btcpay.server/');
$tokens = $client->getTokens();
print_r($tokens);

View File

@ -1,6 +1,6 @@
<?php
/**
* Copyright (c) 2014-2015 BitPay
* Copyright (c) 2014-2015 BTCPayServer
*/
/**

View File

@ -1,18 +1,16 @@
<?php
/**
* Copyright (c) 2014-2015 BitPay
* Copyright (c) 2014-2015 BTCPayServer
*/
require __DIR__ . '/../vendor/autoload.php';
// When running bitpay on your local server
// Customize the curl options
$curl_options = array(
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
);
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
);
// If nothing is passed into the CurlAdapter
// If nothing is passed into the CurlAdapter
// then default values are used
$adapter = new BTCPayServer\Client\Adapter\CurlAdapter($curl_options);

View File

@ -1,24 +1,22 @@
<?php
require __DIR__ . '/../vendor/autoload.php';
#require __DIR__.'/../../vendor/autoload.php';
#$storageEngine = new \BTCPayServer\Storage\FilesystemStorage();
$storageEngine = new \BTCPayServer\Storage\EncryptedFilesystemStorage('YourTopSecretPassword');
$storageEngine = new \BTCPayServer\Storage\FilesystemStorage();
$private = $storageEngine->load('/tmp/private.key');
$public = new \BTCPayServer\PublicKey('/tmp/public.key');
$private = $storageEngine->load('/tmp/bitpay.pri');
$public = new \BTCPayServer\PublicKey('/tmp/bitpay.pub');
error_log('$private ' . $private);
$public->setPrivateKey($private);
$public->generate();
printf("Public Key: %s\n", $public);
printf("Private Key: %s\n", $private);
$message = 'https://test.bitpay.com/subscriptions{"schedule":"weekly","token":"some token","billData":{"currency":"USD","price":"2.00","quantity":1}}';
$message = 'https://test.btcpayserver.com/subscriptions{"schedule":"weekly","token":"some token","billData":{"currency":"USD","price":"2.00","quantity":1}}';
$signedMessage = $private->sign($message);
error_log('message to be signed:: ' . $message . "\n");
error_log('signed message:: ' . $signedMessage);
print_r('message to be signed:: ' . $message . "\n");
print_r('signed message:: ' . $signedMessage);

View File

@ -1,10 +1,10 @@
####
# Copyright (c) 2014-2015 BitPay
# Copyright (c) 2014-2015 BTCPayServer
#
# Example config using a yml file
#
bitpay:
network: testnet
public_key: /tmp/bitpay.pub
private_key: /tmp/bitpay.pri
key_storage_password: YourTopSecretPassword
btcpayserver:
network: testnet
public_key: /tmp/btcpayserver.pub
private_key: /tmp/btcpayserver.pri
key_storage_password: YourTopSecretPassword

View File

@ -1,50 +1,50 @@
<?php
/**
* 001 - Generate keys
*
* This script needs to be run only once per BTCPayServer setup.
* For every next request which you´ll send to the BTCPay Server
* the request as to be complemented with these keys.
* Copyright (c) 2014-2015 BTCPayServer
*
* 001 - Generate and Persist Keys
*
* Requirements:
* - Basic PHP Knowledge
* - if you have not already done so, please run `composer.phar install`
* - Basic PHP knowledge
*/
use BTCPayServer\PrivateKey;
use BTCPayServer\PublicKey;
use BTCPayServer\Storage\EncryptedFilesystemStorage;
require __DIR__ . '/../../vendor/autoload.php';
define('KEY_DIR', __DIR__ . '/tmp'); // directory to store your key files
define('PRIVATE_KEY_NAME', '/btcpay.pri');
define('PUBLIC_KEY_NAME', '/btcpay.pub');
define('PASSWORD', 'TopSecretPassword'); // change this to a strong password
// Start by creating a PrivateKey object
$privateKey = PrivateKey::create(KEY_DIR . PRIVATE_KEY_NAME)->generate();
// then create a PublicKey Object
$publicKey = new PublicKey(KEY_DIR . PUBLIC_KEY_NAME);
// inject the private key into the public key
$publicKey->setPrivateKey($privateKey);
// generate the public key
$publicKey->generate();
// If you have not already done so, please run `composer.phar install`
require __DIR__.'/../../vendor/autoload.php';
/**
* NOTE: You can again do all of this with one line of code like so:
* $publicKey = \BTCPayServer\PublicKey::create(KEY_DIR . PUBLIC_KEY_NAME)->setPrivateKey($privateKey)->generate();
*/
* Start by creating a PrivateKey object
*/
$privateKey = new \BTCPayServer\PrivateKey('/tmp/btcpayserver.pri');
// Generate a random number
$privateKey->generate();
// You can generate a private key with only one line of code like so
$privateKey = \BTCPayServer\PrivateKey::create('/tmp/btcpayserver.pri')->generate();
// NOTE: This has overridden the previous $privateKey variable, although its
// not an issue in this case since we have not used this key for
// anything yet.
/**
* Once we have a private key, a public key is created from it.
*/
$publicKey = new \BTCPayServer\PublicKey('/tmp/btcpayserver.pub');
// Inject the private key into the public key
$publicKey->setPrivateKey($privateKey);
// Generate the public key
$publicKey->generate();
// NOTE: You can again do all of this with one line of code like so:
// `$publicKey = \BTCPayServer\PublicKey::create('/tmp/btcpayserver.pub')->setPrivateKey($privateKey)->generate();`
/**
* Now that you have a private and public key generated, you will need to store
* them somewhere. This option is up to you and how you store them is up to
* them somewhere. This optioin is up to you and how you store them is up to
* you. Please be aware that you MUST store the private key with some type
* of security. If the private key is compromised you will need to repeat this
* of security. If the private key is comprimised you will need to repeat this
* process.
*/
@ -52,12 +52,12 @@ $publicKey->generate();
* It's recommended that you use the EncryptedFilesystemStorage engine to persist your
* keys. You can, of course, create your own as long as it implements the StorageInterface
*/
$storageEngine = new EncryptedFilesystemStorage(PASSWORD);
$storageEngine = new \BTCPayServer\Storage\EncryptedFilesystemStorage('YourTopSecretPassword');
$storageEngine->persist($privateKey);
$storageEngine->persist($publicKey);
/**
* This is all for the first tutorial, you can run this script from the command
* line `php examples/tutorial/001.php` This will generate and create two files
* located at `/tmp/btcpay.pri` and `/tmp/btcpay.pub`
*/
* located at `/tmp/btcpayserver.pri` and `/tmp/btcpayserver.pub`
*/

View File

@ -0,0 +1,110 @@
<?php
/**
* Copyright (c) 2014-2015 BTCPayServer
*
* 002 - Pairing
*
* Requirements:
* - Basic PHP Knowledge
* - Private and Public keys from 001.php
* - Account on https://testnet.demo.btcpayserver.org/
* - Pairing code
*/
require __DIR__.'/../../vendor/autoload.php';
/**
* To load up keys that you have previously saved, you need to use the same
* storage engine. You also need to tell it the location of the key you want
* to load.
*/
$storageEngine = new \BTCPayServer\Storage\EncryptedFilesystemStorage('YourTopSecretPassword');
$privateKey = $storageEngine->load('/tmp/btcpayserver.pri');
$publicKey = $storageEngine->load('/tmp/btcpayserver.pub');
/**
* Create the client, there's a lot to it and there are some easier ways, I am
* showing the long form here to show how various things are injected into the
* client.
*/
$client = new \BTCPayServer\Client\Client();
/**
* The adapter is what will make the calls to BTCPayServer and return the response
* from BTCPayServer. This can be updated or changed as long as it implements the
* AdapterInterface
*/
$adapter = new \BTCPayServer\Client\Adapter\CurlAdapter();
/**
* Now all the objects are created and we can inject them into the client
*/
$client->setPrivateKey($privateKey);
$client->setPublicKey($publicKey);
/**
* Add your btcpayserver url
*/
$client->setUri('https://btcpay.server/');
$client->setAdapter($adapter);
/**
* Visit https://testnet.demo.btcpayserver.org/api-tokens and create a new pairing code. Pairing
* codes can only be used once and the generated code is valid for only 24 hours.
*/
$pairingCode = 'InsertPairingCodeHere';
/**
* Currently this part is required, however future versions of the PHP SDK will
* be refactor and this part may become obsolete.
*/
$sin = \BTCPayServer\SinKey::create()->setPublicKey($publicKey)->generate();
/**** end ****/
try {
$token = $client->createToken(
array(
'pairingCode' => $pairingCode,
'label' => 'You can insert a label here',
'id' => (string) $sin,
)
);
} catch (\Exception $e) {
/**
* The code will throw an exception if anything goes wrong, if you did not
* change the $pairingCode value or if you are trying to use a pairing
* code that has already been used, you will get an exception. It was
* decided that it makes more sense to allow your application to handle
* this exception since each app is different and has different requirements.
*/
echo "Exception occured: " . $e->getMessage().PHP_EOL;
echo "Pairing failed. Please check whether you're trying to pair a production pairing code on test.".PHP_EOL;
$request = $client->getRequest();
$response = $client->getResponse();
/**
* You can use the entire request/response to help figure out what went
* wrong, but for right now, we will just var_dump them.
*/
echo (string) $request.PHP_EOL.PHP_EOL.PHP_EOL;
echo (string) $response.PHP_EOL.PHP_EOL;
/**
* NOTE: The `(string)` is include so that the objects are converted to a
* user friendly string.
*/
exit(1); // We do not want to continue if something went wrong
}
/**
* You will need to persist the token somewhere, by the time you get to this
* point your application has implemented an ORM such as Doctrine or you have
* your own way to persist data. Such as using a framework or some other code
* base such as Drupal.
*/
$persistThisValue = $token->getToken();
echo 'Token obtained: '.$persistThisValue.PHP_EOL;
/**
* Make sure you persist the token, you will need it for the next tutorial
*/

View File

@ -1,175 +0,0 @@
<?php
/**
* 002 - Pairing
*
* This script needs to be run only once per BTCPayServer setup.
* If you need to connect your web-store to a completely new
* BTCPayServer instance, this script will need to be run again.
*
* Requirements:
* - Basic PHP Knowledge
* - Private and Public keys from 001_generateKeys.php
* - Your "TopSecretPassword" which you used in 001_generateKeys.php
* - Account on a BTCPay Server
* - Pairing code
*/
use BTCPayServer\PrivateKey;
use BTCPayServer\PublicKey;
use BTCPayServer\Storage\EncryptedFilesystemStorage;
use BTCPayServer\Client\Client;
use BTCPayServer\Client\Adapter\CurlAdapter;
require __DIR__ . '/../../vendor/autoload.php';
define('KEY_DIR', __DIR__ . '/tmp'); // directory to store your key files
define('PRIVATE_KEY_NAME', '/btcpay.pri');
define('PUBLIC_KEY_NAME', '/btcpay.pub');
define('SIN_NAME', '/sin.key');
define('PASSWORD', 'TopSecretPassword'); // change this to a strong password
define('SERVER_URL', 'https://yourserver.domain.com'); // change to your server (no trailing slash)
define('SERVER_PORT', '443'); // change to your server port
define('PAIRING_CODE', '<PairingToken>'); // pairing code which you get in the admin panel of your btcpay server
define('PAIRING_LABEL', 'PairingToken'); // change to whatever you want
/**
* To load up keys that you have previously saved, you need to use the same
* storage engine. You also need to tell it the location of the key you want
* to load.
*/
$storageEngine = new EncryptedFilesystemStorage(PASSWORD);
$privateKey = $storageEngine->load(KEY_DIR . PRIVATE_KEY_NAME);
$publicKey = $storageEngine->load(KEY_DIR . PUBLIC_KEY_NAME);
/**
* Create the client, there's a lot to it and there are some easier ways, I am
* showing the long form here to show how various things are injected into the
* client.
*/
$client = new Client();
/**
* The adapter is what will make the calls to BitPay and return the response
* from BitPay. This can be updated or changed as long as it implements the
* AdapterInterface
*/
$adapter = new CurlAdapter();
/**
* Now all the objects are created and we can inject them into the client
*/
$client->setPrivateKey($privateKey);
$client->setPublicKey($publicKey);
$client->setUri(SERVER_URL . ':' . SERVER_PORT);
$client->setAdapter($adapter);
/**
* Visit https://YOURBTCPAYSERVER.com/api-tokens and create a new pairing code. Pairing
* codes can only be used once and the generated code is valid for only 24 hours.
*/
$pairingCode = PAIRING_CODE;
/**
* Currently this part is required, however future versions of the PHP SDK will
* be refactor and this part may become obsolete.
*/
$sin = new \BTCPayServer\SinKey(KEY_DIR . SIN_NAME);
$sin->setPublicKey($publicKey);
$sin->generate();
$facade = '';
// 'empty' will be POS
// payroll
// merchant
if (!$facade):
try {
$token = $client->createToken(array(
'pairingCode' => $pairingCode,
'label' => PAIRING_LABEL,
'id' => (string)$sin,
));
} catch (\Exception $e) {
/**
* The code will throw an exception if anything goes wrong, if you did not
* change the $pairingCode value or if you are trying to use a pairing
* code that has already been used, you will get an exception. It was
* decided that it makes more sense to allow your application to handle
* this exception since each app is different and has different requirements.
*/
echo "Exception occured: " . $e->getMessage() . PHP_EOL;
echo "Pairing failed. Please check whether you're trying to pair a production pairing code on test." . PHP_EOL;
$request = $client->getRequest();
$response = $client->getResponse();
/**
* You can use the entire request/response to help figure out what went
* wrong, but for right now, we will just var_dump them.
*/
echo (string)$request . PHP_EOL . PHP_EOL . PHP_EOL;
echo (string)$response . PHP_EOL . PHP_EOL;
/**
* NOTE: The `(string)` is include so that the objects are converted to a
* user friendly string.
*/
exit(1); // We do not want to continue if something went wrong
}
/**
* You will need to persist the token somewhere, by the time you get to this
* point your application has implemented an ORM such as Doctrine or you have
* your own way to persist data. Such as using a framework or some other code
* base such as Drupal.
*/
$persistThisValue = $token->getToken();
echo PHP_EOL . 'Token obtained: ' . $persistThisValue . PHP_EOL;
endif;
if ($facade == 'merchant' || $facade == 'payroll'):
try {
$token = $client->createToken(array(
'facade' => $facade,
'label' => PAIRING_LABEL,
'id' => (string)$sin,
));
echo "<pre>";
var_dump($token);
echo "</pre>";
$pairingCode = $token->GetpairingCode();
$url = SERVER_URL . '/api-access-request?pairingCode=' . $pairingCode;
echo "\n$url";
echo "\n";
echo 'Token obtained: ' . $token->getToken() . PHP_EOL;
} catch (\Exception $e) {
echo "Exception occured: " . $e->getMessage() . PHP_EOL;
echo "Pairing failed. Please check whether you're trying to pair a production pairing code on test." . PHP_EOL;
$request = $client->getRequest();
$response = $client->getResponse();
/**
* You can use the entire request/response to help figure out what went
* wrong, but for right now, we will just var_dump them.
*/
echo (string)$request . PHP_EOL . PHP_EOL . PHP_EOL;
echo (string)$response . PHP_EOL . PHP_EOL;
/**
* NOTE: The `(string)` is include so that the objects are converted to a
* user friendly string.
*/
exit(1); // We do not want to continue if something went wrong
}
endif;
/**
* Make sure you persist the token, you will need it for the next tutorial !
*/

View File

@ -1,59 +1,34 @@
<?php
/**
* Copyright (c) 2014-2015 BTCPayServer
*
* 003 - Creating Invoices
*
* Requirements:
* - Account on https://testnet.demo.btcpayserver.org
* - Basic PHP Knowledge
* - Private and Public keys from 001_generateKeys.php
* - Your "TopSecretPassword" which you used in 001_generateKeys.php
* - Account on a BTCPay Server
* - Token value obtained from 002_pairing.php
* - Private and Public keys from 001.php
* - Token value obtained from 002.php
*/
require __DIR__.'/../../vendor/autoload.php';
use BTCPayServer\PrivateKey;
use BTCPayServer\PublicKey;
use BTCPayServer\Storage\EncryptedFilesystemStorage;
use BTCPayServer\Client\Client;
use BTCPayServer\Client\Adapter\CurlAdapter;
use BTCPayServer\Token;
use BTCPayServer\Invoice;
use BTCPayServer\Buyer;
use BTCPayServer\Item;
use BTCPayServer\Currency;
require __DIR__ . '/../../vendor/autoload.php';
define('KEY_DIR', __DIR__ . '/tmp'); // directory to store your key files
define('PRIVATE_KEY_NAME', '/btcpay.pri');
define('PUBLIC_KEY_NAME', '/btcpay.pub');
define('SIN_NAME', '/sin.key');
define('PASSWORD', 'TopSecretPassword'); // change this to a strong password
define('SERVER_URL', 'https://yourserver.domain.com'); // change to your server (no trailing slash)
define('SERVER_PORT', '443'); // change to your server port
define('PAIRING_CODE', '<PairingToken>'); // pairing code which you get in the admin panel of your btcpay server
define('PAIRING_LABEL', 'PairingToken'); // change to whatever you want
define('TOKEN', '<ApiToken>'); // change to you token received in 002_pairing.php
define('IPN_CALLBACK', 'https://yourServer.com/ipn_callback.php');
$storageEngine = new EncryptedFilesystemStorage(PASSWORD);
$privateKey = $storageEngine->load(KEY_DIR . PRIVATE_KEY_NAME);
$publicKey = $storageEngine->load(KEY_DIR . PUBLIC_KEY_NAME);
$client = new Client();
$adapter = new CurlAdapter();
// See 002.php for explanation
$storageEngine = new \BTCPayServer\Storage\EncryptedFilesystemStorage('YourTopSecretPassword'); // Password may need to be updated if you changed it
$privateKey = $storageEngine->load('/tmp/btcpayserver.pri');
$publicKey = $storageEngine->load('/tmp/btcpayserver.pub');
$client = new \BTCPayServer\Client\Client();
$adapter = new \BTCPayServer\Client\Adapter\CurlAdapter();
$client->setPrivateKey($privateKey);
$client->setPublicKey($publicKey);
$client->setUri(SERVER_URL . ':' . SERVER_PORT);
$client->setUri('https://testnet.demo.btcpayserver.org/');
$client->setAdapter($adapter);
// ---------------------------
/**
* The last object that must be injected is the token object.
*/
$token = new Token();
$token->setToken(TOKEN);
$token = new \BTCPayServer\Token();
$token->setToken('UpdateThisValue'); // UPDATE THIS VALUE
/**
* Token object is injected into the client
@ -64,10 +39,11 @@ $client->setToken($token);
* This is where we will start to create an Invoice object, make sure to check
* the InvoiceInterface for methods that you can use.
*/
$invoice = new Invoice();
$invoice = new \BTCPayServer\Invoice();
$buyer = new Buyer();
$buyer->setEmail('buyeremail@test.com');
$buyer = new \BTCPayServer\Buyer();
$buyer
->setEmail('buyeremail@test.com');
// Add the buyers info to invoice
$invoice->setBuyer($buyer);
@ -75,42 +51,46 @@ $invoice->setBuyer($buyer);
/**
* Item is used to keep track of a few things
*/
$item = new Item();
$item->setCode('skuNumber')->setDescription('General Description of Item')->setPrice('1.99');
$item = new \BTCPayServer\Item();
$item
->setCode('skuNumber')
->setDescription('General Description of Item')
->setPrice('1.99');
$invoice->setItem($item);
/**
* BitPay supports multiple different currencies. Most shopping cart applications
* BTCPayServer supports multiple different currencies. Most shopping cart applications
* and applications in general have defined set of currencies that can be used.
* Setting this to one of the supported currencies will create an invoice using
* the exchange rate for that currency.
*
* @see https://test.bitpay.com/bitcoin-exchange-rates for supported currencies
* @see https://docs.btcpayserver.org/faq-and-common-issues/faq-general#which-cryptocurrencies-are-supported-in-btcpay for supported currencies
*/
$invoice->setCurrency(new Currency('USD'));
$invoice->setCurrency(new \BTCPayServer\Currency('USD'));
// Configure the rest of the invoice
$invoice->setOrderId('OrderIdFromYourSystem');
$invoice
->setOrderId('OrderIdFromYourSystem')
// You will receive IPN's at this URL, should be HTTPS for security purposes!
->setNotificationUrl('https://store.example.com/btcpayserver/callback');
// You will receive IPN's at this URL, should be HTTPS for security purposes!
$invoice->setNotificationUrl(IPN_CALLBACK);
/**
* Updates invoice with new information such as the invoice id and the URL where
* a customer can view the invoice.
*/
try {
echo "Creating invoice at your BTCPay Server now." . PHP_EOL;
echo "Creating invoice at BTCPayServer now.".PHP_EOL;
$client->createInvoice($invoice);
} catch (\Exception $e) {
echo "Exception occured: " . $e->getMessage() . PHP_EOL;
$request = $client->getRequest();
echo "Exception occured: " . $e->getMessage().PHP_EOL;
$request = $client->getRequest();
$response = $client->getResponse();
echo (string)$request . PHP_EOL . PHP_EOL . PHP_EOL;
echo (string)$response . PHP_EOL . PHP_EOL;
echo (string) $request.PHP_EOL.PHP_EOL.PHP_EOL;
echo (string) $response.PHP_EOL.PHP_EOL;
exit(1); // We do not want to continue if something went wrong
}
echo 'Invoice "' . $invoice->getId() . '" created, see ' . $invoice->getUrl() . PHP_EOL;
echo "Verbose details." . PHP_EOL;
echo 'Invoice "'.$invoice->getId().'" created, see '.$invoice->getUrl().PHP_EOL;
echo "Verbose details.".PHP_EOL;
print_r($invoice);

View File

@ -1,100 +1,112 @@
<?php
/**
* 004 - Hosted payment page: create & display invoice
* For details on displaying invoices, see https://bitpay.com/docs/display-invoice
* Copyright (c) 2014-2017 BTCPayServer
*
* 004 - Hosted payment page: create & display invoice
* For details on displaying invoices, see https://docs.btcpayserver.org/integrations/customintegration#modal-checkout
* Requirements:
* - Account on https://testnet.demo.btcpayserver.org
* - Basic PHP Knowledge
* - Private and Public keys from 001_generateKeys.php
* - Your "TopSecretPassword" which you used in 001_generateKeys.php
* - Account on a BTCPay Server
* - Token value obtained from 002_pairing.php
* - Private and Public keys from 001.php
* - Token value obtained from 002.php
* - A webserver to run the code. Running locally works with firefox, but not with Safari & Chrome
*/
require __DIR__.'/../../vendor/autoload.php';
use BTCPayServer\PrivateKey;
use BTCPayServer\PublicKey;
use BTCPayServer\Storage\EncryptedFilesystemStorage;
use BTCPayServer\Client\Client;
use BTCPayServer\Client\Adapter\CurlAdapter;
use BTCPayServer\Token;
use BTCPayServer\Invoice;
use BTCPayServer\Buyer;
use BTCPayServer\Item;
use BTCPayServer\Currency;
require __DIR__ . '/../../vendor/autoload.php';
define('KEY_DIR', __DIR__ . '/tmp'); // directory to store your key files
define('PRIVATE_KEY_NAME', '/btcpay.pri');
define('PUBLIC_KEY_NAME', '/btcpay.pub');
define('SIN_NAME', '/sin.key');
define('PASSWORD', 'TopSecretPassword'); // change this to a strong password
define('SERVER_URL', 'https://yourserver.domain.com'); // change to your server (no trailing slash)
define('SERVER_PORT', '443'); // change to your server port
define('PAIRING_CODE', '<PairingToken>'); // pairing code which you get in the admin panel of your btcpay server
define('PAIRING_LABEL', 'PairingToken'); // change to whatever you want
define('TOKEN', '<ApiToken>'); // change to you token received in 002_pairing.php
define('IPN_CALLBACK', 'https://yourServer.com/ipn_callback.php');
$storageEngine = new EncryptedFilesystemStorage(PASSWORD);
$privateKey = $storageEngine->load(KEY_DIR . PRIVATE_KEY_NAME);
$publicKey = $storageEngine->load(KEY_DIR . PUBLIC_KEY_NAME);
$client = new Client();
$adapter = new CurlAdapter();
// See 002.php for explanation
$storageEngine = new \BTCPayServer\Storage\EncryptedFilesystemStorage('YourTopSecretPassword'); // Password may need to be updated if you changed it
$privateKey = $storageEngine->load('/tmp/btcpayserver.pri');
$publicKey = $storageEngine->load('/tmp/btcpayserver.pub');
$client = new \BTCPayServer\Client\Client();
$adapter = new \BTCPayServer\Client\Adapter\CurlAdapter();
$client->setPrivateKey($privateKey);
$client->setPublicKey($publicKey);
$client->setUri(SERVER_URL . ':' . SERVER_PORT);
$client->setUri('https://btcpay.server/');
$client->setAdapter($adapter);
// ---------------------------
$token = new Token();
$token->setToken(TOKEN);
/**
* The last object that must be injected is the token object.
*/
$token = new \BTCPayServer\Token();
$token->setToken('UpdateThisValue'); // UPDATE THIS VALUE
/**
* Token object is injected into the client
*/
$client->setToken($token);
/**
* For more information about creating a invoice, please check 003_createInvoice.php
* The way we create the invoice here is the same as in the example before.
* This is where we will start to create an Invoice object, make sure to check
* the InvoiceInterface for methods that you can use.
*/
$invoice = new \BTCPayServer\Invoice();
$buyer = new \BTCPayServer\Buyer();
$buyerEmail = "buyeremail@test.com";
$buyer->setEmail($buyerEmail);
$invoice->setBuyer($buyer);
$item = new \BTCPayServer\Item();
$item->setCode('skuNumber')->setDescription('General Description of Item')->setPrice('1.99');
$invoice->setItem($item);
$invoice->setCurrency(new \BTCPayServer\Currency('USD'));
$invoice->setOrderId('OrderIdFromYourSystem');
$invoice->setNotificationUrl(IPN_CALLBACK);
$buyer
->setEmail($buyerEmail);
// Add the buyers info to invoice
$invoice->setBuyer($buyer);
/**
* Item is used to keep track of a few things
*/
$item = new \BTCPayServer\Item();
$item
->setCode('skuNumber')
->setDescription('General Description of Item')
->setPrice('1.99');
$invoice->setItem($item);
/**
* BTCPayServer supports multiple different currencies. Most shopping cart applications
* and applications in general have defined set of currencies that can be used.
* Setting this to one of the supported currencies will create an invoice using
* the exchange rate for that currency.
*
* @see https://docs.btcpayserver.org/faq-and-common-issues/faq-general#which-cryptocurrencies-are-supported-in-btcpay for supported currencies
*/
$invoice->setCurrency(new \BTCPayServer\Currency('USD'));
// Configure the rest of the invoice
$invoice
->setOrderId('OrderIdFromYourSystem')
// You will receive IPN's at this URL, should be HTTPS for security purposes!
->setNotificationUrl('https://store.example.com/btcpayserver/callback');
/**
* Updates invoice with new information such as the invoice id and the URL where
* a customer can view the invoice.
*/
try {
$client->createInvoice($invoice);
} catch (\Exception $e) {
$request = $client->getRequest();
$request = $client->getRequest();
$response = $client->getResponse();
echo (string)$request . PHP_EOL . PHP_EOL . PHP_EOL;
echo (string)$response . PHP_EOL . PHP_EOL;
echo (string) $request.PHP_EOL.PHP_EOL.PHP_EOL;
echo (string) $response.PHP_EOL.PHP_EOL;
exit(1); // We do not want to continue if something went wrong
}
?>
<html>
<head><title>BTCPay Server Modal Checkout</title></head>
<body>
<head><title>BTCPayServer - Modal CSS invoice demo</title></head>
<body bgcolor="rgb(21,28,111)" textcolor="rgb(255,255,255)">
<button onclick="openInvoice()">Pay Now</button>
<br><br><br>
For more information about BTCPay Server´s modal checkout, please see
<a href="https://docs.btcpayserver.org/CustomIntegration/#modal-checkout" target="_blank">
BTCPay Server Doc -> Custom Integration -> Modal Checkout
</a>
</body>
<script src="<?= SERVER_URL ?>/modal/btcpay.js"></script>
<script>
For more information about BTCPayServer's modal CSS invoice, please see <a href="https://docs.btcpayserver.org/integrations/customintegration#modal-checkout" target="_blank">https://btcpayserver.com/docs/display-invoice</a>
</body>
<script src="https://testnet.demo.btcpayserver.org/modal/btcpay.js"> </script>
<script>
function openInvoice() {
bitpay.setApiUrlPrefix(<?= SERVER_URL ?>)
bitpay.showInvoice("<?php echo $invoice->getId();?>");
var network = "testnet"
if (network == "testnet")
btcpayserver.setApiUrlPrefix("https://testnet.demo.btcpayserver.org")
else
btcpayserver.setApiUrlPrefix("https://btcpayserver.org/")
btcpayserver.showInvoice("<?php echo $invoice->getId();?>");
}
</script>
</script>
</html>

View File

@ -1,49 +0,0 @@
<?php
/**
* Copyright (c) 2014-2015 BitPay
*/
/**
* WARNING - This example will NOT work until you have generated your public
* keys and also see the documentation on how to save those keys.
*
* Also please be aware that you CANNOT create an invoice until you have paired
* the keys and received a token back. The token is usesd with the request.
*/
$key_dir = '/tmp';
require __DIR__ . '/../../vendor/autoload.php';
$time = gmdate("Y-m-d\TH:i:s\.", 1414691179) . "000Z";
$token = new \BTCPayServer\Token();
$token->setFacade('payroll')->setToken('your token goes here'); //this is a special api that requires a explicit payroll relationship with BitPay
$instruction1 = new \BTCPayServer\PayoutInstruction();
$instruction1->setAmount(100)->setAddress('2NA5EVH9HHHhM5RxSEWf54gP4v397EmFTxi')->setLabel('Paying Chris');
$payout = new \BTCPayServer\Payout();
$payout->setEffectiveDate($time)->setAmount(100)->setCurrency(new \BTCPayServer\Currency('USD'))->setPricingMethod('bitcoinbestbuy')->setReference('a reference, can be json')->setNotificationEmail('an email goes here')->setNotificationUrl('https://example.com/ipn.php')->setToken($token)->addInstruction($instruction1);
//this is your private key in some form (see GetKeys.php)
$storageEngine = new \BTCPayServer\Storage\EncryptedFilesystemStorage('TopSecretPassword');
$private = $storageEngine->load($key_dir . '/bitpay.pri');
$public = $storageEngine->load($key_dir . '/bitpay.pub');
//$network = new \BTCPayServer\Network\Testnet();
$adapter = new \BTCPayServer\Client\Adapter\CurlAdapter();
$btcpay = new \BTCPayServer\BTCPayServer();
$client = new \BTCPayServer\Client\Client();
$client->setPrivateKey($private);
$client->setPublicKey($public);
$client->setUri('https://my-btcpay-server.com');
$client->setAdapter($adapter);
$client->createPayout($payout);
print_r($payout);

View File

@ -1,20 +1,20 @@
<?php
/**
* Copyright (c) 2014-2017 BitPay
* Copyright (c) 2014-2017 BTCPayServer
*
* 004 - IPN logger
*
* Requirements:
* - Account on https://test.bitpay.com
* - Account on https://testnet.demo.btcpayserver.org
* - Baisic PHP Knowledge
* - Private and Public keys from 001.php
* - Token value obtained from 002.php
* - Invoice created & paid
*/
require __DIR__ . '/../../vendor/autoload.php';
require __DIR__.'/../../vendor/autoload.php';
$myfile = fopen("/tmp/BitPayIPN.log", "a");
$myfile = fopen("/tmp/BTCPayServerIPN.log", "a");
$raw_post_data = file_get_contents('php://input');
@ -29,9 +29,9 @@ if (false === $raw_post_data) {
$ipn = json_decode($raw_post_data);
if (true === empty($ipn)) {
fwrite($myfile, $date . " : Error. Could not decode the JSON payload from BitPay.\n");
fwrite($myfile, $date . " : Error. Could not decode the JSON payload from BTCPayServer.\n");
fclose($myfile);
throw new \Exception('Could not decode the JSON payload from BitPay.');
throw new \Exception('Could not decode the JSON payload from BTCPayServer.');
}
if (true === empty($ipn->id)) {
@ -40,17 +40,22 @@ if (true === empty($ipn->id)) {
throw new \Exception('Invalid BTCPayServer payment notification message received - did not receive invoice ID.');
}
// Now fetch the invoice from BitPay
// Now fetch the invoice from BTCPayServer
// This is needed, since the IPN does not contain any authentication
$client = new \BTCPayServer\Client\Client();
$adapter = new \BTCPayServer\Client\Adapter\CurlAdapter();
$client->setUri('https://my-btcpay-server.com');
$storageEngine = new \BTCPayServer\Storage\EncryptedFilesystemStorage('YourTopSecretPassword');
$privateKey = $storageEngine->load('/tmp/btcpayserver.pri');
$publicKey = $storageEngine->load('/tmp/btcpayserver.pub');
$client = new \BTCPayServer\Client\Client();
$adapter = new \BTCPayServer\Client\Adapter\CurlAdapter();
$client->setPrivateKey($privateKey);
$client->setPublicKey($publicKey);
$client->setUri('https://testnet.demo.btcpayserver.org/');
$client->setAdapter($adapter);
$token = new \BTCPayServer\Token();
$token->setToken('UpdateThisValue'); // UPDATE THIS VALUE
$client->setToken($token);
$token->setFacade('merchant');
/**
* This is where we will fetch the invoice object
@ -61,10 +66,9 @@ $invoiceStatus = $invoice->getStatus();
$invoiceExceptionStatus = $invoice->getExceptionStatus();
$invoicePrice = $invoice->getPrice();
fwrite($myfile, $date . " : IPN received for BitPay invoice " . $invoiceId . " . Status = " . $invoiceStatus . " / exceptionStatus = " . $invoiceExceptionStatus . " Price = " . $invoicePrice . "\n");
fwrite($myfile, "Raw IPN: " . $raw_post_data . "\n");
fwrite($myfile, $date . " : IPN received for BTCPayServer invoice ".$invoiceId." . Status = " .$invoiceStatus." / exceptionStatus = " . $invoiceExceptionStatus." Price = ". $invoicePrice." Tax Included = ". $taxIncluded."\n");
fwrite($myfile, "Raw IPN: ". $raw_post_data."\n");
//Respond with HTTP 200, so BitPay knows the IPN has been received correctly
//If BitPay receives <> HTTP 200, then BitPay will try to send the IPN again with increasing intervals for two more hours.
//Respond with HTTP 200, so BTCPayServer knows the IPN has been received correctly
//If BTCPayServer receives <> HTTP 200, then BTCPayServer will try to send the IPN again with increasing intervals for two more hours.
header("HTTP/1.1 200 OK");
?>

View File

@ -1,60 +1,59 @@
# Creating BitPay invoices - the tutorial
# Creating BTCPayServer invoices - the tutorial
==========================
## About this tutorial
This tutorial contains five scripts. These scripts allow you to do the following:
1) Create keys to communicate with BitPay's API
2) Pair your keys to your BitPay merchant account
3) Create BitPay invoices
4) Display a BitPay invoice using BitPay's hosted payment page
1) Create keys to communicate with BTCPayServer's API
2) Pair your keys to your BTCPayServer merchant account
3) Create BTCPayServer invoices
4) Display a BTCPayServer invoice using BTCPayServer's hosted payment page
5) Log Instant Payment Notifications (IPNs, also called webhooks)
Script 001 & 002 need to be executed once, to properly configure your local installation.
Script 003 creates BitPay invoices; this script can be run permanently.
Script 003 creates BTCPayServer invoices; this script can be run permanently.
Script 004 is very similar to script 003. The main difference is that script 004 outputs HTML, so you can run this on your webserver.
IPNs will be sent after a BitPay invoice receives a payment. IPNs can be logged or processed with IPNlogger.php
IPNs will be sent after a BTCPayServer invoice receives a payment. IPNs can be logged or processed with IPNlogger.php
## Getting started
To begin please visit https://test.bitpay.com/dashboard/signup and register for a BitPay merchant test account. Please fill in all questions, so you get a fully working test account. When filling in the settlement address in your BitPay merchant test account, make sure to fill in a testnet bitcoin address (starting with m or n).
To begin please visit https://testnet.demo.btcpayserver.org/Account/Register and register for a BTCPayServer merchant test account. Please fill in all questions, so you get a fully working test account. When filling in the settlement address in your BTCPayServer merchant test account, make sure to fill in a testnet bitcoin address (starting with m or n).
If you are looking for a testnet bitcoin wallet to test with, please visit https://bitpay.com/wallet and create a new wallet.
If you are looking for a testnet bitcoin wallet to test with, please visit https://docs.btcpayserver.org/faq-and-common-issues/faq-wallet#recommended-external-wallets for a list of recommendations.
If you need testnet bitcoin please visit a testnet faucet, e.g. https://testnet.coinfaucet.eu/en/ or http://tpfaucet.appspot.com/
For more information about testing, please see https://bitpay.com/docs/testing
For more information about testing, please see https://docs.btcpayserver.org/faq-and-common-issues/faq-general
To install BitPay's latest PHP library, please follow the instructions from https://github.com/bitpay/php-bitpay-client/blob/master/README.md
To install BTCPayServer's latest PHP library, please follow the instructions from https://github.com/btcpayserver/btcpayserver-php-client/blob/master/README.md
## Script 1 & 2: configure your local installation
The following two scripts need to be executed once. These scripts will generate your private/public keys and pair them to your BitPay merchant account:
1. 001_generateKeys.php : generates the private/public keys to sign the communication with BitPay. The private/public keys are stored in your filesystem for later usage.
2. 002_pair.php : pairs your private/public keys to your BitPay merchant account. Please make sure to first create a pairing code in your BitPay merchant account (Payment Tools -> Manage API tokens -> Add new token -> Add token) and put this 7 character pairing code in the script. The script returns an API token that should be put put in 003_createInvoice.php, to create invoices permanently.
The following two scripts need to be executed once. These scripts will generate your private/public keys and pair them to your BTCPayServer merchant account:
1. 001_generateKeys.php : generates the private/public keys to sign the communication with BTCPayServer. The private/public keys are stored in your filesystem for later usage.
2. 002_pair.php : pairs your private/public keys to your BTCPayServer merchant account. Please make sure to first create a pairing code in your BTCPayServer merchant account (Payment Tools -> Manage API tokens -> Add new token -> Add token) and put this 7 character pairing code in the script. The script returns an API token that should be put put in 003_createInvoice.php, to create invoices permanently.
These first two scripts need to be executed only once.
## Script 3: create a BitPay invoice
3. 003_createInvoice.php : creates a BitPay invoice. Please make sure to update the script with the API token received from 002_pair.php
## Script 3: create a BTCPayServer invoice
3. 003_createInvoice.php : creates a BTCPayServer invoice. Please make sure to update the script with the API token received from 002_pair.php
This script returns a BitPay invoice object. You can display the invoice by loading the invoice URL in a web browser. You can pay the invoice with your bitcoin wallet.
This script returns a BTCPayServer invoice object. You can display the invoice by loading the invoice URL in a web browser. You can pay the invoice with your bitcoin wallet.
## Script 4: display a BitPay invoice using BitPay's hosted payment page
4. 004_HostedPaymentPage.php : creates a BitPay invoice and returns the HTML to show the invoice. Please make sure to update the script with the API token received from 002_pair.php
## Script 4: display a BTCPayServer invoice using BTCPayServer's hosted payment page
4. 004_HostedPaymentPage.php : creates a BTCPayServer invoice and returns the HTML to show the invoice. Please make sure to update the script with the API token received from 002_pair.php
For more information about paying a BitPay invoice, please see https://support.bitpay.com/hc/en-us/articles/203281456-How-do-I-pay-a-BitPay-invoice-
For more information about paying a BTCPayServer invoice, please see https://docs.btcpayserver.org/
Script 003_createInvoice.php and 004_HostedPaymentPage.php can be run permanently with the token from 002_pair.php
## Script 5: log Instant Payment Notifications
After you've paid the invoice, BitPay will send an IPN to the notificationURL of the invoice. A script to process the IPN should be put on your server and be reachable from the internet. Your should put the URL of IPNLogger.php in 003_createInvoice.php, e.g.:
After you've paid the invoice, BTCPayServer will send an IPN to the notificationURL of the invoice. A script to process the IPN should be put on your server and be reachable from the internet. Your should put the URL of IPNLogger.php in 003_createInvoice.php, e.g.:
```
// You will receive IPN's at this URL, should be HTTPS for security purposes!
$invoice->setNotificationUrl('https://yourserver.com/IPNlogger.php');
```
IPNs can be used by the merchant to update order statuses. Please note to use IPNs as a trigger to fetch the BitPay invoice status, since the IPNs are not authenticated.
IPNs can be used by the merchant to update order statuses. Please note to use IPNs as a trigger to fetch the BTCPayServer invoice status, since the IPNs are not authenticated.
For more information about IPNs see https://bitpay.com/docs/invoice-callbacks
Examples (c) 2014-2017 BitPay
Examples (c) 2014-2017 BTCPayServer

View File

@ -1,27 +1,33 @@
<?php
/**
* Copyright (c) 2014-2017 BitPay
* Copyright (c) 2014-2017 BTCPayServer
*
* getInvoice
*
* Requirements:
* - Account on https://test.bitpay.com
* - Account on https://testnet.demo.btcpayserver.org
* - Baisic PHP Knowledge
* - Private and Public keys from 001.php
* - Token value obtained from 002.php
* - Invoice created
*/
require __DIR__ . '/../../vendor/autoload.php';
require __DIR__.'/../../vendor/autoload.php';
// Now fetch the invoice from BitPay
// Now fetch the invoice from BTCPayServer
$client = new \BTCPayServer\Client\Client();
$adapter = new \BTCPayServer\Client\Adapter\CurlAdapter();
$client->setUri('https://my-btcpay-server.com');
$storageEngine = new \BTCPayServer\Storage\EncryptedFilesystemStorage('YourTopSecretPassword');
$privateKey = $storageEngine->load('/tmp/btcpayserver.pri');
$publicKey = $storageEngine->load('/tmp/btcpayserver.pub');
$client = new \BTCPayServer\Client\Client();
$adapter = new \BTCPayServer\Client\Adapter\CurlAdapter();
$client->setPrivateKey($privateKey);
$client->setPublicKey($publicKey);
$client->setUri('https://testnet.demo.btcpayserver.org');
$client->setAdapter($adapter);
$token = new \BTCPayServer\Token();
$token->setToken('UpdateThisValue'); // UPDATE THIS VALUE
$token->setFacade('merchant');
$client->setToken($token);
@ -30,11 +36,9 @@ $client->setToken($token);
*/
$invoice = $client->getInvoice("UpdateThisValue");
$request = $client->getRequest();
$request = $client->getRequest();
$response = $client->getResponse();
echo (string)$request . PHP_EOL . PHP_EOL . PHP_EOL;
echo (string)$response . PHP_EOL . PHP_EOL;
echo (string) $request.PHP_EOL.PHP_EOL.PHP_EOL;
echo (string) $response.PHP_EOL.PHP_EOL;
print_r($invoice);
?>

View File

@ -1,37 +0,0 @@
<?php
require __DIR__ . '/../../vendor/autoload.php';
$storageEngine = new \BTCPayServer\Storage\EncryptedFilesystemStorage('TopSecretPassword');
$private = $storageEngine->load('/tmp/private_key.key');
$public = $storageEngine->load('/tmp/public_key.key');
$public->setPrivateKey($private);
$public->generate();
$sin = new \BTCPayServer\SinKey('/tmp/sin.key');
$sin->setPublicKey($public);
$sin->generate();
#printf("Public Key: %s\n", $public);
#printf("Private Key: %s\n", $private);
#$message = 'https://test.bitpay.com/subscriptions{"schedule":"weekly","token":"some token","billData":{"currency":"USD","price":"2.00","quantity":1}}';
$message = 'https://test.bitpay.com/bills{
{
"amount":"1.00",
"currency":"USD",
"token":"TfCYYmnL9ZArncyeKCFdNX5V8ArudfiUFTp",
"description":"netsuite test",
"email":"joshlewis@gmail.com"
}';
$signedMessage = $private->sign($message);
error_log('$sin ' . $sin);
error_log('$public ' . $public);
error_log('message to be signed:: ' . $message . "\n");
error_log('signed message:: ' . $signedMessage);

View File

@ -0,0 +1,134 @@
<?php
/**
* @license Copyright 2019 BTCPayServer, MIT License
* see https://github.com/btcpayserver/btcpayserver-php-client/blob/master/LICENSE
*/
namespace BTCPayServer;
use BTCPayServer\DependencyInjection\BTCPayServerExtension;
use BTCPayServer\DependencyInjection\Loader\ArrayLoader;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\Config\Loader\LoaderResolver;
use Symfony\Component\Config\Loader\DelegatingLoader;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
/**
* Setups container and is ready for some dependency injection action
*
* @package BTCPayServer
*/
class BTCPayServer
{
/**
* @var ContainerInterface
*/
protected $container;
/**
* First argument can either be a string or fullpath to a yaml file that
* contains configuration parameters. For a list of configuration values
* see \BTCPayServer\Config\Configuration class
*
* The second argument is the container if you want to build one by hand.
*
* @param array|string $config
* @param ContainerInterface $container
*/
public function __construct($config = array(), ContainerInterface $container = null)
{
$this->container = $container;
if (is_null($container)) {
$this->initializeContainer($config);
}
}
/**
* Initialize the container
*/
protected function initializeContainer($config)
{
$this->container = $this->buildContainer($config);
$this->container->compile();
}
/**
* Build the container of services and parameters
*/
protected function buildContainer($config)
{
$container = new ContainerBuilder(new ParameterBag($this->getParameters()));
$this->prepareContainer($container);
$this->getContainerLoader($container)->load($config);
return $container;
}
protected function getParameters()
{
return array(
'btcpayserver.root_dir' => realpath(__DIR__.'/..'),
);
}
/**
*/
private function prepareContainer(ContainerInterface $container)
{
foreach ($this->getDefaultExtensions() as $ext) {
$container->registerExtension($ext);
$container->loadFromExtension($ext->getAlias());
}
}
/**
* @param ContainerInterface $container
* @return LoaderInterface
*/
private function getContainerLoader(ContainerInterface $container)
{
$locator = new FileLocator();
$resolver = new LoaderResolver(
array(
new ArrayLoader($container),
new YamlFileLoader($container, $locator),
)
);
return new DelegatingLoader($resolver);
}
/**
* Returns an array of the default extensions
*
* @return array
*/
private function getDefaultExtensions()
{
return array(
new BTCPayServerExtension(),
);
}
/**
* @return ContainerInterface
*/
public function getContainer()
{
return $this->container;
}
/**
* @return mixed
*/
public function get($service)
{
return $this->container->get($service);
}
}

View File

@ -80,8 +80,11 @@ class CurlAdapter implements AdapterInterface
/** @var ResponseInterface */
$response = Response::createFromRawResponse($raw);
// For some unknown reason, on some machine, the status code is equal to 0
// If that's the case, let's just ask to curl the real http code
if ($response->getStatusCode() === 0)
$response->setStatusCode(curl_getinfo($curl, CURLINFO_HTTP_CODE));
curl_close($curl);
return $response;
}
@ -94,13 +97,13 @@ class CurlAdapter implements AdapterInterface
private function getCurlDefaultOptions(RequestInterface $request)
{
return array(
CURLOPT_URL => $request->getUri(),
CURLOPT_PORT => $request->getPort(),
CURLOPT_URL => $request->getFullUri(),
CURLOPT_CUSTOMREQUEST => $request->getMethod(),
CURLOPT_HTTPHEADER => $request->getHeaderFields(),
CURLOPT_TIMEOUT => 10,
CURLOPT_SSL_VERIFYPEER => 1,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_CAINFO => __DIR__.'/ca-bundle.crt',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FORBID_REUSE => 1,
CURLOPT_FRESH_CONNECT => 1,

File diff suppressed because it is too large Load Diff

View File

@ -7,6 +7,7 @@
namespace BTCPayServer\Client;
use BTCPayServer\Client\Adapter\AdapterInterface;
use BTCPayServer\Network\NetworkInterface;
use BTCPayServer\TokenInterface;
use BTCPayServer\InvoiceInterface;
use BTCPayServer\PayoutInterface;
@ -52,12 +53,13 @@ class Client implements ClientInterface
protected $privateKey;
/**
* @var string
* @var uri
*/
protected $uri;
public function setUri(string $uri){
$this->uri = $uri;
public function setUri($uri)
{
$this->uri = trim($uri);
}
/**
@ -105,7 +107,7 @@ class Client implements ClientInterface
*/
protected function fillInvoiceData(InvoiceInterface $invoice, $data)
{
// Returns the invoice time in milliseconds. PHP's DateTime object expects the time to be in seconds
# BTCPayServer returns the invoice time in milliseconds. PHP's DateTime object expects the time to be in seconds
$invoiceTime = is_numeric($data['invoiceTime']) ? intval($data['invoiceTime']/1000) : $data['invoiceTime'];
$expirationTime = is_numeric($data['expirationTime']) ? intval($data['expirationTime']/1000) : $data['expirationTime'];
$currentTime = is_numeric($data['currentTime']) ? intval($data['currentTime']/1000) : $data['currentTime'];
@ -116,14 +118,18 @@ class Client implements ClientInterface
->setUrl($data['url'])
->setPosData(array_key_exists('posData', $data) ? $data['posData'] : '')
->setStatus($data['status'])
->setBtcPrice(array_key_exists('btcPrice', $data) ? $data['btcPrice'] : '')
->setPrice($data['price'])
->setTaxIncluded(array_key_exists('taxIncluded', $data) ? $data['taxIncluded'] : 0)
->setCurrency(new \BTCPayServer\Currency($data['currency']))
->setOrderId(array_key_exists('orderId', $data) ? $data['orderId'] : '')
->setInvoiceTime($invoiceTime)
->setExpirationTime($expirationTime)
->setCurrentTime($currentTime)
->setId($data['id'])
->setBtcPaid(array_key_exists('btcPaid', $data) ? $data['btcPaid'] : '')
->setAmountPaid(array_key_exists('amountPaid', $data) ? $data['amountPaid'] : '')
->setRate(array_key_exists('rate', $data) ? $data['rate'] : '')
->setExceptionStatus($data['exceptionStatus'])
->setRefundAddresses(array_key_exists('refundAddresses', $data) ? $data['refundAddresses'] : '')
->setTransactionCurrency(array_key_exists('transactionCurrency', $data) ? $data['transactionCurrency'] : null)
@ -151,12 +157,14 @@ class Client implements ClientInterface
$body = array(
'price' => $item->getPrice(),
'taxIncluded' => $item->getTaxIncluded(),
'currency' => $currency->getCode(),
'posData' => $invoice->getPosData(),
'notificationURL' => $invoice->getNotificationUrl(),
'transactionSpeed' => $invoice->getTransactionSpeed(),
'fullNotifications' => $invoice->isFullNotifications(),
'extendedNotifications' => $invoice->isExtendedNotifications(),
'redirectAutomatically' => $invoice->isRedirectAutomatically(),
'notificationEmail' => $invoice->getNotificationEmail(),
'redirectURL' => $invoice->getRedirectUrl(),
'orderID' => $invoice->getOrderId(),
@ -176,9 +184,14 @@ class Client implements ClientInterface
'guid' => Util::guid(),
'nonce' => Util::nonce(),
'token' => $this->token->getToken(),
'paymentCurrencies' => $invoice->getPaymentCurrencies(),
);
foreach(array_keys($body) as $key) {
if(null === $body[$key]) {
unset($body[$key]);
}
}
$request->setBody(json_encode($body));
$this->addIdentityHeader($request);
$this->addSignatureHeader($request);
@ -204,7 +217,7 @@ class Client implements ClientInterface
$this->response = $this->sendRequest($this->request);
$body = json_decode($this->response->getBody(), true);
if (empty($body['data'])) {
throw new \BTCPayServer\Client\BTCPayServerException('Error with request: no data returned');
throw new \Exception('Error with request: no data returned');
}
$currencies = $body['data'];
array_walk($currencies, function (&$value, $key) {
@ -373,7 +386,7 @@ class Client implements ClientInterface
$body = json_decode($this->response->getBody(), true);
if (empty($body['data'])) {
throw new \BTCPayServer\Client\BTCPayServerException('Error with request: no data returned');
throw new \Exception('Error with request: no data returned');
}
$data = $body['data'];
@ -399,7 +412,7 @@ class Client implements ClientInterface
$body = json_decode($this->response->getBody(), true);
if (empty($body['data'])) {
throw new \BTCPayServer\Client\BTCPayServerException('Error with request: no data returned');
throw new \Exception('Error with request: no data returned');
}
$data = $body['data'];
@ -461,7 +474,7 @@ class Client implements ClientInterface
$this->response = $this->sendRequest($this->request);
$body = json_decode($this->response->getBody(), true);
if (empty($body['data'])) {
throw new \BTCPayServer\Client\BTCPayServerException('Error with request: no data returned');
throw new \Exception('Error with request: no data returned');
}
$tokens = array();
@ -502,7 +515,7 @@ class Client implements ClientInterface
}
if($this->response->getStatusCode() >= 400) {
throw new BTCPayServerException('invalid status code: '. $this->response->getStatusCode());
throw new \Exception('invalid status code: '. $this->response->getStatusCode());
}
$tkn = $body['data'][0];
@ -567,7 +580,7 @@ class Client implements ClientInterface
$body = json_decode($this->response->getBody(), true);
if (isset($body['error'])) {
throw new BTCPayServerException($body['error']);
throw new \Exception($body['error']);
}
$data = $body['data'];
@ -602,7 +615,7 @@ class Client implements ClientInterface
protected function addIdentityHeader(RequestInterface $request)
{
if (null === $this->publicKey) {
throw new \BTCPayServer\Client\BTCPayServerException('Please set your Public Key.');
throw new \Exception('Please set your Public Key.');
}
$request->setHeader('x-identity', (string) $this->publicKey);
@ -614,10 +627,10 @@ class Client implements ClientInterface
protected function addSignatureHeader(RequestInterface $request)
{
if (null === $this->privateKey) {
throw new BTCPayServerException('Please set your Private Key');
throw new \Exception('Please set your Private Key');
}
$url = $request->getUri();
$url = $request->getFullUri();
$message = sprintf(
'%s%s',
@ -626,31 +639,22 @@ class Client implements ClientInterface
);
$signature = $this->privateKey->sign($message);
$request->setHeader('x-signature', $signature);
}
/**
* @return RequestInterface
*
* @throws BTCPayServerException
*/
protected function createNewRequest()
{
$request = new Request();
$host = parse_url($this->uri,PHP_URL_HOST);
$port = parse_url($this->uri,PHP_URL_PORT);
$scheme = parse_url($this->uri,PHP_URL_SCHEME);
if($port === null){
if($scheme === 'http'){
$port = 80;
}elseif($scheme === 'https'){
$port = 443;
}
if ($this->uri === null) {
throw new BTCPayServerException('You should provider the url of your BTCPAY server');
}
$request->setHost($host);
$request->setPort($port);
$request->setScheme($scheme);
$request = new Request();
$request->setUri($this->uri);
$this->prepareRequestHeaders($request);
return $request;
@ -670,41 +674,31 @@ class Client implements ClientInterface
);
$request->setHeader('X-BTCPayServer-Plugin-Info', sprintf('%s/%s', self::NAME, self::VERSION));
$request->setHeader('Content-Type', 'application/json');
$request->setHeader('X-Accept-Version', '2.0.0');
$request->setHeader('X-Accept-Version', '0.1.0');
}
protected function checkPriceAndCurrency($price, $currency)
{
$decimalPosition = strpos($price, '.');
if ($decimalPosition == 0) {
$decimalPrecision = 0;
} else {
$decimalPrecision = strlen(substr($price, $decimalPosition + 1));
}
if ($currency !== 'BTC' && $decimalPrecision > 2) {
throw new \BTCPayServer\Client\BTCPayServerException('Incorrect price format or currency type.');
} elseif ($decimalPrecision > 6) {
throw new \BTCPayServer\Client\BTCPayServerException('Incorrect price format or currency type.');
}
}
/**
* @return array
* @throws \Exception
*/
private function parseResponse()
{
private function parseResponse(){
$bodyString = $this->response->getBody();
if($this->response->getStatusCode() === 401){
throw new \Exception($bodyString);
}
$body = json_decode($bodyString, true);
$error_message = false;
$error_message = (!empty($body['error'])) ? $body['error'] : $error_message;
$error_message = (!empty($body['errors'])) ? $body['errors'] : $error_message;
$error_message = (is_array($error_message)) ? implode("\n", $error_message) : $error_message;
if (false !== $error_message) {
throw new \BTCPayServer\Client\BTCPayServerException($error_message);
throw new \Exception($error_message);
}
return $body;
}

View File

@ -16,6 +16,8 @@ use BTCPayServer\PayoutInterface;
*/
interface ClientInterface
{
const TESTNET = '0x6F';
const LIVENET = '0x00';
/**
* These can be changed/updated so when the request is sent to BTCPayServer it
@ -24,7 +26,7 @@ interface ClientInterface
* @see RFC2616 section 14.43 for User-Agent Format
*/
const NAME = 'BTCPayServer PHP-Client';
const VERSION = '4.0.1';
const VERSION = '2.2.20';
//public function createApplication(ApplicationInterface $application);

View File

@ -37,19 +37,6 @@ class Request implements RequestInterface
*/
protected $method;
/**
* This should be "http" or "https"
* @var string
*/
protected $scheme;
/**
* This should be something such as `test.btcpayserver.com` or just `btcpayserver.com`
*
* @var string
*/
protected $host;
/**
* The path is added to the end of the host
*
@ -57,13 +44,6 @@ class Request implements RequestInterface
*/
protected $path;
/**
* Default is 443 but should be changed by whatever is passed in through the Adapter.
*
* @var integer
*/
protected $port;
/**
*/
public function __construct()
@ -88,7 +68,7 @@ class Request implements RequestInterface
*/
public function __toString()
{
$request = sprintf("%s %s HTTP/1.1\r\n", $this->getMethod(), $this->getUriWithPort());
$request = sprintf("%s %s HTTP/1.1\r\n", $this->getMethod(), $this->getFullUri());
$request .= $this->getHeadersAsString();
$request .= $this->getBody();
@ -103,42 +83,6 @@ class Request implements RequestInterface
return (strtoupper($method) == strtoupper($this->method));
}
/**
* @inheritdoc
*/
public function getScheme()
{
return $this->scheme;
}
/**
* This is called in the Adapter
*
* @inheritdoc
*/
public function setScheme(string $scheme)
{
$this->scheme = $scheme;
}
/**
* @inheritdoc
*/
public function getPort()
{
return $this->port;
}
/**
* This is called in the Adapter
*
* @inheritdoc
*/
public function setPort(int $port)
{
$this->port = $port;
}
/**
* @inheritdoc
*/
@ -163,45 +107,29 @@ class Request implements RequestInterface
*/
public function getUri()
{
return $this->uri;
}
/**
* @inheritdoc
*/
public function getFullUri()
{
$uriNormalized = rtrim($this->getUri(), '/');
$pathNormalized = ltrim($this->getPath(), '/');
return sprintf(
'%s://%s/%s',
$this->getScheme(),
$this->getHost(),
$this->getPath()
'%s/%s',
$uriNormalized,
$pathNormalized
);
}
/**
* @inheritdoc
*/
public function getUriWithPort()
public function setUri($uri)
{
return sprintf(
'%s://%s:%s/%s',
$this->getScheme(),
$this->getHost(),
$this->getPort(),
$this->getPath()
);
}
/**
* @inheritdoc
*/
public function getHost()
{
return $this->host;
}
/**
* Sets the host for the request
*
* @param string $host
*/
public function setHost(string $host)
{
$this->host = $host;
$this->uri = $uri;
return $this;
}
@ -290,7 +218,7 @@ class Request implements RequestInterface
}
/**
* @inheritdoc
* @param string $host
*/
public function setPath($path)
{

View File

@ -24,28 +24,6 @@ interface RequestInterface
*/
public function getMethod();
/**
* Returns "http" or "https"
*
* @return string
*/
public function getScheme();
/**
* Returns the host to send the request to. The host would be something
* such as `test.btcpayserver.com` or `btcpayserver.com`
*
* @return string
*/
public function getHost();
/**
* Returns port to send request on
*
* @return integer
*/
public function getPort();
/**
* example of path is `api/invoice` as this is appended to $host
*
@ -58,7 +36,7 @@ interface RequestInterface
*
* @return string
*/
public function getUri();
public function getFullUri();
/**
* Checks the request to see if the method matches a known value

View File

@ -65,15 +65,14 @@ class Response implements ResponseInterface
$tmp = explode($delimiter, $rawResponse, 2);// grab the 100 Continue header
$rawResponse = $tmp[1];// update the response, purging the most recent 100 Continue header
}// repeat
$lines = preg_split('/(\\r?\\n)/', $rawResponse);
$linesLen = count($lines);
for ($i = 0; $i < $linesLen; $i++) {
if (0 == $i) {
// Example: HTTP/2 404
preg_match('/^HTTP\/([\d\.]+)\s(\d+)/', $lines[$i], $statusLine);
preg_match('/^HTTP\/(\d\.\d|\d)\s(\d+)/', $lines[$i], $statusLine);
$response->setStatusCode($statusCode = $statusLine[2]);
continue;

View File

@ -0,0 +1,101 @@
<?php
/**
* @license Copyright 2019 BTCPayServer, MIT License
* see https://github.com/btcpayserver/btcpayserver-php-client/blob/master/LICENSE
*/
namespace BTCPayServer\Config;
use Symfony\Component\Config\Definition\ConfigurationInterface;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
/**
* This class contains all the valid configuration settings that can be used.
* If you update this file to add new settings, please make sure you update the
* documentation as well.
*
* @see http://symfony.com/doc/current/components/config/definition.html
*
* @package BTCPayServer
*/
class Configuration implements ConfigurationInterface
{
/**
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('btcpay');
$rootNode
->children()
->scalarNode('public_key')
->info('Public Key Filename')
->defaultValue(getenv('HOME').'/.btcpayserver/api.pub')
->end()
->scalarNode('private_key')
->info('Private Key Filename')
->defaultValue(getenv('HOME').'/.btcpayserver/api.key')
->end()
->scalarNode('sin_key')
->info('Private Key Filename')
->defaultValue(getenv('HOME').'/.btcpayserver/api.sin')
->end()
->enumNode('adapter')
->values(array('curl', 'mock'))
->info('Client Adapter')
->defaultValue('curl')
->end()
->append($this->addKeyStorageNode())
->scalarNode('key_storage_password')
->info('Used to encrypt and decrypt keys when saving to filesystem')
->defaultNull()
->end()
->end();
return $treeBuilder;
}
/**
* Adds the key_storage node with validation rules
*
* key_storage MUST:
* * implement BTCPayServer\Storage\StorageInterface
* * be a class that can be loaded
*/
protected function addKeyStorageNode()
{
$builder = new TreeBuilder();
$node = $builder->root('key_storage', 'scalar');
$node
->info('Class that is used to store your keys')
->defaultValue('BTCPayServer\Storage\EncryptedFilesystemStorage')
->validate()
->always()
->then(function ($value) {
if (!class_exists($value)) {
throw new \Exception(
sprintf(
'Could not find class "%s".',
$value
)
);
}
// requires PHP >= 5.3.7
if (!is_subclass_of($value, 'BTCPayServer\Storage\StorageInterface')) {
throw new \Exception(
sprintf(
'"%s" does not implement "BTCPayServer\Storage\StorageInterface"',
$value
)
);
}
return $value;
})
->end();
return $node;
}
}

View File

@ -1,16 +0,0 @@
<?php
namespace Bitpay;
class CurrencyUnrestricted extends Currency
{
/**
* Overrides the parent method to allow any currency symbol to be set.
*/
public function setCode($code)
{
$this->code = $code;
return $this;
}
}

View File

@ -0,0 +1,63 @@
<?php
/**
* @license Copyright 2019 BTCPayServer, MIT License
* see https://github.com/btcpayserver/btcpayserver-php-client/blob/master/LICENSE
*/
namespace BTCPayServer\DependencyInjection;
use BTCPayServer\Config\Configuration;
use Symfony\Component\Config\Definition\Processor;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
/**
* @package BTCPayServer
*/
class BTCPayServerExtension implements ExtensionInterface
{
public function load(array $configs, ContainerBuilder $container)
{
$processor = new Processor();
$config = $processor->processConfiguration(new Configuration(), $configs);
foreach (array_keys($config) as $key) {
$container->setParameter('btcpayserver.'.$key, $config[$key]);
}
$loader = new XmlFileLoader($container, new FileLocator(__DIR__));
$loader->load('services.xml');
$container->setParameter(
'adapter.class',
'BTCPayServer\Client\Adapter\\'.ContainerBuilder::camelize($config['adapter']).'Adapter'
);
$container->setParameter('key_storage.class', $config['key_storage']);
}
/**
* @codeCoverageIgnore
*/
public function getAlias()
{
return 'btcpay';
}
/**
* @codeCoverageIgnore
*/
public function getNamespace()
{
return 'http://example.org/schema/dic/btcpayserver';
}
/**
* @codeCoverageIgnore
*/
public function getXsdValidationBasePath()
{
return false;
}
}

View File

@ -0,0 +1,77 @@
<?php
/**
* @license Copyright 2019 BTCPayServer, MIT License
* see https://github.com/btcpayserver/btcpayserver-php-client/blob/master/LICENSE
*/
namespace BTCPayServer\DependencyInjection\Loader;
use Symfony\Component\Config\Loader\Loader;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
/**
* Used to load a configuration that is passed in as an array
*
* @package BTCPayServer
*/
class ArrayLoader extends Loader
{
protected $container;
public function __construct(ContainerBuilder $container)
{
$this->container = $container;
}
public function load($resource, $type = null)
{
// validation
foreach (array_keys($resource) as $namespace) {
if (in_array($namespace, array('imports', 'paramters', 'services'))) {
continue;
}
if (!$this->container->hasExtension($namespace)) {
$extensionNamespaces = array_filter(
array_map(
function ($ext) {
return $ext->getAlias();
},
$this->container->getExtensions()
)
);
throw new InvalidArgumentException(sprintf(
'There is no extension able to load the configuration for "%s". Looked for namespace "%s", found %s',
$namespace,
$namespace,
$extensionNamespaces ? sprintf('"%s"', implode('", "', $extensionNamespaces)) : 'none'
));
}
}
// Set Paramters
if (isset($resource['parameters'])) {
foreach ($resource['parameters'] as $key => $value) {
$this->container->setParameter($key, $value);
}
}
// extensions
foreach ($resource as $namespace => $values) {
if (in_array($namespace, array('imports', 'parameters', 'services'))) {
continue;
}
if (!is_array($values)) {
$values = array();
}
$this->container->loadFromExtension($namespace, $values);
}
}
public function supports($resource, $type = null)
{
return is_array($resource);
}
}

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
/**
* @license Copyright 2011-2017 BTCPayServer, MIT License
* see https://github.com/btcpayserver/btcpayserver-php-client/blob/master/LICENSE
*/
-->
<container xmlns="http://symfony.com/schema/dic/services">
<parameters>
<parameter key="adapter.class">BTCPayServer\Client\Adapter\CurlAdapter</parameter>
<parameter key="key_manager.class">BTCPayServer\KeyManager</parameter>
<parameter key="key_storage.class">BTCPayServer\Storage\FilesystemStorage</parameter>
</parameters>
<services>
<service id="adapter" class="%adapter.class%" />
<service id="client" class="BTCPayServer\Client\Client">
<call method="setAdapter">
<argument type="service" id="adapter" />
</call>
<call method="setPublicKey">
<argument type="service" id="public_key" />
</call>
<call method="setPrivateKey">
<argument type="service" id="private_key" />
</call>
</service>
<service id="key_storage" class="%key_storage.class%">
<argument>%btcpayserver.key_storage_password%</argument>
</service>
<service id="key_manager" class="%key_manager.class%">
<argument type="service" id="key_storage" />
</service>
<service id="public_key" class="BTCPayServer\PublicKey">
<argument>%btcpayserver.public_key%</argument>
</service>
<service id="private_key" class="BTCPayServer\PrivateKey">
<argument>%btcpayserver.private_key%</argument>
</service>
</services>
</container>

View File

@ -67,6 +67,11 @@ class Invoice implements InvoiceInterface
*/
protected $extendedNotifications = false;
/**
* @var boolean
*/
protected $redirectAutomatically = false;
/**
* @var string
*/
@ -77,6 +82,12 @@ class Invoice implements InvoiceInterface
*/
protected $url;
/**
* @deprecated Deprecated with introduction of BCH
* @var float
*/
protected $btcPrice;
/**
* @var \DateTime
*/
@ -102,12 +113,23 @@ class Invoice implements InvoiceInterface
*/
protected $exceptionStatus;
/**
* @deprecated Deprecated with introduction of BCH
* @var
*/
protected $btcPaid;
/**
* @var
*/
protected $amountPaid;
/**
* @deprecated Deprecated with introduction of BCH
* @var
*/
protected $rate;
/**
* @var
*/
@ -138,11 +160,6 @@ class Invoice implements InvoiceInterface
*/
protected $paymentTotals;
/**
* @var array
*/
protected $paymentCurrencies;
/**
* @inheritdoc
@ -152,6 +169,14 @@ class Invoice implements InvoiceInterface
return $this->getItem()->getPrice();
}
/**
* @inheritdoc
*/
public function getTaxIncluded()
{
return $this->getItem()->getTaxIncluded();
}
/**
* @param float $price
*
@ -166,6 +191,20 @@ class Invoice implements InvoiceInterface
return $this;
}
/**
* @param float $taxIncluded
*
* @return InvoiceInterface
*/
public function setTaxIncluded($taxIncluded)
{
if (!empty($taxIncluded)) {
$this->getItem()->setTaxIncluded($taxIncluded);
}
return $this;
}
/**
* @inheritdoc
*/
@ -405,6 +444,19 @@ class Invoice implements InvoiceInterface
return $this;
}
/**
* @inheritdoc
*/
public function isRedirectAutomatically()
{
return $this->redirectAutomatically;
}
public function setRedirectAutomatically($redirectAutomatically)
{
$this->redirectAutomatically = (boolean) $redirectAutomatically;
return $this;
}
/**
* @inheritdoc
@ -450,6 +502,30 @@ class Invoice implements InvoiceInterface
return $this;
}
/**
* @deprecated Deprecated with introduction of BCH
* @inheritdoc
*/
public function getBtcPrice()
{
return $this->btcPrice;
}
/**
* @deprecated Deprecated with introduction of BCH
* @param float $btcPrice
*
* @return InvoiceInterface
*/
public function setBtcPrice($btcPrice)
{
if (!empty($btcPrice)) {
$this->btcPrice = $btcPrice;
}
return $this;
}
/**
* @inheritdoc
*/
@ -540,10 +616,7 @@ class Invoice implements InvoiceInterface
*/
public function setOrderId($orderId)
{
if (!empty($orderId) && ctype_print($orderId)) {
$this->orderId = trim($orderId);
}
$this->orderId = trim($orderId);
return $this;
}
@ -669,6 +742,30 @@ class Invoice implements InvoiceInterface
return $this;
}
/**
* @deprecated Deprecated with introduction of BCH
* @param void
* @return
*/
public function getBtcPaid()
{
return $this->btcPaid;
}
/**
* @deprecated Deprecated with introduction of BCH
* @param
* @return Invoice
*/
public function setBtcPaid($btcPaid)
{
if (isset($btcPaid)) {
$this->btcPaid = $btcPaid;
}
return $this;
}
/**
* @param void
* @return
@ -691,6 +788,30 @@ class Invoice implements InvoiceInterface
return $this;
}
/**
* @deprecated Deprecated with introduction of BCH
* @param void
* @return Invoice
*/
public function getRate()
{
return $this->rate;
}
/**
* @deprecated Deprecated with introduction of BCH
* @param
* @return
*/
public function setRate($rate)
{
if (!empty($rate)) {
$this->rate = $rate;
}
return $this;
}
/**
* @param void
* @return Invoice
@ -776,7 +897,7 @@ class Invoice implements InvoiceInterface
/**
* @param void
* @return InvoiceInterface
* @return Invoice
*/
public function getPaymentSubtotals()
{
@ -784,8 +905,8 @@ class Invoice implements InvoiceInterface
}
/**
* @param
* @return InvoiceInterface
* @param
* @return
*/
public function setPaymentSubtotals($paymentSubtotals)
{
@ -797,7 +918,7 @@ class Invoice implements InvoiceInterface
}
/**
* @param void
* @return InvoiceInterface
* @return Invoice
*/
public function getPaymentTotals()
{
@ -805,8 +926,8 @@ class Invoice implements InvoiceInterface
}
/**
* @param
* @return InvoiceInterface
* @param
* @return
*/
public function setPaymentTotals($paymentTotals)
{
@ -816,20 +937,4 @@ class Invoice implements InvoiceInterface
return $this;
}
/**
* @inheritdoc
*/
public function getPaymentCurrencies() {
return $this->paymentCurrencies;
}
/**
* @inheritdoc
*/
public function setPaymentCurrencies($paymentCurrencies) {
$this->paymentCurrencies = $paymentCurrencies;
return $this;
}
}

View File

@ -18,14 +18,14 @@ interface InvoiceInterface
* to the associated bitcoin address are credited to the invoice.  If an invoice has
* received a partial payment, it will still reflect a status of new to the merchant
* (from a merchant system perspective, an invoice is either paid or not paid, partial
* payments and over payments are handled by BTCPayServer by either refunding the
* payments and over payments are handled by btcpayserver.com by either refunding the
* customer or applying the funds to a new invoice.
*/
const STATUS_NEW = 'new';
/**
* As soon as full payment (or over payment) is received, an medium or low speed invoice goes into the
* paid status. A high speed invoice immediately goes into 'confirmed', see below.
* As soon as full payment (or over payment) is received, an invoice goes into the
* paid status.
*/
const STATUS_PAID = 'paid';
@ -43,7 +43,7 @@ interface InvoiceInterface
const STATUS_CONFIRMED = 'confirmed';
/**
* When an invoice is complete, it means that BTCPayServer has credited the
* When an invoice is complete, it means that BTCPayServer.com has credited the
* merchants account for the invoice.  Currently, 6 confirmation blocks on the
* bitcoin network are required for an invoice to be complete.  Note, in the future (for
* qualified payers), invoices may move to a complete status immediately upon
@ -62,7 +62,7 @@ interface InvoiceInterface
* An invoice is considered invalid when it was paid, but payment was not confirmed
* within 1 hour after receipt.  It is possible that some transactions on the bitcoin
* network can take longer than 1 hour to be included in a block.  In such
* circumstances, once payment is confirmed, BTCPayServer will make arrangements
* circumstances, once payment is confirmed, BTCPayServer.com will make arrangements
* with the merchant regarding the funds (which can either be credited to the
* merchant account on another invoice, or returned to the buyer).
*/
@ -75,9 +75,21 @@ interface InvoiceInterface
const TRANSACTION_SPEED_MEDIUM = 'medium';
const TRANSACTION_SPEED_LOW = 'low';
/**
* This is the amount that is required to be collected from the buyer. Note, if this is
* specified in a currency other than BTC, the price will be converted into BTC at
* market exchange rates to determine the amount collected from the buyer.
*
* @return string
*/
public function getPrice();
public function getTaxIncluded();
/**
* This is the currency code set for the price setting.  The pricing currencies
* currently supported are USD, EUR, BTC, etc
* currently supported are USD, EUR, BTC, and all of the codes listed on this page:
* https://btcpayserver.com/bitcoin­exchange­rates
*
* @return CurrencyInterface
*/
@ -175,7 +187,16 @@ interface InvoiceInterface
public function isExtendedNotifications();
/**
* The unique id of the invoice assigned by BTCPayServer
* default value: false
* true: Redirect from the checkout UI to the set redirect url
* false: checkout UIwill not redirect but will display a button with a link to the set redirect url
*
* @return boolean
*/
public function isRedirectAutomatically();
/**
* The unique id of the invoice assigned by btcpayserver.com
*
* @return string
*/
@ -188,6 +209,14 @@ interface InvoiceInterface
*/
public function getUrl();
/**
* The amount of bitcoins being requested for payment of this invoice (same as the
* price if the merchant set the price in BTC).
*
* @return string
*/
public function getBtcPrice();
/**
* The time the invoice was created in milliseconds since midnight January 1,
* 1970. Time format is “2014­01­01T19:01:01.123Z”.
@ -206,7 +235,7 @@ interface InvoiceInterface
public function getExpirationTime();
/**
* The current time on the BTCPayServer system (by subtracting the current time from
* The current time on the BTCPayServer.com system (by subtracting the current time from
* the expiration time, the amount of time remaining for payment can be
* determined). Time format is “2014­01­01T19:01:01.123Z”.
*
@ -336,6 +365,13 @@ interface InvoiceInterface
*/
public function getExceptionStatus();
/**
*/
public function getBtcPaid();
/**
*/
public function getRate();
/**
*/
@ -352,38 +388,4 @@ interface InvoiceInterface
* @return array|object
*/
public function getRefundAddresses();
public function getTransactionCurrency();
public function getPaymentSubtotals();
/**
* Equivalent to price for each supported transactionCurrency, excluding minerFees.
* The key is the currency and the value is an amount indicated in the smallest possible unit
* for each supported transactionCurrency (e.g satoshis for BTC and BCH)
* ex: '{"BCH": 1023200, "BTC": 113100 }'
*/
public function getPaymentTotals();
public function getAmountPaid();
public function getExchangeRates();
/**
* Get the enforced transaction currencies.
*
* @return array|null
*/
public function getPaymentCurrencies();
/**
* Set specific invoice currencies and to enforce them on payment step.
*
* @param array $paymentCurrencies
* The currencies need to match what is supported by BTCPay Server.
* E.g. BTC, BTC_ONCHAIN, BTC_OFFCHAIN, LTC, XMR_MONEROLIKE etc.
*
* @return InvoiceInterface
*/
public function setPaymentCurrencies($paymentCurrencies);
}

View File

@ -29,6 +29,11 @@ class Item implements ItemInterface
*/
protected $price;
/**
* @var float
*/
protected $taxIncluded;
/**
* @var integer
*/
@ -96,6 +101,16 @@ class Item implements ItemInterface
return $this->price;
}
/**
* @inheritdoc
*
* @return float
*/
public function getTaxIncluded()
{
return $this->taxIncluded;
}
/**
* @param mixed $price A float, integer, or en_US formatted numeric string
*
@ -112,6 +127,17 @@ class Item implements ItemInterface
return $this;
}
public function setTaxIncluded($taxIncluded)
{
if (is_string($taxIncluded)) {
$this->checkPriceFormat($taxIncluded);
}
$this->taxIncluded = (float)$taxIncluded;
return $this;
}
/**
* @inheritdoc
*/
@ -157,16 +183,8 @@ class Item implements ItemInterface
* values with more than 6 decimals.
*
* @param string $price The price value to check
* @throws \Exception
*/
protected function checkPriceFormat($price)
{
if ($price === '0') {
return;
}
$converted = (float)$price;
if ($converted == 0) {
throw new \BTCPayServer\Client\ArgumentException("Price must be formatted as a float ". $converted);
}
}
}

View File

@ -34,6 +34,11 @@ interface ItemInterface
*/
public function getPrice();
/**
* @return string
*/
public function getTaxIncluded();
/**
* @return string
*/