├── .gitignore ├── GUIDE.md ├── LICENSE ├── README.md ├── composer.json ├── src └── BitPaySDKLight │ ├── Client.php │ ├── Config.php │ ├── Env.php │ ├── Exceptions │ ├── BillCreationException.php │ ├── BillDeliveryException.php │ ├── BillException.php │ ├── BillQueryException.php │ ├── BitPayException.php │ ├── CurrencyException.php │ ├── CurrencyQueryException.php │ ├── InvoiceCreationException.php │ ├── InvoiceException.php │ ├── InvoiceQueryException.php │ ├── RateException.php │ └── RateQueryException.php │ ├── Model │ ├── Bill │ │ ├── Bill.php │ │ ├── BillStatus.php │ │ └── Item.php │ ├── Currency.php │ ├── Facade.php │ ├── Invoice │ │ ├── Buyer.php │ │ ├── BuyerProvidedInfo.php │ │ ├── Invoice.php │ │ ├── InvoiceStatus.php │ │ ├── MinerFees.php │ │ ├── MinerFeesItem.php │ │ ├── RefundInfo.php │ │ ├── Shopper.php │ │ ├── SupportedTransactionCurrencies.php │ │ └── SupportedTransactionCurrency.php │ └── Rate │ │ ├── Rate.php │ │ └── Rates.php │ ├── Tokens.php │ └── Util │ ├── JsonMapper │ ├── JsonMapper.php │ └── JsonMapperException.php │ └── RESTcli │ └── RESTcli.php └── tests └── BitPaySDKLight └── BitPayTest.php /.gitignore: -------------------------------------------------------------------------------- 1 | composer.phar 2 | /vendor/ 3 | .idea 4 | 5 | # Commit your application's lock file https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control 6 | # You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file 7 | # composer.lock 8 | -------------------------------------------------------------------------------- /GUIDE.md: -------------------------------------------------------------------------------- 1 | # BitPay PHP light client 2 | 3 | This SDK provides a convenient abstraction of BitPay's [cryptographically-secure API](https://bitpay.com/api) and allows payment gateway developers to focus on payment flow/e-commerce integration rather than on the specific details of client-server interaction using the API. This SDK optionally provides the flexibility for developers to have control over important details, including the handling of private tokens needed for client-server communication. 4 | 5 | - [Dependencies](GUIDE.md#dependencies) 6 | - [Usage](GUIDE.md#usage) 7 | - [Getting your client token](GUIDE.md#getting-your-client-token) 8 | - [Installation](GUIDE.md#installation) 9 | - - [Composer](GUIDE.md#composer) 10 | - - - [Install composer](GUIDE.md#install-composer) 11 | - - - [Install via composer by hand](GUIDE.md#install-via-composer-by-hand) 12 | - - - [Install using composer](GUIDE.md#install-using-composer) 13 | - [Getting Started](GUIDE.md#getting-started) 14 | - - [Initializing your BitPay light client](GUIDE.md#initializing-your-bitPay-light-client) 15 | - - [Create an invoice](GUIDE.md#create-an-invoice) 16 | - - [Retrieve an invoice](GUIDE.md#retrieve-an-invoice) 17 | - - [Create bill](GUIDE.md#create-bill) 18 | - - [Get bill](GUIDE.md#get-bill) 19 | - - [Deliver bill](GUIDE.md#deliver-bill) 20 | - - [Get exchange rates](GUIDE.md#get-exchange-rates) 21 | - - [Get Currencies](GUIDE.md#get-currencies) 22 | - [Copyright](GUIDE.md#copyright) 23 | 24 | # Dependencies 25 | 26 | You must have a BitPay merchant account to use this SDK. It's free to [sign-up for a BitPay merchant account](https://bitpay.com/start). 27 | 28 | If you need a test account, 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. 29 | If you are looking for a testnet bitcoin wallet to test with, please visit https://bitpay.com/wallet and 30 | create a new wallet. 31 | If you need testnet bitcoin please visit a testnet faucet, e.g. https://testnet.coinfaucet.eu/en/ or http://tpfaucet.appspot.com/ 32 | 33 | For more information about testing, please see https://bitpay.com/docs/testing 34 | 35 | # Usage 36 | 37 | This library was built and tested using the PhpStorm IDE; the source code tree is directly compatible with Other PHP IDEs. 38 | Library dependencies can be downloaded by executing the following command at the root of the library: 39 | ```bash 40 | php composer.phar install 41 | ``` 42 | 43 | ## Getting your client token 44 | 45 | First of all, you need to generate a new POS token on your BitPay's account which will be required to securely connect to the BitPay's API. 46 | For testing purposes use: 47 | https://test.bitpay.com/dashboard/merchant/api-tokens 48 | 49 | For production use: 50 | https://bitpay.com/dashboard/merchant/api-tokens 51 | 52 | Click on 'Add New Token', give a name on the Token Label input, leave the 'Require Authentication' checkbox unchecked and click on 'Add Token'. 53 | The new token will appear and ready to use. 54 | 55 | ## Installation 56 | 57 | ### Composer 58 | 59 | ### Install Composer 60 | 61 | ```bash 62 | curl -sS https://getcomposer.org/installer | php 63 | ``` 64 | 65 | ### Install via composer by hand 66 | 67 | Add to your composer.json file by hand. 68 | 69 | ```bash 70 | { 71 | ... 72 | "require": { 73 | ... 74 | "bitpay/sdk-light": "^2.0" 75 | } 76 | ... 77 | } 78 | ``` 79 | 80 | Once you have added this, just run: 81 | 82 | ```bash 83 | php composer.phar update bitpay/sdk-light 84 | ``` 85 | 86 | ### Install using composer 87 | 88 | ```bash 89 | php composer.phar require bitpay/sdk-light:^2.0 90 | ``` 91 | 92 | ## Getting Started 93 | 94 | ### Initializing your BitPay light client 95 | 96 | Once you have your previously generated Token, you can initialize the client following this example: 97 | 98 | ```php 99 | $bitpay = new BitPaySDKLight\Client("CFJCZH3VitcEER9Uybx8LMvkPsSWzpSWvN4vhNEJp47b", BitPaySDKLight\Env::Test); 100 | ``` 101 | 102 | ### Create an invoice 103 | 104 | Invoices are time-sensitive payment requests addressed to specific buyers. An invoice has a fixed price, typically denominated in fiat currency. It also has an equivalent price in the supported cryptocurrencies, calculated by BitPay, at a locked exchange rate with an expiration time of 15 minutes. 105 | 106 | `POST /invoices` 107 | 108 | Facade `POS` 109 | 110 | #### HTTP Request 111 | 112 | Headers 113 | 114 | | Fields | Description | Presence | 115 | | --- | --- | :---: | 116 | | `X-Accept-Version` | Must be set to `2.0.0` for requests to the BitPay API. | Mandatory | 117 | | `Content-Type` | must be set to `application/json` for requests to the BitPay API. | Mandatory | 118 | 119 | Body 120 | 121 | | Name | Description | Type | Presence | 122 | | --- | --- | :---: | :---: | 123 | | `token` | The API token can be retrieved from the dashboard (limited to `pos` facade) or using the Tokens resource to get access to the `merchant` facade. This is described in the section [Request an API token](GUIDE.md#getting-your-client-token)) | `string` | Mandatory | 124 | | `price` | Fixed price amount for the checkout, in the "currency" of the invoice object | `string` | Mandatory | 125 | | `currency` | ISO 4217 3-character currency code. This is the currency associated with the price field, supported currencies are available via the Currencies resource | `string` | Mandatory | 126 | | `orderId` | Can be used by the merchant to assign their own internal Id to an invoice. If used, there should be a direct match between an orderId and an invoice id | `string` | Optional | 127 | | `itemDesc` | Invoice description - will be added as a line item on the BitPay checkout page, under the merchant name | `string` | Optional | 128 | | `itemCode` | "bitcoindonation" for donations, otherwise do not include the field in the request. | `string` | Optional | 129 | | `notificationEmail` | Merchant email address for notification of invoice status change. It is also possible to configure this email via the account setting on the BitPay dashboard or disable the email notification | `string` | Optional | 130 | | `notificationURL` | URL to which BitPay sends webhook notifications. HTTPS is mandatory. | `string` | Optional | 131 | | `redirectURL` | The shopper will be redirected to this URL when clicking on the Return button after a successful payment or when clicking on the Close button if a separate `closeURL` is not specified. Be sure to include "http://" or "https://" in the url. | `string` | Optional | 132 | | `closeURL` | URL to redirect if the shopper does not pay the invoice and click on the Close button instead. Be sure to include "http://" or "https://" in the url. 133 | | `string` | Optional | 134 | | `autoRedirect` | Set to `false` by default, merchant can setup automatic redirect to their website by setting this parameter to `true`. This will applied to the following scenarios: When the invoice is paid, it automatically redirects the shopper to the `redirectURL` indicated When the invoice expires, it automatically redirects the shopper to the `closeURL` if specified and to the `redirectURL` otherwise Note: If automatic redirect is enabled, `redirectURL` becomes a mandatory invoice parameters. | `boolean` | Optional | 135 | | `posData` | A passthru variable provided by the merchant during invoice creation and designed to be used by the merchant to correlate the invoice with an order or other object in their system. This passthru variable can be a serialized object, e.g.: `"posData": "\"{ \"ref\" : 711454, \"item\" : \"test_item\" }\""`. | `string` | Optional | 136 | | `transactionSpeed` | This is a risk mitigation parameter for the merchant to configure how they want to fulfill orders depending on the number of block confirmations for the transaction made by the consumer on the selected cryptocurrency. high: The invoice is marked as "confirmed" by BitPay as soon as full payment is received but not yet validated on the corresponding blockchain. The invoice will go from a status of "new" to "confirmed", bypassing the "paid" status. If you want an immediate notification for a payment, you can use the high speed setting. However, it makes you more susceptible to receiving fraudulent payments, so it is not recommended. medium: (Recommended for most merchants) The invoice is marked as "confirmed" after the transaction has received basic confirmation on the corresponding blockchain. For invoices paid in Bitcoin (BTC), this means 1 confirmation on the blockchain which takes on average 10 minutes. The invoice will go from a status of "new" to "paid" followed by "confirmed" and then "complete" low: The invoice is marked as "confirmed" once BitPay has credited the funds to the merchant account. The invoice will go from a status of "new" to "paid" followed by "complete", thus bypassing the "confirmed" status. For invoices paid in Bitcoin (BTC), this means 6 confirmations on the blockchain which takes on average an hour If not set on the invoice, transactionSpeed will default to the account-level Order Settings. Note : orders are only credited to your BitPay Account Summary for settlement after the invoice reaches the status "complete" (regardless of this setting). | `string` | Optional | 137 | | `fullNotifications` | This parameter is set to true by default, meaning all standard notifications are being sent for a payment made to an invoice. If you decide to set it to `false` instead, only 1 webhook will be sent for each invoice paid by the consumer. This webhook will be for the "confirmed" or "complete" invoice status, depending on the `transactionSpeed` selected. | `boolean` | Optional | 138 | | `extendedNotifications` | Allows merchants to get access to additional webhooks. For instance when an invoice expires without receiving a payment or when it is refunded. If set to `true`, then `fullNotifications` is automatically set to `true`. When using the `extendedNotifications` parameter, the webhook also have a payload slightly different from the standard webhooks. | `boolean` | Optional | 139 | | `physical` | Indicates whether items are physical goods. Alternatives include digital goods and services. | `boolean` | Optional | 140 | | `buyer` | Allows merchant to pass buyer related information in the invoice object | `object` | Optional | 141 | | → `name` | Buyer's name | `string` | Optional | 142 | | → `address1` | Buyer's address | `string` | Optional | 143 | | → `address2` | Buyer's appartment or suite number | `string` | Optional | 144 | | → `locality` | Buyer's city or locality | `string` | Optional | 145 | | → `region` | Buyer's state or province | `string` | Optional | 146 | | → `postalCode` | Buyer's Zip or Postal Code | `string` | Optional | 147 | | → `country` | Buyer's Country code. Format ISO 3166-1 alpha-2 | `string` | Optional | 148 | | → `email` | Buyer's email address. If provided during invoice creation, this will bypass the email prompt for the consumer when opening the invoice. | `string` | Optional | 149 | | → `phone` | Buyer's phone number | `string` | Optional | 150 | | → `notify` | Indicates whether a BitPay email confirmation should be sent to the buyer once he has paid the invoice | `boolean` | Optional | 151 | | `paymentCurrencies` | Allow the merchant to select the cryptocurrencies available as payment option on the BitPay invoice. Possible values are currently `"BTC"`, `"BCH"`, `"ETH"`, `"GUSD"`, `"PAX"`, `"BUSD"`, `"USDC"`, `"XRP"`, `"DOGE"`, `"DAI"` and `"WBTC"`. For instance `"paymentCurrencies": ["BTC"]` will create an invoice with only XRP available as transaction currency, thus bypassing the currency selection step on the invoice. | `array` | Optional | 152 | | `jsonPayProRequired` | If set to `true`, this means that the invoice will only accept payments from wallets which have implemented the [BitPay JSON Payment Protocol](https://bitpay.com/docs/payment-protocol) | `boolean` | Optional | 153 | 154 | An example code of the create invoice 155 | 156 | ```php 157 | $invoice = new Invoice(50.0, "USD"); 158 | $invoice->setToken($bitpay->_token); 159 | $invoice->setOrderId("65f5090680f6"); 160 | $invoice->setFullNotifications(true); 161 | $invoice->setExtendedNotifications(true); 162 | $invoice->setNotificationURL("https://hookbin.com/lJnJg9WW7MtG9GZlPVdj"); 163 | $invoice->setRedirectURL("https://hookbin.com/lJnJg9WW7MtG9GZlPVdj"); 164 | $invoice->setItemDesc("Ab tempora sed ut."); 165 | $invoice->setNotificationEmail(""); 166 | 167 | $buyer = new Buyer(); 168 | $buyer->setName("Bily Matthews"); 169 | $buyer->setEmail(""); 170 | $buyer->setAddress1("168 General Grove"); 171 | $buyer->setAddress2(""); 172 | $buyer->setCountry("AD"); 173 | $buyer->setLocality("Port Horizon"); 174 | $buyer->setNotify(true); 175 | $buyer->setPhone("+990123456789"); 176 | $buyer->setPostalCode("KY7 1TH"); 177 | $buyer->setRegion("New Port"); 178 | 179 | $invoice->setBuyer($buyer); 180 | 181 | $basicInvoice = $bitpay->createInvoice($invoice); 182 | ``` 183 | 184 | HTTP Response 185 | 186 | ```json 187 | { 188 | "facade": "pos/invoice", 189 | "data": { 190 | "url": "https://bitpay.com/invoice?id=KSnNNfoMDsbRzd1U9ypmVH", 191 | "status": "new", 192 | "price": 10, 193 | "currency": "USD", 194 | "orderId": "20210511_abcde", 195 | "invoiceTime": 1620734545366, 196 | "expirationTime": 1620735445366, 197 | "currentTime": 1620734545415, 198 | "id": "KSnNNfoMDsbRzd1U9ypmVH", 199 | "lowFeeDetected": false, 200 | "amountPaid": 0, 201 | "displayAmountPaid": "0", 202 | "exceptionStatus": false, 203 | "redirectURL": "https://merchantwebsite.com/shop/return", 204 | "refundAddressRequestPending": false, 205 | "buyerProvidedInfo": {}, 206 | "paymentSubtotals": { 207 | "BTC": 18200, 208 | "BCH": 744500, 209 | "ETH": 2535000000000000, 210 | "GUSD": 1000, 211 | "PAX": 10000000000000000000, 212 | "BUSD": 10000000000000000000, 213 | "USDC": 10000000, 214 | "XRP": 7084249, 215 | "DOGE": 2068707100, 216 | "DAI": 9990000000000000000, 217 | "WBTC": 18100 218 | }, 219 | "paymentTotals": { 220 | "BTC": 29800, 221 | "BCH": 744500, 222 | "ETH": 2535000000000000, 223 | "GUSD": 1000, 224 | "PAX": 10000000000000000000, 225 | "BUSD": 10000000000000000000, 226 | "USDC": 10000000, 227 | "XRP": 7084249, 228 | "DOGE": 2068707100, 229 | "DAI": 9990000000000000000, 230 | "WBTC": 18100 231 | }, 232 | "paymentDisplayTotals": { 233 | "BTC": "0.000298", 234 | "BCH": "0.007445", 235 | "ETH": "0.002535", 236 | "GUSD": "10.00", 237 | "PAX": "10.00", 238 | "BUSD": "10.00", 239 | "USDC": "10.00", 240 | "XRP": "7.084249", 241 | "DOGE": "20.687071", 242 | "DAI": "9.99", 243 | "WBTC": "0.000181" 244 | }, 245 | "paymentDisplaySubTotals": { 246 | "BTC": "0.000182", 247 | "BCH": "0.007445", 248 | "ETH": "0.002535", 249 | "GUSD": "10.00", 250 | "PAX": "10.00", 251 | "BUSD": "10.00", 252 | "USDC": "10.00", 253 | "XRP": "7.084249", 254 | "DOGE": "20.687071", 255 | "DAI": "9.99", 256 | "WBTC": "0.000181" 257 | }, 258 | "exchangeRates": { 259 | "BTC": { 260 | "USD": 55072.459995, 261 | "EUR": 45287.42496000001, 262 | "BCH": 40.884360403999914, 263 | "ETH": 13.953840617367156, 264 | "GUSD": 55072.459995, 265 | "PAX": 55072.459995, 266 | "BUSD": 55072.459995, 267 | "USDC": 55072.459995, 268 | "XRP": 38907.54307403195, 269 | "DOGE": 113694.39064944115, 270 | "DAI": 55018.486859390934, 271 | "WBTC": 0.9983514430763876 272 | }, 273 | "BCH": { 274 | "USD": 1343.1537000000003, 275 | "EUR": 1104.481875, 276 | "BTC": 0.02437664632426631, 277 | "ETH": 0.34031805835672807, 278 | "GUSD": 1343.1537000000003, 279 | "PAX": 1343.1537000000003, 280 | "BUSD": 1343.1537000000003, 281 | "USDC": 1343.1537000000003, 282 | "XRP": 948.9100440136494, 283 | "DOGE": 2772.8748903518513, 284 | "DAI": 1341.8373575522414, 285 | "WBTC": 0.024348638771359274 286 | }, 287 | "ETH": { 288 | "USD": 3944.6466899999996, 289 | "EUR": 3242.8077850000004, 290 | "BTC": 0.07159065804331831, 291 | "BCH": 2.9284029977060646, 292 | "GUSD": 3944.6466899999996, 293 | "PAX": 3944.6466899999996, 294 | "BUSD": 3944.6466899999996, 295 | "USDC": 3944.6466899999996, 296 | "XRP": 2786.8105223000134, 297 | "DOGE": 8143.529484384802, 298 | "DAI": 3940.7807840508463, 299 | "WBTC": 0.07150840394174397 300 | }, 301 | ... 302 | }, 303 | "supportedTransactionCurrencies": { 304 | "BTC": { 305 | "enabled": true 306 | }, 307 | "BCH": { 308 | "enabled": true 309 | }, 310 | "ETH": { 311 | "enabled": true 312 | }, 313 | ... 314 | }, 315 | "minerFees": { 316 | "BTC": { 317 | "satoshisPerByte": 79.152, 318 | "totalFee": 11600 319 | }, 320 | "BCH": { 321 | "satoshisPerByte": 0, 322 | "totalFee": 0 323 | }, 324 | "ETH": { 325 | "satoshisPerByte": 0, 326 | "totalFee": 0 327 | }, 328 | ... 329 | }, 330 | "jsonPayProRequired": false, 331 | "paymentCodes": { 332 | "BTC": { 333 | "BIP72b": "bitcoin:?r=https://bitpay.com/i/KSnNNfoMDsbRzd1U9ypmVH", 334 | "BIP73": "https://bitpay.com/i/KSnNNfoMDsbRzd1U9ypmVH" 335 | }, 336 | "BCH": { 337 | "BIP72b": "bitcoincash:?r=https://bitpay.com/i/KSnNNfoMDsbRzd1U9ypmVH", 338 | "BIP73": "https://bitpay.com/i/KSnNNfoMDsbRzd1U9ypmVH" 339 | }, 340 | "ETH": { 341 | "EIP681": "ethereum:?r=https://bitpay.com/i/KSnNNfoMDsbRzd1U9ypmVH" 342 | }, 343 | ... 344 | }, 345 | "token": "8nPJSGgi7omxcbGGZ4KsSgqdi6juypBe9pVpSURDeAwx4VDQx1XfWPy5qqknDKT9KQ" 346 | } 347 | } 348 | ``` 349 | 350 | To get the generated invoice url and status 351 | 352 | ```php 353 | $invoiceUrl = $basicInvoice->getURL(); 354 | 355 | $status = $basicInvoice->getStatus(); 356 | ``` 357 | 358 | > **WARNING**: 359 | If you get the following error when initiating the client for first time: 360 | "500 Internal Server Error` response: {"error":"Account not setup completely yet."}" 361 | Please, go back to your BitPay account and complete the required steps. 362 | More info [here](https://support.bitpay.com/hc/en-us/articles/203010446-How-do-I-apply-for-a-merchant-account-) 363 | 364 | ### Retrieve an invoice 365 | 366 | `GET /invoices/:invoiceid` 367 | 368 | ### Facade `POS` 369 | 370 | ### HTTP Request 371 | 372 | URL Parameters 373 | 374 | | Parameter | Description | Type | Presence | 375 | | --- | --- | :---: | :---: | 376 | | `?token=` | When fetching an invoice the `pos` facade, pass the API token as a URL parameter - the same token used to create the invoice in the first place. | `string` | Mandatory | 377 | 378 | Headers 379 | 380 | | Fields | Description | Presence | 381 | | --- | --- | :---: | 382 | | `X-Accept-Version` | Must be set to `2.0.0` for requests to the BitPay API. | Mandatory | 383 | | `Content-Type` | must be set to `application/json` for requests to the BitPay API. | Mandatory | 384 | 385 | 386 | To get the generated invoice details, pass the Invoice Id with URL parameter 387 | 388 | ```php 389 | $invoice = $bitpay->getInvoice($basicInvoice->getId()); 390 | ``` 391 | 392 | 393 | ### Create bill 394 | 395 | Bills are payment requests addressed to specific buyers. Bill line items have fixed prices, typically denominated in fiat currency. 396 | 397 | `POST /bills` 398 | 399 | ### Facade `POS` 400 | 401 | ### HTTP Request 402 | 403 | Headers 404 | 405 | | Fields | Description | Presence | 406 | | --- | --- | :---: | 407 | | `X-Accept-Version` | Must be set to `2.0.0` for requests to the BitPay API. | Mandatory | 408 | | `Content-Type` | must be set to `application/json` for requests to the BitPay API. | Mandatory | 409 | 410 | Body 411 | 412 | | Name | Description | Type | Presence | 413 | | --- | --- | :---: | :---: | 414 | | `number` | Bill identifier, specified by merchant | `string` | Optional | 415 | | `currency` | ISO 4217 3-character currency code. This is the currency associated with the price field | `string` | Mandatory | 416 | | `name` | Bill recipient's name | `string` | Optional | 417 | | `address1` | Bill recipient's address | `string` | Optional | 418 | | `address2` | Bill recipient's address | `string` | Optional | 419 | | `city` | Bill recipient's city | `string` | Optional | 420 | | `state` | Bill recipient's state or province | `string` | Optional | 421 | | `zip` | Bill recipient's ZIP code | `string` | Optional | 422 | | `country` | Bill recipient's country | `string` | Optional | 423 | | `email` | Bill recipient's email address | `string` | Mandatory | 424 | | `cc` | Email addresses to which a copy of the bill must be sent | `array` | Optional | 425 | | `phone` | Bill recipient's phone number | `string` | Optional | 426 | | `dueDate` | Date and time at which a bill is due, ISO-8601 format yyyy-mm-ddThh:mm:ssZ. (UTC) | `string` | Optional | 427 | | `passProcessingFee` | If set to `true`, BitPay's processing fee will be included in the amount charged on the invoice | `boolean` | Optional | 428 | | `items` | List of line items | `string` | Mandatory | 429 | | → `description` | Line item description | `string` | Mandatory | 430 | | → `price` | Line item unit price for the corresponding `currency` | `number` | Mandatory | 431 | | → `quantity` | Bill identifier, specified by merchant | `number` | Mandatory | 432 | | `token` | The API token can be retrieved from the dashboard (limited to pos facade) | `string` | Mandatory | 433 | 434 | ```php 435 | $items = []; 436 | 437 | $item = new Item(); 438 | $item->setPrice(6.0); 439 | $item->setQuantity(1); 440 | $item->setDescription("Test Item 1"); 441 | array_push($items, $item); 442 | 443 | $item = new Item(); 444 | $item->setPrice(4.0); 445 | $item->setQuantity(1); 446 | $item->setDescription("Test Item 2"); 447 | array_push($items, $item); 448 | 449 | $bill = new Bill("bill1234-ABCD", Currency::USD, "", $items); 450 | $bill->setEmail("john@doe.com"); 451 | 452 | $basicBill = $this->_client->createBill($bill); 453 | ``` 454 | 455 | ### HTTP Response 456 | 457 | ```json 458 | { 459 | "facade": "pos/bill", 460 | "data": { 461 | "status": "draft", 462 | "url": "https://bitpay.com/bill?id=X6KJbe9RxAGWNReCwd1xRw&resource=bills", 463 | "number": "bill1234-ABCD", 464 | "createdDate": "2021-05-21T09:48:02.373Z", 465 | "dueDate": "2021-05-31T00:00:00.000Z", 466 | "currency": "USD", 467 | "email": "john@doe.com", 468 | "cc": [ 469 | "jane@doe.com" 470 | ], 471 | "passProcessingFee": true, 472 | "id": "X6KJbe9RxAGWNReCwd1xRw", 473 | "items": [ 474 | { 475 | "id": "EL4vx41Nxc5RYhbqDthjE", 476 | "description": "Test Item 1", 477 | "price": 6, 478 | "quantity": 1 479 | }, 480 | { 481 | "id": "6spPADZ2h6MfADvnhfsuBt", 482 | "description": "Test Item 2", 483 | "price": 4, 484 | "quantity": 1 485 | } 486 | ], 487 | "token": "qVVgRARN6fKtNZ7Tcq6qpoPBBE3NxdrmdMD883RyMK4Pf8EHENKVxCXhRwyynWveo" 488 | } 489 | } 490 | ``` 491 | 492 | 493 | ### Get bill 494 | 495 | `GET /bills/:billid` 496 | 497 | ### Facade `POS` 498 | 499 | ### HTTP Request 500 | 501 | URL Parameters 502 | 503 | | Parameter | Description | Type | Presence | 504 | | --- | --- | :---: | :---: | 505 | | `?token=` | when fetching settlememts, pass a merchant facade token as a URL parameter. | `string` | Mandatory | 506 | 507 | Headers 508 | 509 | | Fields | Description | Presence | 510 | | --- | --- | :---: | 511 | | `X-Accept-Version` | Must be set to `2.0.0` for requests to the BitPay API. | Mandatory | 512 | | `Content-Type` | must be set to `application/json` for requests to the BitPay API. | Mandatory | 513 | 514 | ```php 515 | $retrievedBill = $bitpay->getBill($bill->getId()); 516 | ``` 517 | ### HTTP Response 518 | 519 | ```json 520 | { 521 | "facade": "pos/bill", 522 | "data": { 523 | "status": "draft", 524 | "url": "https://bitpay.com/bill?id=X6KJbe9RxAGWNReCwd1xRw&resource=bills", 525 | "number": "bill1234-ABCD", 526 | "createdDate": "2021-05-21T09:48:02.373Z", 527 | "dueDate": "2021-05-31T00:00:00.000Z", 528 | "currency": "USD", 529 | "email": "john@doe.com", 530 | "cc": [ 531 | "jane@doe.com" 532 | ], 533 | "passProcessingFee": true, 534 | "id": "X6KJbe9RxAGWNReCwd1xRw", 535 | "items": [ 536 | { 537 | "id": "EL4vx41Nxc5RYhbqDthjE", 538 | "description": "Test Item 1", 539 | "price": 6, 540 | "quantity": 1 541 | }, 542 | { 543 | "id": "6spPADZ2h6MfADvnhfsuBt", 544 | "description": "Test Item 2", 545 | "price": 4, 546 | "quantity": 1 547 | } 548 | ], 549 | "token": "qVVgRARN6fKtNZ7Tcq6qpoPBBE3NxdrmdMD883RyMK4Pf8EHENKVxCXhRwyynWveo" 550 | } 551 | } 552 | ``` 553 | 554 | 555 | ### Deliver bill 556 | 557 | `GET /bills/:billid/deliveries` 558 | 559 | ### Facade `POS` 560 | 561 | ### HTTP Request 562 | 563 | URL Parameters 564 | 565 | | Parameter | Description | Type | Presence | 566 | | --- | --- | :---: | :---: | 567 | | `billId` | the id of the bill you want to deliver via email. | `string` | Mandatory | 568 | 569 | Headers 570 | 571 | | Fields | Description | Presence | 572 | | --- | --- | :---: | 573 | | `X-Accept-Version` | Must be set to `2.0.0` for requests to the BitPay API. | Mandatory | 574 | | `Content-Type` | must be set to `application/json` for requests to the BitPay API. | Mandatory | 575 | 576 | Body 577 | 578 | | Name | Description | Type | Presence | 579 | | --- | --- | :---: | :---: | 580 | | `token` | The resource token for the billId you want to deliver via email. You need to retrieve this token from the bill object itself. | `string` | Mandatory | 581 | 582 | ```php 583 | $deliveredBill = $bitpay->deliverBill($bill->getId()); 584 | ``` 585 | HTTP Response 586 | 587 | Body 588 | 589 | | Name | Description | Type | 590 | | --- | --- | :---: | 591 | | `data` | set to `"Success"` once a bill is successfully sent via email. | `string` | 592 | 593 | ```json 594 | { 595 | "data": "Success" 596 | } 597 | ``` 598 | 599 | ### Get exchange Rates 600 | 601 | Rates are exchange rates, representing the number of fiat currency units equivalent to one BTC. You can retrieve BitPay's [BBB exchange rates](https://bitpay.com/exchange-rates). 602 | 603 | `GET /rates/:basecurrency` 604 | 605 | ### Facade `PUBLIC` 606 | 607 | ### HTTP Request 608 | 609 | URL Parameters 610 | 611 | | Parameter | Description | Type | Presence | 612 | | --- | --- | :---: | :---: | 613 | | `baseCurrency` | the cryptocurrency for which you want to fetch the rates. Current supported values are BTC and BCH. | `string` | Mandatory | 614 | 615 | Headers 616 | 617 | | Fields | Description | Presence | 618 | | --- | --- | :---: | 619 | | `X-Accept-Version` | Must be set to `2.0.0` for requests to the BitPay API. | Mandatory | 620 | | `Content-Type` | must be set to `application/json` for requests to the BitPay API. | Mandatory | 621 | 622 | ```php 623 | $rates = $bitpay->getRates(); 624 | 625 | $rate = $rates->getRate(Currency::USD); //Always use the included Currency model to avoid typos 626 | 627 | $rates->update(); 628 | ``` 629 | HTTP Response 630 | 631 | Body 632 | 633 | | Name | Description | Type | 634 | | --- | --- | :---: | 635 | | `data` | array of currency rates for the requested `baseCurrency`. | `array` | 636 | | → `code` | ISO 4217 3-character currency code. | `string` | 637 | | → `name` | detailed currency name. | `string` | 638 | | → `rate` | rate for the requested `baseCurrency` /`currency` pair. | `number` | 639 | 640 | ```json 641 | { 642 | "data":[ 643 | { 644 | "code":"BTC", 645 | "name":"Bitcoin", 646 | "rate":1 647 | }, 648 | { 649 | "code":"BCH", 650 | "name":"Bitcoin Cash", 651 | "rate":50.77 652 | }, 653 | { 654 | "code":"USD", 655 | "name":"US Dollar", 656 | "rate":41248.11 657 | }, 658 | { 659 | "code":"EUR", 660 | "name":"Eurozone Euro", 661 | "rate":33823.04 662 | }, 663 | { 664 | "code":"GBP", 665 | "name":"Pound Sterling", 666 | "rate":29011.49 667 | }, 668 | { 669 | "code":"JPY", 670 | "name":"Japanese Yen", 671 | "rate":4482741 672 | }, 673 | { 674 | "code":"CAD", 675 | "name":"Canadian Dollar", 676 | "rate":49670.85 677 | }, 678 | { 679 | "code":"AUD", 680 | "name":"Australian Dollar", 681 | "rate":53031.99 682 | }, 683 | { 684 | "code":"CNY", 685 | "name":"Chinese Yuan", 686 | "rate":265266.57 687 | }, 688 | ... 689 | ] 690 | } 691 | ``` 692 | 693 | You can retrieve all the rates for a given cryptocurrency 694 | 695 | URL Parameters 696 | 697 | | Parameter | Description | Type | Presence | 698 | | --- | --- | :---: | :---: | 699 | | `baseCurrency` | the cryptocurrency for which you want to fetch the rates. Current supported values are BTC and BCH. | `string` | Mandatory | 700 | | `currency` | the fiat currency for which you want to fetch the `baseCurrency` rates. | `string` | Mandatory | 701 | 702 | Headers 703 | 704 | | Fields | Description | Presence | 705 | | --- | --- | :---: | 706 | | `X-Accept-Version` | Must be set to `2.0.0` for requests to the BitPay API. | Mandatory | 707 | | `Content-Type` | must be set to `application/json` for requests to the BitPay API. | Mandatory | 708 | 709 | ```php 710 | $rates = $bitpay->getCurrencyRates(Currency::ETH); 711 | 712 | $rate = $rates->getRate(Currency::USD); 713 | ``` 714 | 715 | You can retrieve the rate for a cryptocurrency / fiat pair 716 | 717 | ```php 718 | $rate = $bitpay->getCurrencyPairRate(Currency::BTC, Currency::USD); 719 | ``` 720 | 721 | HTTP Response 722 | 723 | Body 724 | 725 | | Name | Description | Type | 726 | | --- | --- | :---: | 727 | | `data` | rate data object. | `object` | 728 | | → `code` | ISO 4217 3-character currency code. | `string` | 729 | | → `name` | detailed currency name. | `string` | 730 | | → `rate` | rate for the requested `baseCurrency` /`currency` pair. | `number` | 731 | 732 | ```json 733 | { 734 | "data": 735 | { 736 | "code":"USD", 737 | "name":"US Dollar", 738 | "rate":41154.05 739 | } 740 | } 741 | ``` 742 | 743 | 744 | 745 | See also the test package for more examples of API calls. 746 | 747 | ### Get Currencies 748 | 749 | `GET /currencies` 750 | 751 | ### Facade `PUBLIC` 752 | 753 | ### HTTP Request 754 | 755 | Headers 756 | 757 | | Fields | Description | Presence | 758 | | --- | --- | :---: | 759 | | `X-Accept-Version` | Must be set to `2.0.0` for requests to the BitPay API. | Mandatory | 760 | | `Content-Type` | must be set to `application/json` for requests to the BitPay API. | Mandatory | 761 | 762 | You can retrieve all the currencies supported by BitPay. 763 | 764 | ```php 765 | $currencies = $bitpay->getCurrencies(); 766 | ``` 767 | HTTP Response 768 | 769 | Body 770 | 771 | | Name | Description | Type | 772 | | --- | --- | :---: | 773 | | `data` | Array of supported currencies | `array` | 774 | | → `code` | ISO 4217 3-character currency code | `string` | 775 | | → `symbol` | Display symbol | `string` | 776 | | → `precision` | Number of decimal places | `number` | 777 | | → `name` | English currency name | `string` | 778 | | → `plural` | English plural form | `string` | 779 | | → `alts` | Alternative currency name(s) | `string` | 780 | | → `minimum` | Minimum supported value when creating an invoice, bill or payout for instance | `string` | 781 | | → `sanctionned` | If the currency is linked to a sanctionned country | `boolean` | 782 | | → `decimals` | decimal precision | `number` | 783 | | → `chain` | For cryptocurrencies or tokens, the corresponding chain is also specified. For instance, with `USDC` (Circle USD Coin), the `chain` is `ETH`. | `string` | 784 | 785 | ```json 786 | { 787 | "data": [ 788 | { 789 | "code": "BTC", 790 | "symbol": "฿", 791 | "precision": 6, 792 | "name": "Bitcoin", 793 | "plural": "Bitcoin", 794 | "alts": "btc", 795 | "minimum": 0.000006, 796 | "sanctioned": false, 797 | "decimals": 8, 798 | "chain": "BTC" 799 | }, 800 | ... 801 | ... 802 | { 803 | "code": "XRP", 804 | "symbol": "Ʀ", 805 | "precision": 6, 806 | "name": "Ripple", 807 | "plural": "Ripple", 808 | "alts": "xrp", 809 | "minimum": 0.000006, 810 | "sanctioned": false, 811 | "decimals": 6, 812 | "chain": "XRP" 813 | }, 814 | ... 815 | ... 816 | { 817 | "code": "EUR", 818 | "symbol": "€", 819 | "precision": 2, 820 | "name": "Eurozone Euro", 821 | "plural": "Eurozone Euros", 822 | "alts": "eur", 823 | "minimum": 0.01, 824 | "sanctioned": false, 825 | "decimals": 2 826 | }, 827 | ... 828 | ... 829 | { 830 | "code": "USD", 831 | "symbol": "$", 832 | "precision": 2, 833 | "name": "US Dollar", 834 | "plural": "US Dollars", 835 | "alts": "usd bucks", 836 | "minimum": 0.01, 837 | "sanctioned": false, 838 | "decimals": 2 839 | }, 840 | { 841 | "code": "USDC", 842 | "symbol": "$", 843 | "precision": 2, 844 | "name": "Circle USD Coin", 845 | "plural": "Circle USD Coin", 846 | "alts": "", 847 | "minimum": 0.01, 848 | "sanctioned": false, 849 | "decimals": 6, 850 | "chain": "ETH" 851 | }, 852 | ... 853 | ... 854 | ] 855 | } 856 | ``` 857 | 858 | 859 | # Copyright 860 | 861 | Copyright (c) 2019 BitPay 862 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 BitPay 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # BitPay PHP Light Client 4 | [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](https://raw.githubusercontent.com/bitpay/php-bitpay-light-client/master/LICENSE.md) 5 | [![Packagist](https://img.shields.io/packagist/v/bitpay/sdk-light.svg?style=flat-square)](https://packagist.org/packages/bitpay/sdk-light) 6 | [![Total Downloads](https://poser.pugx.org/bitpay/sdk-light/downloads.svg)](https://packagist.org/packages/bitpay/sdk-light) 7 | [![Latest Unstable Version](https://poser.pugx.org/bitpay/sdk-light/v/unstable.svg)](https://packagist.org/packages/bitpay/sdk-light) 8 | 9 | Light implementation of the client for the BitPay's [Cryptographically Secure RESTful API](https://bitpay.com/api). 10 | 11 | ## Getting Started 12 | 13 | To get up and running with our PHP library quickly, follow [The GUIDE](https://github.com/bitpay/php-bitpay-light-client/blob/master/GUIDE.md) 14 | 15 | ## Support 16 | 17 | * https://github.com/bitpay/php-bitpay-light-client/issues 18 | * https://support.bitpay.com 19 | 20 | ## Contribute 21 | 22 | To contribute to this project, please fork and submit a pull request. 23 | 24 | ## License 25 | 26 | MIT License 27 | 28 | Copyright (c) 2019 BitPay 29 | 30 | Permission is hereby granted, free of charge, to any person obtaining a copy 31 | of this software and associated documentation files (the "Software"), to deal 32 | in the Software without restriction, including without limitation the rights 33 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 34 | copies of the Software, and to permit persons to whom the Software is 35 | furnished to do so, subject to the following conditions: 36 | 37 | The above copyright notice and this permission notice shall be included in all 38 | copies or substantial portions of the Software. 39 | 40 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 41 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 42 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 43 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 44 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 45 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 46 | SOFTWARE. 47 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bitpay/sdk-light", 3 | "description": "Light version of the PHP library for the new cryptographically secure BitPay API", 4 | "license": "MIT", 5 | "minimum-stability": "stable", 6 | "keywords": [ 7 | "bitpay", 8 | "bitcoin", 9 | "cash", 10 | "payment", 11 | "gateway" 12 | ], 13 | "homepage": "https://github.com/bitpay/php-bitpay-light-client", 14 | "require": { 15 | "php": "^7.4 || ^8.0", 16 | "guzzlehttp/guzzle": "^6.3 || ^7.0", 17 | "ext-json": "*", 18 | "ext-openssl": "*" 19 | }, 20 | "authors": [ 21 | { 22 | "name": "Antonio Buedo", 23 | "email": "solutions-engineering@bitpay.com" 24 | } 25 | ], 26 | "require-dev": { 27 | "phpunit/phpunit": "^7.5 || ^9.0" 28 | }, 29 | "autoload": { 30 | "psr-4": { 31 | "BitPaySDKLight\\": "src/BitPaySDKLight" 32 | } 33 | }, 34 | "autoload-dev": { 35 | "psr-4": { 36 | "BitPaySDKLight\\Test\\": "tests/BitPaySDKLight" 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/BitPaySDKLight/Client.php: -------------------------------------------------------------------------------- 1 | _token = $token; 53 | $this->_env = strtolower($environment) == "test" ? Env::Test : Env::Prod; 54 | $this->init(); 55 | } catch (Exception $e) { 56 | throw new BitPayException("failed to initialize BitPay Light Client (Config) : ".$e->getMessage()); 57 | } 58 | 59 | } 60 | 61 | /** 62 | * Initialize this object with the selected environment. 63 | * 64 | * @throws BitPayException BitPayException class 65 | */ 66 | private function init() 67 | { 68 | try { 69 | $this->_RESTcli = new RESTcli($this->_env); 70 | } catch (Exception $e) { 71 | throw new BitPayException("failed to build configuration : ".$e->getMessage()); 72 | } 73 | } 74 | 75 | /** 76 | * Returns a GUID for use in REST calls. 77 | * 78 | * @see http://en.wikipedia.org/wiki/Globally_unique_identifier 79 | * 80 | * @return string 81 | */ 82 | private function guid() 83 | { 84 | return sprintf( 85 | '%s-%s-%s-%s-%s', 86 | bin2hex(openssl_random_pseudo_bytes(4)), 87 | bin2hex(openssl_random_pseudo_bytes(2)), 88 | bin2hex(openssl_random_pseudo_bytes(2)), 89 | bin2hex(openssl_random_pseudo_bytes(2)), 90 | bin2hex(openssl_random_pseudo_bytes(6)) 91 | ); 92 | } 93 | 94 | /** 95 | * Create a BitPay invoice. 96 | * 97 | * @param $invoice Invoice An Invoice object with request parameters defined. 98 | * 99 | * @return Invoice $invoice Invoice A BitPay generated Invoice object. 100 | * @throws InvoiceCreationException InvoiceCreationException class 101 | * @throws BitPayException BitPayException class 102 | */ 103 | public function createInvoice( 104 | Invoice $invoice 105 | ): Invoice { 106 | try { 107 | $invoice->setToken($this->_token); 108 | $invoice->setGuid($this->guid()); 109 | 110 | $responseJson = $this->_RESTcli->post("invoices", $invoice->toArray()); 111 | } catch (BitPayException $e) { 112 | throw new InvoiceCreationException("failed to serialize Invoice object : ".$e->getMessage(), null, null, $e->getApiCode()); 113 | } catch (Exception $e) { 114 | throw new InvoiceCreationException("failed to serialize Invoice object : ".$e->getMessage()); 115 | } 116 | 117 | try { 118 | $mapper = new JsonMapper(); 119 | $invoice = $mapper->map( 120 | json_decode($responseJson), 121 | new Invoice() 122 | ); 123 | 124 | } catch (Exception $e) { 125 | throw new InvoiceCreationException( 126 | "failed to deserialize BitPay server response (Invoice) : ".$e->getMessage()); 127 | } 128 | 129 | return $invoice; 130 | } 131 | 132 | /** 133 | * Retrieve a BitPay invoice. 134 | * 135 | * @param $invoiceId string The id of the invoice to retrieve. 136 | * 137 | * @return Invoice A BitPay Invoice object. 138 | * @throws InvoiceQueryException InvoiceQueryException class 139 | * @throws BitPayException BitPayException class 140 | */ 141 | public function getInvoice( 142 | string $invoiceId 143 | ): Invoice { 144 | try { 145 | $params = []; 146 | $params["token"] = $this->_token; 147 | 148 | $responseJson = $this->_RESTcli->get("invoices/".$invoiceId, $params); 149 | } catch (BitPayException $e) { 150 | throw new InvoiceQueryException("failed to serialize Invoice object : ".$e->getMessage(), null, null, $e->getApiCode()); 151 | } catch (Exception $e) { 152 | throw new InvoiceQueryException("failed to serialize Invoice object : ".$e->getMessage()); 153 | } 154 | 155 | try { 156 | $mapper = new JsonMapper(); 157 | $invoice = $mapper->map( 158 | json_decode($responseJson), 159 | new Invoice() 160 | ); 161 | 162 | } catch (Exception $e) { 163 | throw new InvoiceQueryException( 164 | "failed to deserialize BitPay server response (Invoice) : ".$e->getMessage()); 165 | } 166 | 167 | return $invoice; 168 | } 169 | 170 | /** 171 | * Create a BitPay Bill. 172 | * 173 | * @param Bill $bill string A Bill object with request parameters defined. 174 | * 175 | * @return Bill A BitPay generated Bill object. 176 | * @throws BillCreationException BillCreationException class 177 | * @throws BitPayException BitPayException class 178 | */ 179 | public function createBill(Bill $bill): Bill 180 | { 181 | try { 182 | $bill->setToken($this->_token); 183 | 184 | $responseJson = $this->_RESTcli->post("bills", $bill->toArray()); 185 | } catch (BitPayException $e) { 186 | throw new BillCreationException("failed to serialize Bill object : ".$e->getMessage(), null, null, $e->getApiCode()); 187 | } catch (Exception $e) { 188 | throw new BillCreationException("failed to serialize Bill object : ".$e->getMessage()); 189 | } 190 | 191 | try { 192 | $mapper = new JsonMapper(); 193 | $bill = $mapper->map( 194 | json_decode($responseJson), 195 | new Bill() 196 | ); 197 | 198 | } catch (Exception $e) { 199 | throw new BillCreationException( 200 | "failed to deserialize BitPay server response (Bill) : ".$e->getMessage()); 201 | } 202 | 203 | return $bill; 204 | } 205 | 206 | /** 207 | * Retrieve a BitPay bill by bill id. 208 | * 209 | * @param $billId string The id of the bill to retrieve. 210 | * @return Bill A BitPay Bill object. 211 | * @throws BillQueryException BillQueryException class 212 | * @throws BitPayException BitPayException class 213 | */ 214 | public function getBill(string $billId): Bill 215 | { 216 | 217 | try { 218 | $params = []; 219 | $params["token"] = $this->_token; 220 | 221 | $responseJson = $this->_RESTcli->get("bills/".$billId, $params); 222 | } catch (BitPayException $e) { 223 | throw new BillQueryException("failed to serialize Bill object : ".$e->getMessage(), null, null, $e->getApiCode()); 224 | } catch (Exception $e) { 225 | throw new BillQueryException("failed to serialize Bill object : ".$e->getMessage()); 226 | } 227 | 228 | try { 229 | $mapper = new JsonMapper(); 230 | $bill = $mapper->map( 231 | json_decode($responseJson), 232 | new Bill() 233 | ); 234 | 235 | } catch (Exception $e) { 236 | throw new BillQueryException( 237 | "failed to deserialize BitPay server response (Bill) : ".$e->getMessage()); 238 | } 239 | 240 | return $bill; 241 | } 242 | 243 | /** 244 | * Deliver a BitPay Bill. 245 | * 246 | * @param $billId string The id of the requested bill. 247 | * @param $billToken string The token of the requested bill. 248 | * 249 | * @return string A response status returned from the API. 250 | * @throws BillDeliveryException BillDeliveryException class 251 | * @throws BitPayException BitPayException class 252 | */ 253 | public function deliverBill(string $billId, string $billToken): string 254 | { 255 | try { 256 | $responseJson = $this->_RESTcli->post( 257 | "bills/".$billId."/deliveries", ['token' => $billToken]); 258 | } catch (BitPayException $e) { 259 | throw new BillDeliveryException("failed to serialize Bill object : ".$e->getMessage(), null, null, $e->getApiCode()); 260 | } catch (Exception $e) { 261 | throw new BillDeliveryException("failed to serialize Bill object : ".$e->getMessage()); 262 | } 263 | 264 | try { 265 | $result = str_replace("\"", "", $responseJson); 266 | } catch (Exception $e) { 267 | throw new BillDeliveryException("failed to deserialize BitPay server response (Bill) : ".$e->getMessage()); 268 | } 269 | 270 | return $result; 271 | } 272 | 273 | /** 274 | * Retrieve the exchange rate table maintained by BitPay. See https://bitpay.com/bitcoin-exchange-rates. 275 | * 276 | * @return Rates A Rates object populated with the BitPay exchange rate table. 277 | * @throws RateQueryException RateQueryException class 278 | * @throws BitPayException BitPayException class 279 | */ 280 | public function getRates(): Rates 281 | { 282 | try { 283 | $responseJson = $this->_RESTcli->get("rates", null); 284 | } catch (BitPayException $e) { 285 | throw new RateQueryException("failed to serialize Rates object : ".$e->getMessage(), null, null, $e->getApiCode()); 286 | } catch (Exception $e) { 287 | throw new RateQueryException("failed to serialize Rates object : ".$e->getMessage()); 288 | } 289 | 290 | try { 291 | $mapper = new JsonMapper(); 292 | $rates = $mapper->mapArray( 293 | json_decode($responseJson), 294 | [], 295 | 'BitPaySDKLight\Model\Rate\Rate' 296 | ); 297 | 298 | } catch (Exception $e) { 299 | throw new RateQueryException( 300 | "failed to deserialize BitPay server response (Rates) : ".$e->getMessage()); 301 | } 302 | 303 | return new Rates($rates, $this); 304 | } 305 | 306 | /** 307 | * Retrieve all the rates for a given cryptocurrency 308 | * 309 | * @param string $baseCurrency The cryptocurrency for which you want to fetch the rates. 310 | * Current supported values are BTC, BCH, ETH, XRP, DOGE and LTC 311 | * @return Rates A Rates object populated with the currency rates for the requested baseCurrency. 312 | * @throws BitPayException BitPayException class 313 | */ 314 | public function getCurrencyRates(string $baseCurrency): Rates 315 | { 316 | try { 317 | $responseJson = $this->_RESTcli->get("rates/".$baseCurrency, null, false); 318 | } catch (Exception $e) { 319 | throw new RateQueryException("failed to serialize Rates object : ".$e->getMessage()); 320 | } 321 | 322 | try { 323 | $mapper = new JsonMapper(); 324 | $rates = $mapper->mapArray( 325 | json_decode($responseJson), 326 | [], 327 | 'BitPaySDKLight\Model\Rate\Rate' 328 | ); 329 | 330 | } catch (Exception $e) { 331 | throw new RateQueryException( 332 | "failed to deserialize BitPay server response (Rates) : ".$e->getMessage()); 333 | } 334 | 335 | return new Rates($rates, $this); 336 | } 337 | 338 | /** 339 | * Retrieve the rate for a cryptocurrency / fiat pair 340 | * 341 | * @param string $baseCurrency The cryptocurrency for which you want to fetch the fiat-equivalent rate. 342 | * Current supported values are BTC, BCH, ETH, XRP, DOGE and LTC 343 | * @param string $currency The fiat currency for which you want to fetch the baseCurrency rate 344 | * @return Rate A Rate object populated with the currency rate for the requested baseCurrency. 345 | * @throws BitPayException BitPayException class 346 | */ 347 | public function getCurrencyPairRate(string $baseCurrency, string $currency): Rate 348 | { 349 | try { 350 | $responseJson = $this->_RESTcli->get("rates/".$baseCurrency."/".$currency, null, false); 351 | } catch (Exception $e) { 352 | throw new RateQueryException("failed to serialize Rate object : ".$e->getMessage()); 353 | } 354 | 355 | try { 356 | $mapper = new JsonMapper(); 357 | $rate = $mapper->map( 358 | json_decode($responseJson), 359 | new Rate() 360 | ); 361 | 362 | } catch (Exception $e) { 363 | throw new RateQueryException( 364 | "failed to deserialize BitPay server response (Rate) : ".$e->getMessage()); 365 | } 366 | 367 | return $rate; 368 | } 369 | 370 | /** 371 | * Fetch the supported currencies. 372 | * 373 | * @return array A list of BitPay Invoice objects. 374 | * @throws CurrencyQueryException CurrencyQueryException class 375 | * @throws BitPayException BitPayException class 376 | */ 377 | public function getCurrencies(): array 378 | { 379 | try { 380 | $responseJson = $this->_RESTcli->get("currencies", null); 381 | } catch (BitPayException $e) { 382 | throw new CurrencyQueryException("failed to serialize Currency object : ".$e->getMessage(), null, null, $e->getApiCode()); 383 | } catch (Exception $e) { 384 | throw new CurrencyQueryException("failed to serialize Currency object : ".$e->getMessage()); 385 | } 386 | 387 | try { 388 | $mapper = new JsonMapper(); 389 | $currencies = $mapper->mapArray( 390 | json_decode($responseJson), 391 | [], 392 | 'BitPaySDKLight\Model\Currency' 393 | ); 394 | 395 | } catch (Exception $e) { 396 | throw new CurrencyQueryException( 397 | "failed to deserialize BitPay server response (Currency) : ".$e->getMessage()); 398 | } 399 | 400 | return $currencies; 401 | } 402 | } -------------------------------------------------------------------------------- /src/BitPaySDKLight/Config.php: -------------------------------------------------------------------------------- 1 | _environment; 28 | } 29 | 30 | /** 31 | * @param $environment 32 | */ 33 | public function setEnvironment($environment) 34 | { 35 | $this->_environment = $environment; 36 | } 37 | 38 | /** 39 | * @return mixed 40 | */ 41 | public function getEnvConfig() 42 | { 43 | return $this->_envConfig; 44 | } 45 | 46 | /** 47 | * @param $envConfig 48 | */ 49 | public function setEnvConfig($envConfig) 50 | { 51 | $this->_envConfig = $envConfig; 52 | } 53 | } -------------------------------------------------------------------------------- /src/BitPaySDKLight/Env.php: -------------------------------------------------------------------------------- 1 | bitPayCode.": ".$this->bitPayMessage."-> ".$message; 23 | $this->apiCode = $apiCode; 24 | parent::__construct($message, $code, $previous); 25 | } 26 | 27 | /** 28 | * @return string Error code provided by the BitPay REST API 29 | */ 30 | public function getApiCode() 31 | { 32 | return $this->apiCode; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/BitPaySDKLight/Exceptions/BillDeliveryException.php: -------------------------------------------------------------------------------- 1 | bitPayCode.": ".$this->bitPayMessage."-> ".$message; 23 | $this->apiCode = $apiCode; 24 | parent::__construct($message, $code, $previous); 25 | } 26 | 27 | /** 28 | * @return string Error code provided by the BitPay REST API 29 | */ 30 | public function getApiCode() 31 | { 32 | return $this->apiCode; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/BitPaySDKLight/Exceptions/BillException.php: -------------------------------------------------------------------------------- 1 | bitPayCode.": ".$this->bitPayMessage."-> ".$message; 23 | } 24 | 25 | parent::__construct($message, $code, $previous); 26 | } 27 | 28 | /** 29 | * @return string Error code provided by the BitPay REST API 30 | */ 31 | public function getApiCode() 32 | { 33 | return $this->apiCode; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/BitPaySDKLight/Exceptions/BillQueryException.php: -------------------------------------------------------------------------------- 1 | bitPayCode.": ".$this->bitPayMessage."-> ".$message; 24 | $this->apiCode = $apiCode; 25 | parent::__construct($message, $code, $previous); 26 | } 27 | 28 | /** 29 | * @return string Error code provided by the BitPay REST API 30 | */ 31 | public function getApiCode() 32 | { 33 | return $this->apiCode; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/BitPaySDKLight/Exceptions/BitPayException.php: -------------------------------------------------------------------------------- 1 | bitPayCode.": ".$this->bitPayMessage."-> ".$message; 25 | } 26 | $this->apiCode = $apiCode; 27 | parent::__construct($message, $code, $previous); 28 | } 29 | 30 | /** 31 | * @return string Error code provided by the BitPay REST API 32 | */ 33 | public function getApiCode() 34 | { 35 | return $this->apiCode; 36 | } 37 | } -------------------------------------------------------------------------------- /src/BitPaySDKLight/Exceptions/CurrencyException.php: -------------------------------------------------------------------------------- 1 | bitPayCode.": ".$this->bitPayMessage."-> ".$message; 23 | } 24 | 25 | parent::__construct($message, $code, $previous); 26 | } 27 | 28 | /** 29 | * @return string Error code provided by the BitPay REST API 30 | */ 31 | public function getApiCode() 32 | { 33 | return $this->apiCode; 34 | } 35 | } -------------------------------------------------------------------------------- /src/BitPaySDKLight/Exceptions/CurrencyQueryException.php: -------------------------------------------------------------------------------- 1 | bitPayCode.": ".$this->bitPayMessage."-> ".$message; 24 | $this->apiCode = $apiCode; 25 | parent::__construct($message, $code, $previous); 26 | } 27 | 28 | /** 29 | * @return string Error code provided by the BitPay REST API 30 | */ 31 | public function getApiCode() 32 | { 33 | return $this->apiCode; 34 | } 35 | } -------------------------------------------------------------------------------- /src/BitPaySDKLight/Exceptions/InvoiceCreationException.php: -------------------------------------------------------------------------------- 1 | bitPayCode.": ".$this->bitPayMessage."-> ".$message; 22 | $this->apiCode = $apiCode; 23 | parent::__construct($message, $code, $previous); 24 | } 25 | 26 | /** 27 | * @return string Error code provided by the BitPay REST API 28 | */ 29 | public function getApiCode() 30 | { 31 | return $this->apiCode; 32 | } 33 | } -------------------------------------------------------------------------------- /src/BitPaySDKLight/Exceptions/InvoiceException.php: -------------------------------------------------------------------------------- 1 | bitPayCode.": ".$this->bitPayMessage."-> ".$message; 23 | } 24 | 25 | parent::__construct($message, $code, $previous); 26 | } 27 | 28 | /** 29 | * @return string Error code provided by the BitPay REST API 30 | */ 31 | public function getApiCode() 32 | { 33 | return $this->apiCode; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/BitPaySDKLight/Exceptions/InvoiceQueryException.php: -------------------------------------------------------------------------------- 1 | bitPayCode.": ".$this->bitPayMessage."-> ".$message; 22 | $this->apiCode = $apiCode; 23 | parent::__construct($message, $code, $previous); 24 | } 25 | 26 | /** 27 | * @return string Error code provided by the BitPay REST API 28 | */ 29 | public function getApiCode() 30 | { 31 | return $this->apiCode; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/BitPaySDKLight/Exceptions/RateException.php: -------------------------------------------------------------------------------- 1 | bitPayCode.": ".$this->bitPayMessage."-> ".$message; 23 | } 24 | 25 | parent::__construct($message, $code, $previous); 26 | } 27 | 28 | /** 29 | * @return string Error code provided by the BitPay REST API 30 | */ 31 | public function getApiCode() 32 | { 33 | return $this->apiCode; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/BitPaySDKLight/Exceptions/RateQueryException.php: -------------------------------------------------------------------------------- 1 | bitPayCode.": ".$this->bitPayMessage."-> ".$message; 23 | $this->apiCode = $apiCode; 24 | parent::__construct($message, $code, $previous); 25 | } 26 | 27 | /** 28 | * @return string Error code provided by the BitPay REST API 29 | */ 30 | public function getApiCode() 31 | { 32 | return $this->apiCode; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/BitPaySDKLight/Model/Bill/Bill.php: -------------------------------------------------------------------------------- 1 | _number = $number; 53 | $this->_currency = $currency; 54 | $this->_email = $email; 55 | $this->_items = $items; 56 | } 57 | 58 | // API fields 59 | // 60 | 61 | public function getToken() 62 | { 63 | return $this->_token; 64 | } 65 | 66 | public function setToken(string $token) 67 | { 68 | $this->_token = $token; 69 | } 70 | 71 | // Required fields 72 | // 73 | 74 | public function getCurrency() 75 | { 76 | return $this->_currency; 77 | } 78 | 79 | public function setCurrency(string $currency) 80 | { 81 | if (!Currency::isValid($currency)) { 82 | throw new BitPayException("currency code must be a type of Model.Currency"); 83 | } 84 | 85 | $this->_currency = $currency; 86 | } 87 | 88 | public function getEmail() 89 | { 90 | return $this->_email; 91 | } 92 | 93 | public function setEmail(string $email) 94 | { 95 | $this->_email = $email; 96 | } 97 | 98 | public function getItems() 99 | { 100 | return $this->_items; 101 | } 102 | 103 | public function getItemsAsArray() 104 | { 105 | $items = []; 106 | 107 | foreach ($this->_items as $item) { 108 | if ($item instanceof Item) { 109 | array_push($items, $item->toArray()); 110 | } else { 111 | array_push($items, $item); 112 | } 113 | } 114 | 115 | return $items; 116 | } 117 | 118 | public function setItems(array $items) 119 | { 120 | $itemsArray = []; 121 | 122 | foreach ($items as $item) { 123 | if ($item instanceof Item) { 124 | array_push($itemsArray, $item); 125 | } else { 126 | array_push($itemsArray, Item::createFromArray((array)$item)); 127 | } 128 | } 129 | $this->_items = $itemsArray; 130 | } 131 | 132 | // Optional fields 133 | // 134 | 135 | public function getNumber() 136 | { 137 | return $this->_number; 138 | } 139 | 140 | public function setNumber(string $number) 141 | { 142 | $this->_number = $number; 143 | } 144 | 145 | public function getName() 146 | { 147 | return $this->_name; 148 | } 149 | 150 | public function setName(string $name) 151 | { 152 | $this->_name = $name; 153 | } 154 | 155 | public function getAddress1() 156 | { 157 | return $this->_address1; 158 | } 159 | 160 | public function setAddress1(string $address1) 161 | { 162 | $this->_address1 = $address1; 163 | } 164 | 165 | public function getAddress2() 166 | { 167 | return $this->_address2; 168 | } 169 | 170 | public function setAddress2(string $address2) 171 | { 172 | $this->_address2 = $address2; 173 | } 174 | 175 | public function getCity() 176 | { 177 | return $this->_city; 178 | } 179 | 180 | public function setCity(string $city) 181 | { 182 | $this->_city = $city; 183 | } 184 | 185 | public function getState() 186 | { 187 | return $this->_state; 188 | } 189 | 190 | public function setState(string $state) 191 | { 192 | $this->_state = $state; 193 | } 194 | 195 | public function getZip() 196 | { 197 | return $this->_zip; 198 | } 199 | 200 | public function setZip(string $zip) 201 | { 202 | $this->_zip = $zip; 203 | } 204 | 205 | public function getCountry() 206 | { 207 | return $this->_country; 208 | } 209 | 210 | public function setCountry(string $country) 211 | { 212 | $this->_country = $country; 213 | } 214 | 215 | public function getCc() 216 | { 217 | return $this->_cc; 218 | } 219 | 220 | public function setCc(array $cc) 221 | { 222 | $this->_cc = $cc; 223 | } 224 | 225 | public function getPhone() 226 | { 227 | return $this->_phone; 228 | } 229 | 230 | public function setPhone(string $phone) 231 | { 232 | $this->_phone = $phone; 233 | } 234 | 235 | public function getDueDate() 236 | { 237 | return $this->_dueDate; 238 | } 239 | 240 | public function setDueDate(string $dueDate) 241 | { 242 | $this->_dueDate = $dueDate; 243 | } 244 | 245 | public function getPassProcessingFee() 246 | { 247 | return $this->_passProcessingFee; 248 | } 249 | 250 | public function setPassProcessingFee(bool $passProcessingFee) 251 | { 252 | $this->_passProcessingFee = $passProcessingFee; 253 | } 254 | 255 | // Response fields 256 | // 257 | 258 | public function getStatus() 259 | { 260 | return $this->_status; 261 | } 262 | 263 | public function setStatus(string $status) 264 | { 265 | $this->_status = $status; 266 | } 267 | 268 | public function getUrl() 269 | { 270 | return $this->_url; 271 | } 272 | 273 | public function setUrl(string $url) 274 | { 275 | $this->_url = $url; 276 | } 277 | 278 | public function getCreatedDate() 279 | { 280 | return $this->_createdDate; 281 | } 282 | 283 | public function setCreatedDate(string $createdDate) 284 | { 285 | $this->_createdDate = $createdDate; 286 | } 287 | 288 | public function getId() 289 | { 290 | return $this->_id; 291 | } 292 | 293 | public function setId(string $id) 294 | { 295 | $this->_id = $id; 296 | } 297 | 298 | public function getMerchant() 299 | { 300 | return $this->_merchant; 301 | } 302 | 303 | public function setMerchant(string $merchant) 304 | { 305 | $this->_merchant = $merchant; 306 | } 307 | 308 | public function toArray() 309 | { 310 | $elements = [ 311 | 'currency' => $this->getCurrency(), 312 | 'token' => $this->getToken(), 313 | 'email' => $this->getEmail(), 314 | 'items' => $this->getItemsAsArray(), 315 | 'number' => $this->getNumber(), 316 | 'name' => $this->getName(), 317 | 'address1' => $this->getAddress1(), 318 | 'address2' => $this->getAddress2(), 319 | 'city' => $this->getCity(), 320 | 'state' => $this->getState(), 321 | 'zip' => $this->getZip(), 322 | 'country' => $this->getCountry(), 323 | 'cc' => $this->getCc(), 324 | 'phone' => $this->getPhone(), 325 | 'dueDate' => $this->getDueDate(), 326 | 'passProcessingFee' => $this->getPassProcessingFee(), 327 | 'status' => $this->getStatus(), 328 | 'url' => $this->getUrl(), 329 | 'createdDate' => $this->getCreatedDate(), 330 | 'id' => $this->getId(), 331 | 'merchant' => $this->getMerchant(), 332 | ]; 333 | 334 | foreach ($elements as $key => $value) { 335 | if (empty($value)) { 336 | unset($elements[$key]); 337 | } 338 | } 339 | 340 | return $elements; 341 | } 342 | } 343 | -------------------------------------------------------------------------------- /src/BitPaySDKLight/Model/Bill/BillStatus.php: -------------------------------------------------------------------------------- 1 | _id; 24 | } 25 | 26 | public function setId(string $id) 27 | { 28 | $this->_id = $id; 29 | } 30 | 31 | public function getDescription() 32 | { 33 | return $this->_description; 34 | } 35 | 36 | public function setDescription(string $description) 37 | { 38 | $this->_description = $description; 39 | } 40 | 41 | public function getPrice() 42 | { 43 | return $this->_price; 44 | } 45 | 46 | public function setPrice(float $price) 47 | { 48 | $this->_price = $price; 49 | } 50 | 51 | public function getQuantity() 52 | { 53 | return $this->_quantity; 54 | } 55 | 56 | public function setQuantity(int $quantity) 57 | { 58 | $this->_quantity = $quantity; 59 | } 60 | 61 | public static function createFromArray(array $item) 62 | { 63 | $instance = new self(); 64 | 65 | foreach ($item as $key => $value) { 66 | $instance->{'_'.$key} = $value; 67 | } 68 | 69 | return $instance; 70 | } 71 | 72 | public function toArray() 73 | { 74 | $elements = [ 75 | 'id' => $this->getId(), 76 | 'description' => $this->getDescription(), 77 | 'price' => $this->getPrice(), 78 | 'quantity' => $this->getQuantity(), 79 | ]; 80 | 81 | foreach ($elements as $key => $value) { 82 | if (empty($value)) { 83 | unset($elements[$key]); 84 | } 85 | } 86 | 87 | return $elements; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/BitPaySDKLight/Model/Currency.php: -------------------------------------------------------------------------------- 1 | getConstants()); 217 | } catch (Exception $e) { 218 | return false; 219 | } 220 | } 221 | 222 | public function __construct() { } 223 | 224 | public function getCode() 225 | { 226 | return $this->_code; 227 | } 228 | 229 | public function setCode(string $code) 230 | { 231 | $this->_code = $code; 232 | } 233 | 234 | public function getSymbol() 235 | { 236 | return $this->_symbol; 237 | } 238 | 239 | public function setSymbol(string $symbol = null) 240 | { 241 | $this->_symbol = $symbol; 242 | } 243 | 244 | public function getPrecision() 245 | { 246 | return $this->_precision; 247 | } 248 | 249 | public function setPrecision(int $precision) 250 | { 251 | $this->_precision = $precision; 252 | } 253 | 254 | public function getCurrentlySettled() 255 | { 256 | return $this->_currentlySettled; 257 | } 258 | 259 | public function setCurrentlySettled(bool $currentlySettled) 260 | { 261 | $this->_currentlySettled = $currentlySettled; 262 | } 263 | 264 | public function getName() 265 | { 266 | return $this->_name; 267 | } 268 | 269 | public function setName(string $name) 270 | { 271 | $this->_name = $name; 272 | } 273 | 274 | public function getPlural() 275 | { 276 | return $this->_plural; 277 | } 278 | 279 | public function setPlural(string $plural) 280 | { 281 | $this->_plural = $plural; 282 | } 283 | 284 | public function getAlts() 285 | { 286 | return $this->_alts; 287 | } 288 | 289 | public function setAlts(string $alts) 290 | { 291 | $this->_alts = $alts; 292 | } 293 | 294 | public function getMinimum() 295 | { 296 | return $this->_minimum; 297 | } 298 | 299 | public function setMinimum(string $minimum) 300 | { 301 | $this->_minimum = $minimum; 302 | } 303 | 304 | public function getSanctioned() 305 | { 306 | return $this->_sanctioned; 307 | } 308 | 309 | public function setSanctioned(bool $sanctioned) 310 | { 311 | $this->_sanctioned = $sanctioned; 312 | } 313 | 314 | public function getDecimals() 315 | { 316 | return $this->_decimals; 317 | } 318 | 319 | public function setDecimals(string $decimals) 320 | { 321 | $this->_decimals = $decimals; 322 | } 323 | 324 | public function getPayoutFields() 325 | { 326 | return $this->_payoutFields; 327 | } 328 | 329 | public function setPayoutFields(array $payoutFields) 330 | { 331 | $this->_payoutFields = $payoutFields; 332 | } 333 | 334 | public function getSettlementMinimum() 335 | { 336 | return $this->_settlementMinimum; 337 | } 338 | 339 | public function setSettlementMinimum(array $settlementMinimum) 340 | { 341 | $this->_settlementMinimum = $settlementMinimum; 342 | } 343 | 344 | public function toArray() 345 | { 346 | $elements = [ 347 | 'code' => $this->getCode(), 348 | 'symbol' => $this->getSymbol(), 349 | 'precision' => $this->getPrecision(), 350 | 'currentlySettled' => $this->getCurrentlySettled(), 351 | 'name' => $this->getName(), 352 | 'plural' => $this->getPlural(), 353 | 'alts' => $this->getAlts(), 354 | 'minimum' => $this->getMinimum(), 355 | 'sanctioned' => $this->getSanctioned(), 356 | 'decimals' => $this->getDecimals(), 357 | 'payoutFields' => $this->getPayoutFields(), 358 | 'settlementMinimum' => $this->getSettlementMinimum(), 359 | ]; 360 | 361 | foreach ($elements as $key => $value) { 362 | if (empty($value)) { 363 | unset($elements[$key]); 364 | } 365 | } 366 | 367 | return $elements; 368 | } 369 | } 370 | -------------------------------------------------------------------------------- /src/BitPaySDKLight/Model/Facade.php: -------------------------------------------------------------------------------- 1 | _name; 29 | } 30 | 31 | public function setName(string $name) 32 | { 33 | $this->_name = $name; 34 | } 35 | 36 | public function getAddress1() 37 | { 38 | return $this->_address1; 39 | } 40 | 41 | public function setAddress1(string $address1) 42 | { 43 | $this->_address1 = $address1; 44 | } 45 | 46 | public function getAddress2() 47 | { 48 | return $this->_address2; 49 | } 50 | 51 | public function setAddress2(string $address2) 52 | { 53 | $this->_address2 = $address2; 54 | } 55 | 56 | public function getLocality() 57 | { 58 | return $this->_locality; 59 | } 60 | 61 | public function setLocality(string $locality) 62 | { 63 | $this->_locality = $locality; 64 | } 65 | 66 | public function getRegion() 67 | { 68 | return $this->_region; 69 | } 70 | 71 | public function setRegion(string $region) 72 | { 73 | $this->_region = $region; 74 | } 75 | 76 | public function getPostalCode() 77 | { 78 | return $this->_postalCode; 79 | } 80 | 81 | public function setPostalCode(string $postalCode) 82 | { 83 | $this->_postalCode = $postalCode; 84 | } 85 | 86 | public function getCountry() 87 | { 88 | return $this->_country; 89 | } 90 | 91 | public function setCountry(string $country) 92 | { 93 | $this->_country = $country; 94 | } 95 | 96 | public function getEmail() 97 | { 98 | return $this->_email; 99 | } 100 | 101 | public function setEmail(string $email) 102 | { 103 | $this->_email = $email; 104 | } 105 | 106 | public function getPhone() 107 | { 108 | return $this->_phone; 109 | } 110 | 111 | public function setPhone(string $phone) 112 | { 113 | $this->_phone = $phone; 114 | } 115 | 116 | public function getNotify() 117 | { 118 | return $this->_notify; 119 | } 120 | 121 | public function setNotify(bool $notify) 122 | { 123 | $this->_notify = $notify; 124 | } 125 | 126 | public function toArray() 127 | { 128 | $elements = [ 129 | 'name' => $this->getName(), 130 | 'address1' => $this->getAddress1(), 131 | 'address2' => $this->getAddress2(), 132 | 'locality' => $this->getLocality(), 133 | 'region' => $this->getRegion(), 134 | 'postalCode' => $this->getPostalCode(), 135 | 'country' => $this->getCountry(), 136 | 'email' => $this->getEmail(), 137 | 'phone' => $this->getPhone(), 138 | 'notify' => $this->getNotify(), 139 | ]; 140 | 141 | foreach ($elements as $key => $value) { 142 | if (empty($value)) { 143 | unset($elements[$key]); 144 | } 145 | } 146 | 147 | return $elements; 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /src/BitPaySDKLight/Model/Invoice/BuyerProvidedInfo.php: -------------------------------------------------------------------------------- 1 | _name; 22 | } 23 | 24 | public function setName($name) 25 | { 26 | $this->_name = $name; 27 | } 28 | 29 | public function getPhoneNumber() 30 | { 31 | return $this->_phoneNumber; 32 | } 33 | 34 | public function setPhoneNumber($phoneNumber) 35 | { 36 | $this->_phoneNumber = $phoneNumber; 37 | } 38 | 39 | public function getSelectedWallet() 40 | { 41 | return $this->_selectedWallet; 42 | } 43 | 44 | public function setSelectedWallet($selectedWallet) 45 | { 46 | $this->_selectedWallet = $selectedWallet; 47 | } 48 | 49 | public function getEmailAddress() 50 | { 51 | return $this->_emailAddress; 52 | } 53 | 54 | public function setEmailAddress($emailAddress) 55 | { 56 | $this->_emailAddress = $emailAddress; 57 | } 58 | 59 | public function getSelectedTransactionCurrency() 60 | { 61 | return $this->_selectedTransactionCurrency; 62 | } 63 | 64 | public function setSelectedTransactionCurrency($selectedTransactionCurrency) 65 | { 66 | $this->_selectedTransactionCurrency = $selectedTransactionCurrency; 67 | } 68 | 69 | public function toArray() 70 | { 71 | $elements = [ 72 | 'name' => $this->getName(), 73 | 'phoneNumber' => $this->getPhoneNumber(), 74 | 'emailAddress' => $this->getEmailAddress(), 75 | 'selectedTransactionCurrency' => $this->getSelectedTransactionCurrency(), 76 | ]; 77 | 78 | foreach ($elements as $key => $value) { 79 | if (empty($value)) { 80 | unset($elements[$key]); 81 | } 82 | } 83 | 84 | return $elements; 85 | } 86 | } -------------------------------------------------------------------------------- /src/BitPaySDKLight/Model/Invoice/Invoice.php: -------------------------------------------------------------------------------- 1 | _price = $price; 95 | $this->_currency = $currency; 96 | $this->_buyer = new Buyer(); 97 | $this->_buyerProvidedInfo = new BuyerProvidedInfo(); 98 | $this->_supportedTransactionCurrencies = new SupportedTransactionCurrencies(); 99 | $this->_minerFees = new MinerFees(); 100 | $this->_shopper = new Shopper(); 101 | $this->_refundInfo = new RefundInfo(); 102 | } 103 | 104 | // API fields 105 | // 106 | 107 | public function getCurrency() 108 | { 109 | return $this->_currency; 110 | } 111 | 112 | // Required fields 113 | // 114 | 115 | public function setCurrency(string $currency) 116 | { 117 | if (!Currency::isValid($currency)) { 118 | throw new BitPayException("currency code must be a type of Model.Currency"); 119 | } 120 | 121 | $this->_currency = $currency; 122 | } 123 | 124 | public function getGuid() 125 | { 126 | return $this->_guid; 127 | } 128 | 129 | public function setGuid(string $guid) 130 | { 131 | $this->_guid = $guid; 132 | } 133 | 134 | public function getToken() 135 | { 136 | return $this->_token; 137 | } 138 | 139 | // Optional fields 140 | // 141 | 142 | public function setToken(string $token) 143 | { 144 | $this->_token = $token; 145 | } 146 | 147 | public function getPrice() 148 | { 149 | return $this->_price; 150 | } 151 | 152 | public function setPrice(float $price) 153 | { 154 | $this->_price = $price; 155 | } 156 | 157 | public function getPosData() 158 | { 159 | return $this->_posData; 160 | } 161 | 162 | public function setPosData(string $posData) 163 | { 164 | $this->_posData = $posData; 165 | } 166 | 167 | public function getNotificationURL() 168 | { 169 | return $this->_notificationURL; 170 | } 171 | 172 | public function setNotificationURL(string $notificationURL) 173 | { 174 | $this->_notificationURL = $notificationURL; 175 | } 176 | 177 | public function getTransactionSpeed() 178 | { 179 | return $this->_transactionSpeed; 180 | } 181 | 182 | public function setTransactionSpeed(string $transactionSpeed) 183 | { 184 | $this->_transactionSpeed = $transactionSpeed; 185 | } 186 | 187 | public function getFullNotifications() 188 | { 189 | return $this->_fullNotifications; 190 | } 191 | 192 | public function setFullNotifications(bool $fullNotifications) 193 | { 194 | $this->_fullNotifications = $fullNotifications; 195 | } 196 | 197 | public function getNotificationEmail() 198 | { 199 | return $this->_notificationEmail; 200 | } 201 | 202 | public function setNotificationEmail(string $notificationEmail) 203 | { 204 | $this->_notificationEmail = $notificationEmail; 205 | } 206 | 207 | public function getRedirectURL() 208 | { 209 | return $this->_redirectURL; 210 | } 211 | 212 | public function setRedirectURL(string $redirectURL) 213 | { 214 | $this->_redirectURL = $redirectURL; 215 | } 216 | 217 | public function getCloseURL() 218 | { 219 | return $this->_closeURL; 220 | } 221 | 222 | public function setCloseURL(string $closeURL) 223 | { 224 | $this->_closeURL = $closeURL; 225 | } 226 | 227 | public function getAutoRedirect() 228 | { 229 | return $this->_autoRedirect; 230 | } 231 | 232 | public function setAutoRedirect(bool $autoRedirect) 233 | { 234 | $this->_autoRedirect = $autoRedirect; 235 | } 236 | 237 | public function getJsonPayProRequired() 238 | { 239 | return $this->_jsonPayProRequired; 240 | } 241 | 242 | public function setJsonPayProRequired(bool $jsonPayProRequired) 243 | { 244 | $this->_jsonPayProRequired = $jsonPayProRequired; 245 | } 246 | 247 | public function getBitpayIdRequired() 248 | { 249 | return $this->_bitpayIdRequired; 250 | } 251 | 252 | public function setBitpayIdRequired(bool $bitpayIdRequired) 253 | { 254 | $this->_bitpayIdRequired = $bitpayIdRequired; 255 | } 256 | 257 | public function getMerchantName() 258 | { 259 | return $this->_merchantName; 260 | } 261 | 262 | public function setMerchantName(string $merchantName) 263 | { 264 | $this->_merchantName = $merchantName; 265 | } 266 | 267 | public function getForcedBuyerSelectedWallet() 268 | { 269 | return $this->_forcedBuyerSelectedWallet; 270 | } 271 | 272 | public function setForcedBuyerSelectedWallet(string $forcedBuyerSelectedWallet) 273 | { 274 | $this->_forcedBuyerSelectedWallet = $forcedBuyerSelectedWallet; 275 | } 276 | 277 | public function getSelectedTransactionCurrency() 278 | { 279 | return $this->_selectedTransactionCurrency; 280 | } 281 | 282 | public function setSelectedTransactionCurrency(string $selectedTransactionCurrency) 283 | { 284 | $this->_selectedTransactionCurrency = $selectedTransactionCurrency; 285 | } 286 | 287 | public function getOrderId() 288 | { 289 | return $this->_orderId; 290 | } 291 | 292 | public function setOrderId(string $orderId) 293 | { 294 | $this->_orderId = $orderId; 295 | } 296 | 297 | public function getItemDesc() 298 | { 299 | return $this->_itemDesc; 300 | } 301 | 302 | public function setItemDesc(string $itemDesc) 303 | { 304 | $this->_itemDesc = $itemDesc; 305 | } 306 | 307 | public function getItemCode() 308 | { 309 | return $this->_itemCode; 310 | } 311 | 312 | public function setItemCode(string $itemCode) 313 | { 314 | $this->_itemCode = $itemCode; 315 | } 316 | 317 | public function getPhysical() 318 | { 319 | return $this->_physical; 320 | } 321 | 322 | public function setPhysical(bool $physical) 323 | { 324 | $this->_physical = $physical; 325 | } 326 | 327 | public function getPaymentCurrencies() 328 | { 329 | return $this->_paymentCurrencies; 330 | } 331 | 332 | public function setPaymentCurrencies(array $paymentCurrencies) 333 | { 334 | $this->_paymentCurrencies = $paymentCurrencies; 335 | } 336 | 337 | public function getAcceptanceWindow() 338 | { 339 | return $this->_acceptanceWindow; 340 | } 341 | 342 | // Buyer data 343 | // 344 | 345 | public function setAcceptanceWindow(float $acceptanceWindow) 346 | { 347 | $this->_acceptanceWindow = $acceptanceWindow; 348 | } 349 | 350 | public function getBuyer() 351 | { 352 | return $this->_buyer; 353 | } 354 | 355 | public function setBuyer(Buyer $buyer) 356 | { 357 | $this->_buyer = $buyer; 358 | } 359 | 360 | public function getBuyerSms() 361 | { 362 | return $this->_buyerSms; 363 | } 364 | 365 | public function setBuyerSms(string $buyerSms) 366 | { 367 | $this->_buyerSms = $buyerSms; 368 | } 369 | 370 | public function getBuyerEmail() 371 | { 372 | return $this->_buyerEmail; 373 | } 374 | 375 | public function setBuyerEmail(string $buyerEmail) 376 | { 377 | $this->_buyerEmail = $buyerEmail; 378 | } 379 | 380 | public function getSmsCode() 381 | { 382 | return $this->_smsCode; 383 | } 384 | 385 | public function setSmsCode(string $smsCode) 386 | { 387 | $this->_smsCode = $smsCode; 388 | } 389 | 390 | // Response fields 391 | // 392 | 393 | public function getRefundAddresses() 394 | { 395 | return $this->_refundAddresses; 396 | } 397 | 398 | public function setRefundAddresses(array $refundAddresses) 399 | { 400 | $this->_refundAddresses = $refundAddresses; 401 | } 402 | 403 | public function getId() 404 | { 405 | return $this->_id; 406 | } 407 | 408 | public function setId($id) 409 | { 410 | $this->_id = $id; 411 | } 412 | 413 | public function getUrl() 414 | { 415 | return $this->_url; 416 | } 417 | 418 | public function setUrl($url) 419 | { 420 | $this->_url = $url; 421 | } 422 | 423 | public function getPaymentSubTotals() 424 | { 425 | return $this->_paymentSubtotals; 426 | } 427 | 428 | public function setPaymentSubTotals($paymentSubtotals) 429 | { 430 | $this->_paymentSubtotals = $paymentSubtotals; 431 | } 432 | 433 | public function getPaymentTotals() 434 | { 435 | return $this->_paymentTotals; 436 | } 437 | 438 | public function setPaymentTotals($paymentTotals) 439 | { 440 | $this->_paymentTotals = $paymentTotals; 441 | } 442 | 443 | public function getPaymentDisplayTotals() 444 | { 445 | return $this->_paymentDisplayTotals; 446 | } 447 | 448 | public function setPaymentDisplayTotals($paymentDisplayTotals) 449 | { 450 | $this->_paymentDisplayTotals = $paymentDisplayTotals; 451 | } 452 | 453 | public function getPaymentDisplaySubTotals() 454 | { 455 | return $this->_paymentDisplaySubTotals; 456 | } 457 | 458 | public function setPaymentDisplaySubTotals($paymentDisplaySubTotals) 459 | { 460 | $this->_paymentDisplaySubTotals = $paymentDisplaySubTotals; 461 | } 462 | 463 | public function getPaymentCodes() 464 | { 465 | return $this->_paymentCodes; 466 | } 467 | 468 | public function setPaymentCodes($paymentCodes) 469 | { 470 | $this->_paymentCodes = $paymentCodes; 471 | } 472 | 473 | public function getPaymentString() 474 | { 475 | return $this->_paymentString; 476 | } 477 | 478 | public function setPaymentString(string $paymentString) 479 | { 480 | $this->_paymentString = $paymentString; 481 | } 482 | 483 | public function getVerificationLink() 484 | { 485 | return $this->_verificationLink; 486 | } 487 | 488 | public function setVerificationLink(string $verificationLink) 489 | { 490 | $this->_verificationLink = $verificationLink; 491 | } 492 | 493 | public function getAmount() 494 | { 495 | return $this->_amount; 496 | } 497 | 498 | public function setAmount($amount) 499 | { 500 | $this->_amount = $amount; 501 | } 502 | 503 | public function getDescription() 504 | { 505 | return $this->_description; 506 | } 507 | 508 | public function setDescription($description) 509 | { 510 | $this->_description = $description; 511 | } 512 | 513 | public function getIsFee() 514 | { 515 | return $this->_isFee; 516 | } 517 | 518 | public function setIsFee(bool $isFee) 519 | { 520 | $this->_isFee = $isFee; 521 | } 522 | 523 | public function getUnderpaidAmount() 524 | { 525 | return $this->_underpaidAmount; 526 | } 527 | 528 | public function setUnderpaidAmount($underpaidAmount) 529 | { 530 | $this->_underpaidAmount = $underpaidAmount; 531 | } 532 | 533 | public function getOverpaidAmount() 534 | { 535 | return $this->_overpaidAmount; 536 | } 537 | 538 | public function setOverpaidAmount($overpaidAmount) 539 | { 540 | $this->_overpaidAmount = $overpaidAmount; 541 | } 542 | 543 | public function getStatus() 544 | { 545 | return $this->_status; 546 | } 547 | 548 | public function setStatus($status) 549 | { 550 | $this->_status = $status; 551 | } 552 | 553 | public function getLowFeeDetected() 554 | { 555 | return $this->_lowFeeDetected; 556 | } 557 | 558 | public function setLowFeeDetected($lowFeeDetected) 559 | { 560 | $this->_lowFeeDetected = $lowFeeDetected; 561 | } 562 | 563 | public function getInvoiceTime() 564 | { 565 | return $this->_invoiceTime; 566 | } 567 | 568 | public function setInvoiceTime($invoiceTime) 569 | { 570 | $this->_invoiceTime = $invoiceTime; 571 | } 572 | 573 | public function getExpirationTime() 574 | { 575 | return $this->_expirationTime; 576 | } 577 | 578 | public function setExpirationTime($expirationTime) 579 | { 580 | $this->_expirationTime = $expirationTime; 581 | } 582 | 583 | public function getCurrentTime() 584 | { 585 | return $this->_currentTime; 586 | } 587 | 588 | public function setCurrentTime($currentTime) 589 | { 590 | $this->_currentTime = $currentTime; 591 | } 592 | 593 | public function getTransactions() 594 | { 595 | return $this->_transactions; 596 | } 597 | 598 | public function setTransactions($transactions) 599 | { 600 | $this->_transactions = $transactions; 601 | } 602 | 603 | public function getExceptionStatus() 604 | { 605 | return $this->_exceptionStatus; 606 | } 607 | 608 | public function setExceptionStatus($exceptionStatus) 609 | { 610 | $this->_exceptionStatus = $exceptionStatus; 611 | } 612 | 613 | public function getTargetConfirmations() 614 | { 615 | return $this->_targetConfirmations; 616 | } 617 | 618 | public function setTargetConfirmations($targetConfirmations) 619 | { 620 | $this->_targetConfirmations = $targetConfirmations; 621 | } 622 | 623 | public function getRefundAddressRequestPending() 624 | { 625 | return $this->_refundAddressRequestPending; 626 | } 627 | 628 | public function setRefundAddressRequestPending($refundAddressRequestPending) 629 | { 630 | $this->_refundAddressRequestPending = $refundAddressRequestPending; 631 | } 632 | 633 | public function getBuyerProvidedEmail() 634 | { 635 | return $this->_buyerProvidedEmail; 636 | } 637 | 638 | public function setBuyerProvidedEmail($buyerProvidedEmail) 639 | { 640 | $this->_buyerProvidedEmail = $buyerProvidedEmail; 641 | } 642 | 643 | public function getBuyerProvidedInfo() 644 | { 645 | return $this->_buyerProvidedInfo; 646 | } 647 | 648 | public function setBuyerProvidedInfo(BuyerProvidedInfo $buyerProvidedInfo) 649 | { 650 | $this->_buyerProvidedInfo = $buyerProvidedInfo; 651 | } 652 | 653 | public function getSupportedTransactionCurrencies() 654 | { 655 | return $this->_supportedTransactionCurrencies; 656 | } 657 | 658 | public function setSupportedTransactionCurrencies(SupportedTransactionCurrencies $supportedTransactionCurrencies) 659 | { 660 | $this->_supportedTransactionCurrencies = $supportedTransactionCurrencies; 661 | } 662 | 663 | public function getMinerFees() 664 | { 665 | return $this->_minerFees; 666 | } 667 | 668 | public function setMinerFees(MinerFees $minerFees) 669 | { 670 | $this->_minerFees = $minerFees; 671 | } 672 | 673 | public function getNonPayProPaymentReceived() 674 | { 675 | return $this->_nonPayProPaymentReceived; 676 | } 677 | 678 | public function setNonPayProPaymentReceived(bool $nonPayProPaymentReceived) 679 | { 680 | $this->_nonPayProPaymentReceived = $nonPayProPaymentReceived; 681 | } 682 | 683 | public function getShopper() 684 | { 685 | return $this->_shopper; 686 | } 687 | 688 | public function setShopper(Shopper $shopper) 689 | { 690 | $this->_shopper = $shopper; 691 | } 692 | 693 | public function getBillId() 694 | { 695 | return $this->_billId; 696 | } 697 | 698 | public function setBillId($billId) 699 | { 700 | $this->_billId = $billId; 701 | } 702 | 703 | public function getRefundInfo() 704 | { 705 | return $this->_refundInfo; 706 | } 707 | 708 | public function setRefundInfo(RefundInfo $refundInfo) 709 | { 710 | $this->_refundInfo = $refundInfo; 711 | } 712 | 713 | public function getExtendedNotifications() 714 | { 715 | return $this->_extendedNotifications; 716 | } 717 | 718 | public function setExtendedNotifications(bool $extendedNotifications) 719 | { 720 | $this->_extendedNotifications = $extendedNotifications; 721 | } 722 | 723 | public function getTransactionCurrency() 724 | { 725 | return $this->_transactionCurrency; 726 | } 727 | 728 | public function setTransactionCurrency($transactionCurrency) 729 | { 730 | $this->_transactionCurrency = $transactionCurrency; 731 | } 732 | 733 | public function getAmountPaid() 734 | { 735 | return $this->_amountPaid; 736 | } 737 | 738 | public function setAmountPaid($amountPaid) 739 | { 740 | $this->_amountPaid = $amountPaid; 741 | } 742 | 743 | public function getDisplayAmountPaid() 744 | { 745 | return $this->_displayAmountPaid; 746 | } 747 | 748 | public function setDisplayAmountPaid(string $displayAmountPaid) 749 | { 750 | $this->_displayAmountPaid = $displayAmountPaid; 751 | } 752 | 753 | public function getExchangeRates() 754 | { 755 | return $this->_exchangeRates; 756 | } 757 | 758 | public function setExchangeRates($exchangeRates) 759 | { 760 | $this->_exchangeRates = $exchangeRates; 761 | } 762 | 763 | public function getIsCancelled() 764 | { 765 | return $this->_isCancelled; 766 | } 767 | 768 | public function setIsCancelled(bool $isCancelled) 769 | { 770 | $this->_isCancelled = $isCancelled; 771 | } 772 | 773 | public function getFiatAmount() 774 | { 775 | return $this->_fiatAmount; 776 | } 777 | 778 | public function setFiatAmount($fiatAmount) 779 | { 780 | $this->_fiatAmount = $fiatAmount; 781 | } 782 | 783 | public function toArray() 784 | { 785 | $elements = [ 786 | 'currency' => $this->getCurrency(), 787 | 'guid' => $this->getGuid(), 788 | 'token' => $this->getToken(), 789 | 'price' => $this->getPrice(), 790 | 'posData' => $this->getPosData(), 791 | 'notificationURL' => $this->getNotificationURL(), 792 | 'closeURL' => $this->getCloseURL(), 793 | 'transactionSpeed' => $this->getTransactionSpeed(), 794 | 'fullNotifications' => $this->getFullNotifications(), 795 | 'notificationEmail' => $this->getNotificationEmail(), 796 | 'redirectURL' => $this->getRedirectURL(), 797 | 'orderId' => $this->getOrderId(), 798 | 'itemDesc' => $this->getItemDesc(), 799 | 'itemCode' => $this->getItemCode(), 800 | 'physical' => $this->getPhysical(), 801 | 'paymentCurrencies' => $this->getPaymentCurrencies(), 802 | 'acceptanceWindow' => $this->getAcceptanceWindow(), 803 | 'buyer' => $this->getBuyer()->toArray(), 804 | 'refundAddresses' => $this->getRefundAddresses(), 805 | 'autoRedirect' => $this->getAutoRedirect(), 806 | 'id' => $this->getId(), 807 | 'url' => $this->getUrl(), 808 | 'status' => $this->getStatus(), 809 | 'lowFeeDetected' => $this->getLowFeeDetected(), 810 | 'invoiceTime' => $this->getInvoiceTime(), 811 | 'expirationTime' => $this->getExpirationTime(), 812 | 'currentTime' => $this->getCurrentTime(), 813 | 'transactions' => $this->getTransactions(), 814 | 'exceptionStatus' => $this->getExceptionStatus(), 815 | 'targetConfirmations' => $this->getTargetConfirmations(), 816 | 'refundAddressRequestPending' => $this->getRefundAddressRequestPending(), 817 | 'buyerProvidedEmail' => $this->getBuyerProvidedEmail(), 818 | 'buyerProvidedInfo' => $this->getBuyerProvidedInfo()->toArray(), 819 | 'supportedTransactionCurrencies' => $this->getSupportedTransactionCurrencies()->toArray(), 820 | 'minerFees' => $this->getMinerFees()->toArray(), 821 | 'shopper' => $this->getShopper()->toArray(), 822 | 'billId' => $this->getBillId(), 823 | 'refundInfo' => $this->getRefundInfo()->toArray(), 824 | 'extendedNotifications' => $this->getExtendedNotifications(), 825 | 'nonPayProPaymentReceived' => $this->getNonPayProPaymentReceived(), 826 | 'transactionCurrency' => $this->getTransactionCurrency(), 827 | 'amountPaid' => $this->getAmountPaid(), 828 | 'exchangeRates' => $this->getExchangeRates(), 829 | 'merchantName' => $this->getMerchantName(), 830 | 'bitpayIdRequired' => $this->getBitpayIdRequired(), 831 | 'forcedBuyerSelectedWallet' => $this->getForcedBuyerSelectedWallet(), 832 | 'buyerSms' => $this->getBuyerSms(), 833 | 'paymentString' => $this->getPaymentString(), 834 | 'verificationLink' => $this->getVerificationLink(), 835 | 'amount' => $this->getAmount(), 836 | 'description' => $this->getDescription(), 837 | 'isFee' => $this->getIsFee(), 838 | 'isCancelled' => $this->getIsCancelled(), 839 | 'fiatAmount' => $this->getFiatAmount(), 840 | 'buyerEmail' => $this->getBuyerEmail(), 841 | 'smsCode' => $this->getSmsCode(), 842 | 'paymentTotals' => $this->getPaymentTotals(), 843 | 'paymentSubtotals' => $this->getPaymentSubTotals(), 844 | 'paymentDisplayTotals' => $this->getPaymentDisplayTotals(), 845 | 'paymentDisplaySubTotals' => $this->getPaymentDisplaySubTotals(), 846 | 'displayAmountPaid' => $this->getDisplayAmountPaid(), 847 | 'paymentCodes' => $this->getPaymentCodes(), 848 | 'paymentString' => $this->getPaymentString(), 849 | 'verificationLink' => $this->getVerificationLink(), 850 | 'bitpayIdRequired' => $this->getBitpayIdRequired() 851 | ]; 852 | 853 | foreach ($elements as $key => $value) { 854 | if (empty($value)) { 855 | unset($elements[$key]); 856 | } 857 | } 858 | 859 | return $elements; 860 | } 861 | } 862 | -------------------------------------------------------------------------------- /src/BitPaySDKLight/Model/Invoice/InvoiceStatus.php: -------------------------------------------------------------------------------- 1 | _btc = new MinerFeesItem(); 19 | $this->_bch = new MinerFeesItem(); 20 | $this->_eth = new MinerFeesItem(); 21 | $this->_usdc = new MinerFeesItem(); 22 | $this->_gusd = new MinerFeesItem(); 23 | $this->_pax = new MinerFeesItem(); 24 | } 25 | 26 | public function getBTH() 27 | { 28 | return $this->_btc; 29 | } 30 | 31 | public function setBTH(MinerFeesItem $btc) 32 | { 33 | $this->_btc = $btc; 34 | } 35 | 36 | public function getBCH() 37 | { 38 | return $this->_bch; 39 | } 40 | 41 | public function setBCH(MinerFeesItem $bch) 42 | { 43 | $this->_bch = $bch; 44 | } 45 | 46 | public function getETH() 47 | { 48 | return $this->_bch; 49 | } 50 | 51 | public function setETH(MinerFeesItem $eth) 52 | { 53 | $this->_eth = $eth; 54 | } 55 | 56 | public function getUSDC() 57 | { 58 | return $this->_usdc; 59 | } 60 | 61 | public function setUSDC(MinerFeesItem $usdc) 62 | { 63 | $this->_usdc = $usdc; 64 | } 65 | 66 | public function getGUSD() 67 | { 68 | return $this->_gusd; 69 | } 70 | 71 | public function setGUSD(MinerFeesItem $gusd) 72 | { 73 | $this->_gusd = $gusd; 74 | } 75 | 76 | public function getPAX() 77 | { 78 | return $this->_pax; 79 | } 80 | 81 | public function setPAX(MinerFeesItem $pax) 82 | { 83 | $this->_pax = $pax; 84 | } 85 | 86 | public function toArray() 87 | { 88 | $elements = [ 89 | 'btc' => $this->getBTH()->toArray(), 90 | 'bch' => $this->getBCH()->toArray(), 91 | 'eth' => $this->getETH()->toArray(), 92 | 'usdc' => $this->getUSDC()->toArray(), 93 | 'gusd' => $this->getGUSD()->toArray(), 94 | 'pax' => $this->getPAX()->toArray(), 95 | ]; 96 | 97 | foreach ($elements as $key => $value) { 98 | if (empty($value)) { 99 | unset($elements[$key]); 100 | } 101 | } 102 | 103 | return $elements; 104 | } 105 | } -------------------------------------------------------------------------------- /src/BitPaySDKLight/Model/Invoice/MinerFeesItem.php: -------------------------------------------------------------------------------- 1 | _satoshisPerByte; 19 | } 20 | 21 | public function setSatoshisPerByte(float $satoshisPerByte) 22 | { 23 | $this->_satoshisPerByte = $satoshisPerByte; 24 | } 25 | 26 | public function getTotalFee() 27 | { 28 | return $this->_totalFee; 29 | } 30 | 31 | public function setTotalFee(float $totalFee) 32 | { 33 | $this->_totalFee = $totalFee; 34 | } 35 | 36 | public function toArray() 37 | { 38 | $elements = [ 39 | 'satoshisPerByte' => $this->getSatoshisPerByte(), 40 | 'totalFee' => $this->getTotalFee(), 41 | ]; 42 | 43 | foreach ($elements as $key => $value) { 44 | if (empty($value)) { 45 | unset($elements[$key]); 46 | } 47 | } 48 | 49 | return $elements; 50 | } 51 | } -------------------------------------------------------------------------------- /src/BitPaySDKLight/Model/Invoice/RefundInfo.php: -------------------------------------------------------------------------------- 1 | _supportRequest; 20 | } 21 | 22 | public function setSupportRequest(string $supportRequest) 23 | { 24 | $this->_supportRequest = $supportRequest; 25 | } 26 | 27 | public function getCurrency() 28 | { 29 | return $this->_currency; 30 | } 31 | 32 | public function setCurrency(string $currency) 33 | { 34 | $this->_currency = $currency; 35 | } 36 | 37 | public function getAmounts() 38 | { 39 | return $this->_amounts; 40 | } 41 | 42 | public function setAmounts(array $amounts) 43 | { 44 | $this->_amounts = $amounts; 45 | } 46 | 47 | public function toArray() 48 | { 49 | $elements = [ 50 | 'supportRequest' => $this->getSupportRequest(), 51 | 'currency' => $this->getCurrency(), 52 | 'amounts' => $this->getAmounts(), 53 | ]; 54 | 55 | foreach ($elements as $key => $value) { 56 | if (empty($value)) { 57 | unset($elements[$key]); 58 | } 59 | } 60 | 61 | return $elements; 62 | } 63 | } -------------------------------------------------------------------------------- /src/BitPaySDKLight/Model/Invoice/Shopper.php: -------------------------------------------------------------------------------- 1 | _user; 18 | } 19 | 20 | public function setUser(string $user) 21 | { 22 | $this->_user = $user; 23 | } 24 | 25 | public function toArray() 26 | { 27 | $elements = [ 28 | 'user' => $this->getUser(), 29 | ]; 30 | 31 | foreach ($elements as $key => $value) { 32 | if (empty($value)) { 33 | unset($elements[$key]); 34 | } 35 | } 36 | 37 | return $elements; 38 | } 39 | } -------------------------------------------------------------------------------- /src/BitPaySDKLight/Model/Invoice/SupportedTransactionCurrencies.php: -------------------------------------------------------------------------------- 1 | _btc = new SupportedTransactionCurrency(); 19 | $this->_bch = new SupportedTransactionCurrency(); 20 | $this->_eth = new SupportedTransactionCurrency(); 21 | $this->_usdc = new SupportedTransactionCurrency(); 22 | $this->_gusd = new SupportedTransactionCurrency(); 23 | $this->_pax = new SupportedTransactionCurrency(); 24 | } 25 | 26 | public function getBTC() 27 | { 28 | return $this->_btc; 29 | } 30 | 31 | public function setBTC(SupportedTransactionCurrency $btc) 32 | { 33 | $this->_btc = $btc; 34 | } 35 | 36 | public function getBCH() 37 | { 38 | return $this->_bch; 39 | } 40 | 41 | public function setBCH(SupportedTransactionCurrency $bch) 42 | { 43 | $this->_bch = $bch; 44 | } 45 | 46 | public function getETH() 47 | { 48 | return $this->_eth; 49 | } 50 | 51 | public function setETH(SupportedTransactionCurrency $eth) 52 | { 53 | $this->_eth = $eth; 54 | } 55 | 56 | public function getUSDC() 57 | { 58 | return $this->_usdc; 59 | } 60 | 61 | public function setUSDC(SupportedTransactionCurrency $usdc) 62 | { 63 | $this->_usdc = $usdc; 64 | } 65 | 66 | public function getGUSD() 67 | { 68 | return $this->_gusd; 69 | } 70 | 71 | public function setGUSD(SupportedTransactionCurrency $gusd) 72 | { 73 | $this->_gusd = $gusd; 74 | } 75 | 76 | public function getPAX() 77 | { 78 | return $this->_pax; 79 | } 80 | 81 | public function setPAX(SupportedTransactionCurrency $pax) 82 | { 83 | $this->_pax = $pax; 84 | } 85 | 86 | public function toArray() 87 | { 88 | $elements = [ 89 | 'btc' => $this->getBTC()->toArray(), 90 | 'bch' => $this->getBCH()->toArray(), 91 | 'eth' => $this->getETH()->toArray(), 92 | 'usdc' => $this->getUSDC()->toArray(), 93 | 'gusd' => $this->getGUSD()->toArray(), 94 | 'pax' => $this->getPAX()->toArray(), 95 | ]; 96 | 97 | foreach ($elements as $key => $value) { 98 | if (empty($value)) { 99 | unset($elements[$key]); 100 | } 101 | } 102 | 103 | return $elements; 104 | } 105 | } -------------------------------------------------------------------------------- /src/BitPaySDKLight/Model/Invoice/SupportedTransactionCurrency.php: -------------------------------------------------------------------------------- 1 | _enabled = $enabled; 18 | } 19 | 20 | public function getEnabled() 21 | { 22 | return $this->_enabled; 23 | } 24 | 25 | public function toArray() 26 | { 27 | $elements = [ 28 | 'enabled' => $this->getEnabled(), 29 | ]; 30 | 31 | foreach ($elements as $key => $value) { 32 | if (empty($value)) { 33 | unset($elements[$key]); 34 | } 35 | } 36 | 37 | return $elements; 38 | } 39 | } -------------------------------------------------------------------------------- /src/BitPaySDKLight/Model/Rate/Rate.php: -------------------------------------------------------------------------------- 1 | _name; 20 | } 21 | 22 | public function setName(string $name) 23 | { 24 | $this->_name = $name; 25 | } 26 | 27 | public function getCode() 28 | { 29 | return $this->_code; 30 | } 31 | 32 | public function setCode(string $code) 33 | { 34 | $this->_code = $code; 35 | } 36 | 37 | public function getRate() 38 | { 39 | return $this->_rate; 40 | } 41 | 42 | public function setRate(float $rate) 43 | { 44 | $this->_rate = $rate; 45 | } 46 | 47 | public function toArray() 48 | { 49 | $elements = [ 50 | 'name' => $this->getName(), 51 | 'code' => $this->getCode(), 52 | 'rate' => $this->getRate(), 53 | ]; 54 | 55 | foreach ($elements as $key => $value) { 56 | if (empty($value)) { 57 | unset($elements[$key]); 58 | } 59 | } 60 | 61 | return $elements; 62 | } 63 | } -------------------------------------------------------------------------------- /src/BitPaySDKLight/Model/Rate/Rates.php: -------------------------------------------------------------------------------- 1 | _bp = $bp; 19 | $this->_rates = $rates; 20 | } 21 | 22 | public function getRates() 23 | { 24 | $rates = []; 25 | 26 | foreach ($this->_rates as $rate) { 27 | if ($rate instanceof Rate) { 28 | array_push($rates, $rate->toArray()); 29 | } else { 30 | array_push($rates, $rate); 31 | } 32 | } 33 | 34 | return $rates; 35 | } 36 | 37 | public function update() 38 | { 39 | $this->_rates = $this->_bp->getRates()->getRates(); 40 | } 41 | 42 | public function getRate(String $currencyCode) 43 | { 44 | $val = null; 45 | 46 | if (!Currency::isValid($currencyCode)) { 47 | throw new BitPayException("currency code must be a type of Model.Currency"); 48 | } 49 | 50 | foreach ($this->_rates as $rateObj) { 51 | if ($rateObj->getCode() == $currencyCode) { 52 | $val = $rateObj->getRate(); 53 | break; 54 | } 55 | } 56 | 57 | return $val; 58 | } 59 | 60 | public function toArray() 61 | { 62 | $elements = [ 63 | 'rates' => $this->getRates(), 64 | ]; 65 | 66 | foreach ($elements as $key => $value) { 67 | if (empty($value)) { 68 | unset($elements[$key]); 69 | } 70 | } 71 | 72 | return $elements; 73 | } 74 | } -------------------------------------------------------------------------------- /src/BitPaySDKLight/Tokens.php: -------------------------------------------------------------------------------- 1 | merchant = $merchant; 33 | $this->payroll = $payroll; 34 | } 35 | 36 | public static function loadFromArray(array $tokens) 37 | { 38 | $instance = new self(); 39 | 40 | foreach ($tokens as $facade => $token) { 41 | $instance->{$facade} = $token; 42 | } 43 | 44 | return $instance; 45 | } 46 | 47 | /** 48 | * @param $facade 49 | * @return string 50 | * @throws Exception 51 | */ 52 | public function getTokenByFacade($facade) 53 | { 54 | $token = null; 55 | switch ($facade) { 56 | case Facade::Merchant: 57 | $token = $this->merchant; 58 | break; 59 | case Facade::Payroll: 60 | $token = $this->payroll; 61 | break; 62 | } 63 | 64 | if ($token) { 65 | return $token; 66 | } 67 | 68 | throw new Exception("given facade does not exist or no token defined for the given facade"); 69 | } 70 | 71 | /** 72 | * @param $merchant 73 | */ 74 | public function setMerchantToken($merchant) 75 | { 76 | $this->merchant = $merchant; 77 | } 78 | 79 | /** 80 | * @return mixed 81 | */ 82 | public function getPayrollToken() 83 | { 84 | return $this->payroll; 85 | } 86 | 87 | /** 88 | * @param $payroll 89 | */ 90 | public function setPayrollToken($payroll) 91 | { 92 | $this->payroll = $payroll; 93 | } 94 | } -------------------------------------------------------------------------------- /src/BitPaySDKLight/Util/JsonMapper/JsonMapper.php: -------------------------------------------------------------------------------- 1 | 10 | * @license OSL-3.0 http://opensource.org/licenses/osl-3.0 11 | * @link http://cweiske.de/ 12 | */ 13 | namespace BitPaySDKLight\Util\JsonMapper; 14 | use ReflectionClass; 15 | use ReflectionNamedType; 16 | /** 17 | * Automatically map JSON structures into objects. 18 | * 19 | * @category Netresearch 20 | * @package JsonMapper 21 | * @author Christian Weiske 22 | * @license OSL-3.0 http://opensource.org/licenses/osl-3.0 23 | * @link http://cweiske.de/ 24 | */ 25 | class JsonMapper 26 | { 27 | /** 28 | * PSR-3 compatible logger object 29 | * 30 | * @link http://www.php-fig.org/psr/psr-3/ 31 | * @var object 32 | * @see setLogger() 33 | */ 34 | protected $logger; 35 | 36 | /** 37 | * Throw an exception when JSON data contain a property 38 | * that is not defined in the PHP class 39 | * 40 | * @var boolean 41 | */ 42 | public $bExceptionOnUndefinedProperty = false; 43 | 44 | /** 45 | * Throw an exception if the JSON data miss a property 46 | * that is marked with @required in the PHP class 47 | * 48 | * @var boolean 49 | */ 50 | public $bExceptionOnMissingData = false; 51 | 52 | /** 53 | * If the types of map() parameters shall be checked. 54 | * 55 | * You have to disable it if you're using the json_decode "assoc" parameter. 56 | * 57 | * json_decode($str, false) 58 | * 59 | * @var boolean 60 | */ 61 | public $bEnforceMapType = false; 62 | 63 | /** 64 | * Throw an exception when an object is expected but the JSON contains 65 | * a non-object type. 66 | * 67 | * @var boolean 68 | */ 69 | public $bStrictObjectTypeChecking = false; 70 | 71 | /** 72 | * Throw an exception, if null value is found 73 | * but the type of attribute does not allow nulls. 74 | * 75 | * @var bool 76 | */ 77 | public $bStrictNullTypes = true; 78 | 79 | /** 80 | * Allow mapping of private and proteted properties. 81 | * 82 | * @var boolean 83 | */ 84 | public $bIgnoreVisibility = false; 85 | 86 | /** 87 | * Remove attributes that were not passed in JSON, 88 | * to avoid confusion between them and NULL values. 89 | * 90 | * @var boolean 91 | */ 92 | public $bRemoveUndefinedAttributes = false; 93 | 94 | /** 95 | * Override class names that JsonMapper uses to create objects. 96 | * Useful when your setter methods accept abstract classes or interfaces. 97 | * 98 | * @var array 99 | */ 100 | public $classMap = array(); 101 | 102 | /** 103 | * Callback used when an undefined property is found. 104 | * 105 | * Works only when $bExceptionOnUndefinedProperty is disabled. 106 | * 107 | * Parameters to this function are: 108 | * 1. Object that is being filled 109 | * 2. Name of the unknown JSON property 110 | * 3. JSON value of the property 111 | * 112 | * @var callable 113 | */ 114 | public $undefinedPropertyHandler = null; 115 | 116 | /** 117 | * Runtime cache for inspected classes. This is particularly effective if 118 | * mapArray() is called with a large number of objects 119 | * 120 | * @var array property inspection result cache 121 | */ 122 | protected $arInspectedClasses = array(); 123 | 124 | /** 125 | * Method to call on each object after deserialization is done. 126 | * 127 | * Is only called if it exists on the object. 128 | * 129 | * @var string|null 130 | */ 131 | public $postMappingMethod = null; 132 | 133 | /** 134 | * Map data all data in $json into the given $object instance. 135 | * 136 | * @param object|array $json JSON object structure from json_decode() 137 | * @param object $object Object to map $json data into 138 | * 139 | * @return mixed Mapped object is returned. 140 | * @see mapArray() 141 | */ 142 | public function map($json, $object) 143 | { 144 | if ($this->bEnforceMapType && !is_object($json)) { 145 | throw new InvalidArgumentException( 146 | 'JsonMapper::map() requires first argument to be an object' 147 | . ', ' . gettype($json) . ' given.' 148 | ); 149 | } 150 | if (!is_object($object)) { 151 | throw new InvalidArgumentException( 152 | 'JsonMapper::map() requires second argument to be an object' 153 | . ', ' . gettype($object) . ' given.' 154 | ); 155 | } 156 | 157 | $strClassName = get_class($object); 158 | $rc = new ReflectionClass($object); 159 | $strNs = $rc->getNamespaceName(); 160 | $providedProperties = array(); 161 | foreach ($json as $key => $jvalue) { 162 | $key = $this->getSafeName($key); 163 | $providedProperties[$key] = true; 164 | 165 | // Store the property inspection results so we don't have to do it 166 | // again for subsequent objects of the same type 167 | if (!isset($this->arInspectedClasses[$strClassName][$key])) { 168 | $this->arInspectedClasses[$strClassName][$key] 169 | = $this->inspectProperty($rc, $key); 170 | } 171 | 172 | list($hasProperty, $accessor, $type, $isNullable) 173 | = $this->arInspectedClasses[$strClassName][$key]; 174 | 175 | if (!$hasProperty) { 176 | if ($this->bExceptionOnUndefinedProperty) { 177 | throw new JsonMapper_Exception( 178 | 'JSON property "' . $key . '" does not exist' 179 | . ' in object of type ' . $strClassName 180 | ); 181 | } else if ($this->undefinedPropertyHandler !== null) { 182 | call_user_func( 183 | $this->undefinedPropertyHandler, 184 | $object, $key, $jvalue 185 | ); 186 | } else { 187 | $this->log( 188 | 'info', 189 | 'Property {property} does not exist in {class}', 190 | array('property' => $key, 'class' => $strClassName) 191 | ); 192 | } 193 | continue; 194 | } 195 | 196 | if ($accessor === null) { 197 | if ($this->bExceptionOnUndefinedProperty) { 198 | throw new JsonMapper_Exception( 199 | 'JSON property "' . $key . '" has no public setter method' 200 | . ' in object of type ' . $strClassName 201 | ); 202 | } 203 | $this->log( 204 | 'info', 205 | 'Property {property} has no public setter method in {class}', 206 | array('property' => $key, 'class' => $strClassName) 207 | ); 208 | continue; 209 | } 210 | 211 | if ($isNullable || !$this->bStrictNullTypes) { 212 | if ($jvalue === null) { 213 | $this->setProperty($object, $accessor, null); 214 | continue; 215 | } 216 | $type = $this->removeNullable($type); 217 | } else if ($jvalue === null) { 218 | throw new JsonMapper_Exception( 219 | 'JSON property "' . $key . '" in class "' 220 | . $strClassName . '" must not be NULL' 221 | ); 222 | } 223 | 224 | $type = $this->getFullNamespace($type, $strNs); 225 | $type = $this->getMappedType($type, $jvalue); 226 | 227 | if ($type === null || $type === 'mixed') { 228 | //no given type - simply set the json data 229 | $this->setProperty($object, $accessor, $jvalue); 230 | continue; 231 | } else if ($this->isObjectOfSameType($type, $jvalue)) { 232 | $this->setProperty($object, $accessor, $jvalue); 233 | continue; 234 | } else if ($this->isSimpleType($type)) { 235 | if ($type === 'string' && is_object($jvalue)) { 236 | throw new JsonMapper_Exception( 237 | 'JSON property "' . $key . '" in class "' 238 | . $strClassName . '" is an object and' 239 | . ' cannot be converted to a string' 240 | ); 241 | } 242 | settype($jvalue, $type); 243 | $this->setProperty($object, $accessor, $jvalue); 244 | continue; 245 | } 246 | 247 | //FIXME: check if type exists, give detailed error message if not 248 | if ($type === '') { 249 | throw new JsonMapper_Exception( 250 | 'Empty type at property "' 251 | . $strClassName . '::$' . $key . '"' 252 | ); 253 | } 254 | 255 | $array = null; 256 | $subtype = null; 257 | if ($this->isArrayOfType($type)) { 258 | //array 259 | $array = array(); 260 | $subtype = substr($type, 0, -2); 261 | } else if (substr($type, -1) == ']') { 262 | list($proptype, $subtype) = explode('[', substr($type, 0, -1)); 263 | if ($proptype == 'array') { 264 | $array = array(); 265 | } else { 266 | $array = $this->createInstance($proptype, false, $jvalue); 267 | } 268 | } else { 269 | if (is_a($type, 'ArrayObject', true)) { 270 | $array = $this->createInstance($type, false, $jvalue); 271 | } 272 | } 273 | 274 | if ($array !== null) { 275 | if (!is_array($jvalue) && $this->isFlatType(gettype($jvalue))) { 276 | throw new JsonMapper_Exception( 277 | 'JSON property "' . $key . '" must be an array, ' 278 | . gettype($jvalue) . ' given' 279 | ); 280 | } 281 | 282 | $cleanSubtype = $this->removeNullable($subtype); 283 | $subtype = $this->getFullNamespace($cleanSubtype, $strNs); 284 | $child = $this->mapArray($jvalue, $array, $subtype, $key); 285 | } else if ($this->isFlatType(gettype($jvalue))) { 286 | //use constructor parameter if we have a class 287 | // but only a flat type (i.e. string, int) 288 | if ($this->bStrictObjectTypeChecking) { 289 | throw new JsonMapper_Exception( 290 | 'JSON property "' . $key . '" must be an object, ' 291 | . gettype($jvalue) . ' given' 292 | ); 293 | } 294 | $child = $this->createInstance($type, true, $jvalue); 295 | } else { 296 | $child = $this->createInstance($type, false, $jvalue); 297 | $this->map($jvalue, $child); 298 | } 299 | $this->setProperty($object, $accessor, $child); 300 | } 301 | 302 | if ($this->bExceptionOnMissingData) { 303 | $this->checkMissingData($providedProperties, $rc); 304 | } 305 | 306 | if ($this->bRemoveUndefinedAttributes) { 307 | $this->removeUndefinedAttributes($object, $providedProperties); 308 | } 309 | 310 | if ($this->postMappingMethod !== null 311 | && $rc->hasMethod($this->postMappingMethod) 312 | ) { 313 | $refDeserializePostMethod = $rc->getMethod( 314 | $this->postMappingMethod 315 | ); 316 | $refDeserializePostMethod->setAccessible(true); 317 | $refDeserializePostMethod->invoke($object); 318 | } 319 | 320 | return $object; 321 | } 322 | 323 | /** 324 | * Convert a type name to a fully namespaced type name. 325 | * 326 | * @param string $type Type name (simple type or class name) 327 | * @param string $strNs Base namespace that gets prepended to the type name 328 | * 329 | * @return string Fully-qualified type name with namespace 330 | */ 331 | protected function getFullNamespace($type, $strNs) 332 | { 333 | if ($type === null || $type === '' || $type[0] === '\\' || $strNs === '') { 334 | return $type; 335 | } 336 | list($first) = explode('[', $type, 2); 337 | if ($first === 'mixed' || $this->isSimpleType($first)) { 338 | return $type; 339 | } 340 | 341 | //create a full qualified namespace 342 | return '\\' . $strNs . '\\' . $type; 343 | } 344 | 345 | /** 346 | * Check required properties exist in json 347 | * 348 | * @param array $providedProperties array with json properties 349 | * @param object $rc Reflection class to check 350 | * 351 | * @throws JsonMapper_Exception 352 | * 353 | * @return void 354 | */ 355 | protected function checkMissingData($providedProperties, ReflectionClass $rc) 356 | { 357 | foreach ($rc->getProperties() as $property) { 358 | $rprop = $rc->getProperty($property->name); 359 | $docblock = $rprop->getDocComment(); 360 | $annotations = static::parseAnnotations($docblock); 361 | if (isset($annotations['required']) 362 | && !isset($providedProperties[$property->name]) 363 | ) { 364 | throw new JsonMapper_Exception( 365 | 'Required property "' . $property->name . '" of class ' 366 | . $rc->getName() 367 | . ' is missing in JSON data' 368 | ); 369 | } 370 | } 371 | } 372 | 373 | /** 374 | * Remove attributes from object that were not passed in JSON data. 375 | * 376 | * This is to avoid confusion between those that were actually passed 377 | * as NULL, and those that weren't provided at all. 378 | * 379 | * @param object $object Object to remove properties from 380 | * @param array $providedProperties Array with JSON properties 381 | * 382 | * @return void 383 | */ 384 | protected function removeUndefinedAttributes($object, $providedProperties) 385 | { 386 | foreach (get_object_vars($object) as $propertyName => $dummy) { 387 | if (!isset($providedProperties[$propertyName])) { 388 | unset($object->{$propertyName}); 389 | } 390 | } 391 | } 392 | 393 | /** 394 | * Map an array 395 | * 396 | * @param array $json JSON array structure from json_decode() 397 | * @param mixed $array Array or ArrayObject that gets filled with 398 | * data from $json 399 | * @param string $class Class name for children objects. 400 | * All children will get mapped onto this type. 401 | * Supports class names and simple types 402 | * like "string" and nullability "string|null". 403 | * Pass "null" to not convert any values 404 | * @param string $parent_key Defines the key this array belongs to 405 | * in order to aid debugging. 406 | * 407 | * @return mixed Mapped $array is returned 408 | */ 409 | public function mapArray($json, $array, $class = null, $parent_key = '') 410 | { 411 | $originalClass = $class; 412 | foreach ($json as $key => $jvalue) { 413 | $class = $this->getMappedType($originalClass, $jvalue); 414 | if ($class === null) { 415 | $array[$key] = $jvalue; 416 | } else if ($this->isArrayOfType($class)) { 417 | $array[$key] = $this->mapArray( 418 | $jvalue, 419 | array(), 420 | substr($class, 0, -2) 421 | ); 422 | } else if ($this->isFlatType(gettype($jvalue))) { 423 | //use constructor parameter if we have a class 424 | // but only a flat type (i.e. string, int) 425 | if ($jvalue === null) { 426 | $array[$key] = null; 427 | } else { 428 | if ($this->isSimpleType($class)) { 429 | settype($jvalue, $class); 430 | $array[$key] = $jvalue; 431 | } else { 432 | $array[$key] = $this->createInstance( 433 | $class, true, $jvalue 434 | ); 435 | } 436 | } 437 | } else if ($this->isFlatType($class)) { 438 | throw new JsonMapper_Exception( 439 | 'JSON property "' . ($parent_key ? $parent_key : '?') . '"' 440 | . ' is an array of type "' . $class . '"' 441 | . ' but contained a value of type' 442 | . ' "' . gettype($jvalue) . '"' 443 | ); 444 | } else if (is_a($class, 'ArrayObject', true)) { 445 | $array[$key] = $this->mapArray( 446 | $jvalue, 447 | $this->createInstance($class) 448 | ); 449 | } else { 450 | $array[$key] = $this->map( 451 | $jvalue, $this->createInstance($class, false, $jvalue) 452 | ); 453 | } 454 | } 455 | return $array; 456 | } 457 | 458 | /** 459 | * Try to find out if a property exists in a given class. 460 | * Checks property first, falls back to setter method. 461 | * 462 | * @param ReflectionClass $rc Reflection class to check 463 | * @param string $name Property name 464 | * 465 | * @return array First value: if the property exists 466 | * Second value: the accessor to use ( 467 | * ReflectionMethod or ReflectionProperty, or null) 468 | * Third value: type of the property 469 | * Fourth value: if the property is nullable 470 | */ 471 | protected function inspectProperty(ReflectionClass $rc, $name) 472 | { 473 | //try setter method first 474 | $setter = 'set' . $this->getCamelCaseName($name); 475 | 476 | if ($rc->hasMethod($setter)) { 477 | $rmeth = $rc->getMethod($setter); 478 | if ($rmeth->isPublic() || $this->bIgnoreVisibility) { 479 | $isNullable = false; 480 | $rparams = $rmeth->getParameters(); 481 | if (count($rparams) > 0) { 482 | $isNullable = $rparams[0]->allowsNull(); 483 | $ptype = $rparams[0]->getType(); 484 | if ($ptype !== null) { 485 | if ($ptype instanceof ReflectionNamedType) { 486 | $typeName = $ptype->getName(); 487 | } 488 | if ($ptype instanceof ReflectionUnionType 489 | || !$ptype->isBuiltin() 490 | ) { 491 | $typeName = '\\' . $typeName; 492 | } 493 | //allow overriding an "array" type hint 494 | // with a more specific class in the docblock 495 | if ($typeName !== 'array') { 496 | return array( 497 | true, $rmeth, 498 | $typeName, 499 | $isNullable, 500 | ); 501 | } 502 | } 503 | } 504 | 505 | $docblock = $rmeth->getDocComment(); 506 | $annotations = static::parseAnnotations($docblock); 507 | 508 | if (!isset($annotations['param'][0])) { 509 | return array(true, $rmeth, null, $isNullable); 510 | } 511 | list($type) = explode(' ', trim($annotations['param'][0])); 512 | return array(true, $rmeth, $type, $this->isNullable($type)); 513 | } 514 | } 515 | 516 | //now try to set the property directly 517 | //we have to look it up in the class hierarchy 518 | $class = $rc; 519 | $rprop = null; 520 | do { 521 | if ($class->hasProperty($name)) { 522 | $rprop = $class->getProperty($name); 523 | } 524 | } while ($rprop === null && $class = $class->getParentClass()); 525 | 526 | if ($rprop === null) { 527 | //case-insensitive property matching 528 | foreach ($rc->getProperties() as $p) { 529 | if ((strcasecmp($p->name, $name) === 0)) { 530 | $rprop = $p; 531 | break; 532 | } 533 | } 534 | } 535 | if ($rprop !== null) { 536 | if ($rprop->isPublic() || $this->bIgnoreVisibility) { 537 | $docblock = $rprop->getDocComment(); 538 | $annotations = static::parseAnnotations($docblock); 539 | 540 | if (!isset($annotations['var'][0])) { 541 | // If there is no annotations (higher priority) inspect 542 | // if there's a scalar type being defined 543 | if (PHP_VERSION_ID >= 70400 && $rprop->hasType()) { 544 | $rPropType = $rprop->getType(); 545 | $propTypeName = $rPropType->getName(); 546 | 547 | if ($this->isSimpleType($propTypeName)) { 548 | return array( 549 | true, 550 | $rprop, 551 | $propTypeName, 552 | $rPropType->allowsNull() 553 | ); 554 | } 555 | 556 | return array( 557 | true, 558 | $rprop, 559 | '\\'.$propTypeName, 560 | $rPropType->allowsNull() 561 | ); 562 | } 563 | 564 | return array(true, $rprop, null, false); 565 | } 566 | 567 | //support "@var type description" 568 | list($type) = explode(' ', $annotations['var'][0]); 569 | 570 | return array(true, $rprop, $type, $this->isNullable($type)); 571 | } else { 572 | //no setter, private property 573 | return array(true, null, null, false); 574 | } 575 | } 576 | 577 | //no setter, no property 578 | return array(false, null, null, false); 579 | } 580 | 581 | /** 582 | * Removes - and _ and makes the next letter uppercase 583 | * 584 | * @param string $name Property name 585 | * 586 | * @return string CamelCasedVariableName 587 | */ 588 | protected function getCamelCaseName($name) 589 | { 590 | return str_replace( 591 | ' ', '', ucwords(str_replace(array('_', '-'), ' ', $name)) 592 | ); 593 | } 594 | 595 | /** 596 | * Since hyphens cannot be used in variables we have to uppercase them. 597 | * 598 | * Technically you may use them, but they are awkward to access. 599 | * 600 | * @param string $name Property name 601 | * 602 | * @return string Name without hyphen 603 | */ 604 | protected function getSafeName($name) 605 | { 606 | if (strpos($name, '-') !== false) { 607 | $name = $this->getCamelCaseName($name); 608 | } 609 | 610 | return $name; 611 | } 612 | 613 | /** 614 | * Set a property on a given object to a given value. 615 | * 616 | * Checks if the setter or the property are public are made before 617 | * calling this method. 618 | * 619 | * @param object $object Object to set property on 620 | * @param object $accessor ReflectionMethod or ReflectionProperty 621 | * @param mixed $value Value of property 622 | * 623 | * @return void 624 | */ 625 | protected function setProperty( 626 | $object, $accessor, $value 627 | ) { 628 | if (!$accessor->isPublic() && $this->bIgnoreVisibility) { 629 | $accessor->setAccessible(true); 630 | } 631 | if ($accessor instanceof ReflectionProperty) { 632 | $accessor->setValue($object, $value); 633 | } else { 634 | //setter method 635 | $accessor->invoke($object, $value); 636 | } 637 | } 638 | 639 | /** 640 | * Create a new object of the given type. 641 | * 642 | * This method exists to be overwritten in child classes, 643 | * so you can do dependency injection or so. 644 | * 645 | * @param string $class Class name to instantiate 646 | * @param boolean $useParameter Pass $parameter to the constructor or not 647 | * @param mixed $jvalue Constructor parameter (the json value) 648 | * 649 | * @return object Freshly created object 650 | */ 651 | protected function createInstance( 652 | $class, $useParameter = false, $jvalue = null 653 | ) { 654 | if ($useParameter) { 655 | return new $class($jvalue); 656 | } else { 657 | $reflectClass = new ReflectionClass($class); 658 | $constructor = $reflectClass->getConstructor(); 659 | if (null === $constructor 660 | || $constructor->getNumberOfRequiredParameters() > 0 661 | ) { 662 | return $reflectClass->newInstanceWithoutConstructor(); 663 | } 664 | return $reflectClass->newInstance(); 665 | } 666 | } 667 | 668 | /** 669 | * Get the mapped class/type name for this class. 670 | * Returns the incoming classname if not mapped. 671 | * 672 | * @param string $type Type name to map 673 | * @param mixed $jvalue Constructor parameter (the json value) 674 | * 675 | * @return string The mapped type/class name 676 | */ 677 | protected function getMappedType($type, $jvalue = null) 678 | { 679 | if (isset($this->classMap[$type])) { 680 | $target = $this->classMap[$type]; 681 | } else if (is_string($type) && $type !== '' && $type[0] == '\\' 682 | && isset($this->classMap[substr($type, 1)]) 683 | ) { 684 | $target = $this->classMap[substr($type, 1)]; 685 | } else { 686 | $target = null; 687 | } 688 | 689 | if ($target) { 690 | if (is_callable($target)) { 691 | $type = $target($type, $jvalue); 692 | } else { 693 | $type = $target; 694 | } 695 | } 696 | return $type; 697 | } 698 | 699 | /** 700 | * Checks if the given type is a "simple type" 701 | * 702 | * @param string $type type name from gettype() 703 | * 704 | * @return boolean True if it is a simple PHP type 705 | * 706 | * @see isFlatType() 707 | */ 708 | protected function isSimpleType($type) 709 | { 710 | return $type == 'string' 711 | || $type == 'boolean' || $type == 'bool' 712 | || $type == 'integer' || $type == 'int' 713 | || $type == 'double' || $type == 'float' 714 | || $type == 'array' || $type == 'object'; 715 | } 716 | 717 | /** 718 | * Checks if the object is of this type or has this type as one of its parents 719 | * 720 | * @param string $type class name of type being required 721 | * @param mixed $value Some PHP value to be tested 722 | * 723 | * @return boolean True if $object has type of $type 724 | */ 725 | protected function isObjectOfSameType($type, $value) 726 | { 727 | if (false === is_object($value)) { 728 | return false; 729 | } 730 | 731 | return is_a($value, $type); 732 | } 733 | 734 | /** 735 | * Checks if the given type is a type that is not nested 736 | * (simple type except array and object) 737 | * 738 | * @param string $type type name from gettype() 739 | * 740 | * @return boolean True if it is a non-nested PHP type 741 | * 742 | * @see isSimpleType() 743 | */ 744 | protected function isFlatType($type) 745 | { 746 | return $type == 'NULL' 747 | || $type == 'string' 748 | || $type == 'boolean' || $type == 'bool' 749 | || $type == 'integer' || $type == 'int' 750 | || $type == 'double' || $type == 'float'; 751 | } 752 | 753 | /** 754 | * Returns true if type is an array of elements 755 | * (bracket notation) 756 | * 757 | * @param string $strType type to be matched 758 | * 759 | * @return bool 760 | */ 761 | protected function isArrayOfType($strType) 762 | { 763 | return substr($strType, -2) === '[]'; 764 | } 765 | 766 | /** 767 | * Checks if the given type is nullable 768 | * 769 | * @param string $type type name from the phpdoc param 770 | * 771 | * @return boolean True if it is nullable 772 | */ 773 | protected function isNullable($type) 774 | { 775 | return stripos('|' . $type . '|', '|null|') !== false; 776 | } 777 | 778 | /** 779 | * Remove the 'null' section of a type 780 | * 781 | * @param string $type type name from the phpdoc param 782 | * 783 | * @return string The new type value 784 | */ 785 | protected function removeNullable($type) 786 | { 787 | if ($type === null) { 788 | return null; 789 | } 790 | return substr( 791 | str_ireplace('|null|', '|', '|' . $type . '|'), 792 | 1, -1 793 | ); 794 | } 795 | 796 | /** 797 | * Copied from PHPUnit 3.7.29, Util/Test.php 798 | * 799 | * @param string $docblock Full method docblock 800 | * 801 | * @return array Array of arrays. 802 | * Key is the "@"-name like "param", 803 | * each value is an array of the rest of the @-lines 804 | */ 805 | protected static function parseAnnotations($docblock) 806 | { 807 | $annotations = array(); 808 | // Strip away the docblock header and footer 809 | // to ease parsing of one line annotations 810 | $docblock = substr($docblock, 3, -2); 811 | 812 | $re = '/@(?P[A-Za-z_-]+)(?:[ \t]+(?P.*?))?[ \t]*\r?$/m'; 813 | if (preg_match_all($re, $docblock, $matches)) { 814 | $numMatches = count($matches[0]); 815 | 816 | for ($i = 0; $i < $numMatches; ++$i) { 817 | $annotations[$matches['name'][$i]][] = $matches['value'][$i]; 818 | } 819 | } 820 | 821 | return $annotations; 822 | } 823 | 824 | /** 825 | * Log a message to the $logger object 826 | * 827 | * @param string $level Logging level 828 | * @param string $message Text to log 829 | * @param array $context Additional information 830 | * 831 | * @return null 832 | */ 833 | protected function log($level, $message, array $context = array()) 834 | { 835 | if ($this->logger) { 836 | $this->logger->log($level, $message, $context); 837 | } 838 | } 839 | 840 | /** 841 | * Sets a logger instance on the object 842 | * 843 | * @param LoggerInterface $logger PSR-3 compatible logger object 844 | * 845 | * @return null 846 | */ 847 | public function setLogger($logger) 848 | { 849 | $this->logger = $logger; 850 | } 851 | } 852 | ?> 853 | -------------------------------------------------------------------------------- /src/BitPaySDKLight/Util/JsonMapper/JsonMapperException.php: -------------------------------------------------------------------------------- 1 | bitPayCode.$this->bitPayMessage."-> ".$message; 22 | 23 | parent::__construct($message, 101); 24 | } 25 | } -------------------------------------------------------------------------------- /src/BitPaySDKLight/Util/RESTcli/RESTcli.php: -------------------------------------------------------------------------------- 1 | _baseUrl = $environment == Env::Test ? Env::TestUrl : Env::ProdUrl; 29 | $this->init(); 30 | } 31 | 32 | public function init() 33 | { 34 | try { 35 | $this->_client = new GuzzleHttpClient( 36 | [ 37 | 'base_url' => $this->_baseUrl, 38 | 'defaults' => [ 39 | 'headers' => [ 40 | 'x-accept-version' => Env::BitpayApiVersion, 41 | 'x-bitpay-plugin-info' => Env::BitpayPluginInfo, 42 | 'x-bitpay-api-frame' => Env::BitpayApiFrame, 43 | 'x-bitpay-api-frame-version' => Env::BitpayApiFrameVersion, 44 | ], 45 | ], 46 | ]); 47 | } catch (Exception $e) { 48 | throw new BitPayException("RESTcli init failed : ".$e->getMessage()); 49 | } 50 | } 51 | 52 | public function post($uri, array $formData = []): string 53 | { 54 | try { 55 | $fullURL = $this->_baseUrl.$uri; 56 | $headers = [ 57 | 'Content-Type' => 'application/json', 58 | 'x-accept-version' => Env::BitpayApiVersion, 59 | 'x-bitpay-plugin-info' => Env::BitpayPluginInfo, 60 | 'x-bitpay-api-frame' => Env::BitpayApiFrame, 61 | 'x-bitpay-api-frame-version' => Env::BitpayApiFrameVersion, 62 | ]; 63 | 64 | /** 65 | * @var Response 66 | */ 67 | $response = $this->_client->requestAsync( 68 | 'POST', $fullURL, [ 69 | $options[RequestOptions::SYNCHRONOUS] = false, 70 | 'headers' => $headers, 71 | RequestOptions::JSON => $formData, 72 | ])->wait(); 73 | $responseJson = $this->responseToJsonString($response); 74 | return $responseJson; 75 | } catch (BadResponseException $e) { 76 | $errorJson = $this->responseToJsonString($e->getResponse()); 77 | throw new BitPayException("POST failed : Guzzle/BadResponseException : ".$errorJson['message'], $errorJson['code']); 78 | } catch (Exception $e) { 79 | throw new BitPayException("POST failed : ".$e->getMessage()); 80 | } 81 | } 82 | 83 | public function get($uri, array $parameters = null): string 84 | { 85 | try { 86 | $fullURL = $this->_baseUrl.$uri; 87 | $headers = [ 88 | 'Content-Type' => 'application/json', 89 | 'x-accept-version' => Env::BitpayApiVersion, 90 | 'x-bitpay-plugin-info' => Env::BitpayPluginInfo, 91 | 'x-bitpay-api-frame' => Env::BitpayApiFrame, 92 | 'x-bitpay-api-frame-version' => Env::BitpayApiFrameVersion, 93 | ]; 94 | 95 | if ($parameters) { 96 | $fullURL .= '?'.http_build_query($parameters); 97 | } 98 | 99 | /** 100 | * @var Response 101 | */ 102 | $response = $this->_client->requestAsync( 103 | 'GET', $fullURL, [ 104 | $options[RequestOptions::SYNCHRONOUS] = false, 105 | 'headers' => $headers, 106 | 'query' => $parameters, 107 | ])->wait(); 108 | $responseJson = $this->responseToJsonString($response); 109 | return $responseJson; 110 | } catch (BadResponseException $e) { 111 | $errorJson = $this->responseToJsonString($e->getResponse()); 112 | throw new BitPayException("GET failed : Guzzle/BadResponseException : ".$errorJson['message'], $errorJson['code']); 113 | } catch (Exception $e) { 114 | throw new BitPayException("GET failed : ".$e->getMessage()); 115 | } 116 | } 117 | 118 | public function delete($uri, array $parameters = null): string 119 | { 120 | try { 121 | $fullURL = $this->_baseUrl.$uri; 122 | if ($parameters) { 123 | $fullURL .= '?'.http_build_query($parameters); 124 | } 125 | 126 | $headers = [ 127 | 'x-accept-version' => Env::BitpayApiVersion, 128 | 'x-bitpay-plugin-info' => Env::BitpayPluginInfo, 129 | 'x-bitpay-api-frame' => Env::BitpayApiFrame, 130 | 'x-bitpay-api-frame-version' => Env::BitpayApiFrameVersion, 131 | 'Content-Type' => 'application/json', 132 | ]; 133 | 134 | /** 135 | * @var Response 136 | */ 137 | $response = $this->_client->requestAsync( 138 | 'DELETE', $fullURL, [ 139 | $options[RequestOptions::SYNCHRONOUS] = false, 140 | 'headers' => $headers, 141 | 'query' => $parameters, 142 | ])->wait(); 143 | 144 | $responseJson = $this->responseToJsonString($response); 145 | 146 | return $responseJson; 147 | } catch (BadResponseException $e) { 148 | $errorJson = $this->responseToJsonString($e->getResponse()); 149 | throw new BitPayException("DELETE failed : Guzzle/BadResponseException : ".$errorJson['message'], $errorJson['code']); 150 | } catch (Exception $e) { 151 | throw new BitPayException("DELETE failed : ".$e->getMessage()); 152 | } 153 | } 154 | 155 | public function update($uri, array $formData = []): string 156 | { 157 | try { 158 | $fullURL = $this->_baseUrl.$uri; 159 | $headers = [ 160 | 'x-accept-version' => Env::BitpayApiVersion, 161 | 'x-bitpay-plugin-info' => Env::BitpayPluginInfo, 162 | 'x-bitpay-api-frame' => Env::BitpayApiFrame, 163 | 'x-bitpay-api-frame-version' => Env::BitpayApiFrameVersion, 164 | 'Content-Type' => 'application/json', 165 | ]; 166 | 167 | /** 168 | * @var Response 169 | */ 170 | $response = $this->_client->requestAsync( 171 | 'PUT', $fullURL, [ 172 | $options[RequestOptions::SYNCHRONOUS] = false, 173 | 'headers' => $headers, 174 | RequestOptions::JSON => $formData, 175 | ])->wait(); 176 | 177 | $responseJson = $this->responseToJsonString($response); 178 | 179 | return $responseJson; 180 | } catch (BadResponseException $e) { 181 | $errorJson = $this->responseToJsonString($e->getResponse()); 182 | throw new BitPayException("UPDATE failed : Guzzle/BadResponseException : ".$errorJson['message'], $errorJson['code']); 183 | } catch (Exception $e) { 184 | throw new BitPayException("UPDATE failed : ".$e->getMessage()); 185 | } 186 | } 187 | 188 | public function responseToJsonString(Response $response): string 189 | { 190 | if ($response == null) { 191 | throw new Exception("Error: HTTP response is null"); 192 | } 193 | 194 | try { 195 | $body = json_decode($response->getBody()->getContents(), true); 196 | 197 | if (!empty($body['status'])) { 198 | if ($body['status'] == 'error') { 199 | throw new BitpayException($body['message'], null, null, $body['code']); 200 | } 201 | } 202 | 203 | $error_message = false; 204 | $error_message = (!empty($body['error'])) ? $body['error'] : $error_message; 205 | $error_message = (!empty($body['errors'])) ? $body['errors'] : $error_message; 206 | $error_message = (is_array($error_message)) ? implode("\n", $error_message) : $error_message; 207 | if (false !== $error_message) { 208 | throw new BitpayException($error_message); 209 | } 210 | if (!empty($body['success'])) { 211 | return json_encode($body); 212 | } 213 | 214 | return json_encode($body['data']); 215 | 216 | } catch (BitpayException $e) { 217 | throw new BitPayException("failed to retrieve HTTP response body : ".$e->getMessage(), null, null, $e->getApiCode()); 218 | } catch (Exception $e) { 219 | throw new BitPayException("failed to retrieve HTTP response body : ".$e->getMessage()); 220 | } 221 | } 222 | 223 | } 224 | -------------------------------------------------------------------------------- /tests/BitPaySDKLight/BitPayTest.php: -------------------------------------------------------------------------------- 1 | _clientMock = $this->createMock(Client::class); 33 | try { 34 | $this->_client = new Client($this->_token, $this->_environment); 35 | } catch (\Exception $e) { 36 | $e->getTraceAsString(); 37 | self::fail($e->getMessage()); 38 | } 39 | 40 | $this->assertNotNull($this->_client); 41 | } 42 | 43 | public function testShouldGetInvoiceId() 44 | { 45 | $invoice = new Invoice(2.16, "eur"); 46 | $invoice->setOrderId("98e572ea-910e-415d-b6de-65f5090680f6"); 47 | $invoice->setFullNotifications(true); 48 | $invoice->setExtendedNotifications(true); 49 | $invoice->setTransactionSpeed("medium"); 50 | $invoice->setNotificationURL("https://hookbin.com/lJnJg9WW7MtG9GZlPVdj"); 51 | $invoice->setRedirectURL("https://hookbin.com/lJnJg9WW7MtG9GZlPVdj"); 52 | $invoice->setPosData("98e572ea35hj356xft8y8cgh56h5090680f6"); 53 | $invoice->setItemDesc("Ab tempora sed ut."); 54 | $invoice->setNotificationEmail(""); 55 | 56 | $buyer = new Buyer(); 57 | $buyer->setName("Bily Matthews"); 58 | $buyer->setEmail(""); 59 | $buyer->setAddress1("168 General Grove"); 60 | $buyer->setAddress2(""); 61 | $buyer->setCountry("AD"); 62 | $buyer->setLocality("Port Horizon"); 63 | $buyer->setNotify(true); 64 | $buyer->setPhone("+99477512690"); 65 | $buyer->setPostalCode("KY7 1TH"); 66 | $buyer->setRegion("New Port"); 67 | 68 | $invoice->setBuyer($buyer); 69 | 70 | try { 71 | $basicInvoice = $this->_client->createInvoice($invoice); 72 | $retrievedInvoice = $this->_client->getInvoice($basicInvoice->getId()); 73 | } catch (\Exception $e) { 74 | $e->getTraceAsString(); 75 | self::fail($e->getMessage()); 76 | } 77 | 78 | $this->assertNotNull($basicInvoice->getId()); 79 | $this->assertNotNull($retrievedInvoice->getId()); 80 | $this->assertEquals($basicInvoice->getId(), $retrievedInvoice->getId()); 81 | } 82 | 83 | public function testShouldCreateInvoiceBtc() 84 | { 85 | try { 86 | $basicInvoice = $this->_client->createInvoice(new Invoice(0.1, Currency::BTC)); 87 | } catch (\Exception $e) { 88 | $e->getTraceAsString(); 89 | self::fail($e->getMessage()); 90 | } 91 | 92 | $this->assertNotNull($basicInvoice->getId()); 93 | 94 | } 95 | 96 | public function testShouldCreateInvoiceBch() 97 | { 98 | try { 99 | $basicInvoice = $this->_client->createInvoice(new Invoice(0.1, Currency::BCH)); 100 | } catch (\Exception $e) { 101 | $e->getTraceAsString(); 102 | self::fail($e->getMessage()); 103 | } 104 | 105 | $this->assertNotNull($basicInvoice->getId()); 106 | 107 | } 108 | 109 | public function testShouldCreateInvoiceEth() 110 | { 111 | try { 112 | $basicInvoice = $this->_client->createInvoice(new Invoice(0.1, Currency::ETH)); 113 | } catch (\Exception $e) { 114 | $e->getTraceAsString(); 115 | self::fail($e->getMessage()); 116 | } 117 | 118 | $this->assertNotNull($basicInvoice->getId()); 119 | 120 | } 121 | 122 | public function testShouldCreateBillUSD() 123 | { 124 | $items = []; 125 | 126 | $item = new Item(); 127 | $item->setPrice(30.0); 128 | $item->setQuantity(9); 129 | $item->setDescription("product-a"); 130 | array_push($items, $item); 131 | 132 | $item = new Item(); 133 | $item->setPrice(14.0); 134 | $item->setQuantity(16); 135 | $item->setDescription("product-b"); 136 | array_push($items, $item); 137 | 138 | $item = new Item(); 139 | $item->setPrice(3.90); 140 | $item->setQuantity(42); 141 | $item->setDescription("product-c"); 142 | array_push($items, $item); 143 | 144 | $item = new Item(); 145 | $item->setPrice(6.99); 146 | $item->setQuantity(12); 147 | $item->setDescription("product-d"); 148 | array_push($items, $item); 149 | 150 | $bill = new Bill("1001", Currency::USD, "", $items); 151 | $bill->setEmail("sandbox@bitpay.com"); 152 | $basicBill = null; 153 | try { 154 | $basicBill = $this->_client->createBill($bill); 155 | } catch (\Exception $e) { 156 | $e->getTraceAsString(); 157 | self::fail($e->getMessage()); 158 | } 159 | 160 | $this->assertNotNull($basicBill->getId()); 161 | $this->assertNotNull($basicBill->getItems()[0]->getId()); 162 | } 163 | 164 | public function testShouldCreateBillEUR() 165 | { 166 | $items = []; 167 | 168 | $item = new Item(); 169 | $item->setPrice(30.0); 170 | $item->setQuantity(9); 171 | $item->setDescription("product-a"); 172 | array_push($items, $item); 173 | 174 | $item = new Item(); 175 | $item->setPrice(14.0); 176 | $item->setQuantity(16); 177 | $item->setDescription("product-b"); 178 | array_push($items, $item); 179 | 180 | $item = new Item(); 181 | $item->setPrice(3.90); 182 | $item->setQuantity(42); 183 | $item->setDescription("product-c"); 184 | array_push($items, $item); 185 | 186 | $item = new Item(); 187 | $item->setPrice(6.99); 188 | $item->setQuantity(12); 189 | $item->setDescription("product-d"); 190 | array_push($items, $item); 191 | 192 | $bill = new Bill("1002", Currency::EUR, "", $items); 193 | $bill->setEmail("sandbox@bitpay.com"); 194 | $basicBill = null; 195 | try { 196 | $basicBill = $this->_client->createBill($bill); 197 | } catch (\Exception $e) { 198 | $e->getTraceAsString(); 199 | self::fail($e->getMessage()); 200 | } 201 | 202 | $this->assertNotNull($basicBill->getId()); 203 | $this->assertNotNull($basicBill->getUrl()); 204 | $this->assertEquals(BillStatus::Draft, $basicBill->getStatus()); 205 | $this->assertNotNull($basicBill->getItems()[0]->getId()); 206 | } 207 | 208 | public function testShouldGetBill() 209 | { 210 | $items = []; 211 | 212 | $item = new Item(); 213 | $item->setPrice(30.0); 214 | $item->setQuantity(9); 215 | $item->setDescription("product-a"); 216 | array_push($items, $item); 217 | 218 | $item = new Item(); 219 | $item->setPrice(14.0); 220 | $item->setQuantity(16); 221 | $item->setDescription("product-b"); 222 | array_push($items, $item); 223 | 224 | $item = new Item(); 225 | $item->setPrice(3.90); 226 | $item->setQuantity(42); 227 | $item->setDescription("product-c"); 228 | array_push($items, $item); 229 | 230 | $item = new Item(); 231 | $item->setPrice(6.99); 232 | $item->setQuantity(12); 233 | $item->setDescription("product-d"); 234 | array_push($items, $item); 235 | 236 | $bill = new Bill("1003", Currency::EUR, "", $items); 237 | $bill->setEmail("sandbox@bitpay.com"); 238 | $basicBill = null; 239 | $retrievedBill = null; 240 | try { 241 | $basicBill = $this->_client->createBill($bill); 242 | $retrievedBill = $this->_client->getBill($basicBill->getId()); 243 | } catch (\Exception $e) { 244 | $e->getTraceAsString(); 245 | self::fail($e->getMessage()); 246 | } 247 | 248 | $this->assertEquals($basicBill->getId(), $retrievedBill->getId()); 249 | $this->assertEquals($basicBill->getItems(), $retrievedBill->getItems()); 250 | } 251 | 252 | public function testShouldDeliverBill() 253 | { 254 | $items = []; 255 | 256 | $item = new Item(); 257 | $item->setPrice(30.0); 258 | $item->setQuantity(9); 259 | $item->setDescription("product-a"); 260 | array_push($items, $item); 261 | 262 | $item = new Item(); 263 | $item->setPrice(14.0); 264 | $item->setQuantity(16); 265 | $item->setDescription("product-b"); 266 | array_push($items, $item); 267 | 268 | $item = new Item(); 269 | $item->setPrice(3.90); 270 | $item->setQuantity(42); 271 | $item->setDescription("product-c"); 272 | array_push($items, $item); 273 | 274 | $item = new Item(); 275 | $item->setPrice(6.99); 276 | $item->setQuantity(12); 277 | $item->setDescription("product-d"); 278 | array_push($items, $item); 279 | 280 | $bill = new Bill("1005", Currency::EUR, "", $items); 281 | $bill->setEmail("sandbox@bitpay.com"); 282 | $basicBill = null; 283 | $retrievedBill = null; 284 | $result = null; 285 | try { 286 | $basicBill = $this->_client->createBill($bill); 287 | $result = $this->_client->deliverBill($basicBill->getId(), $basicBill->getToken()); 288 | $retrievedBill = $this->_client->getBill($basicBill->getId()); 289 | } catch (\Exception $e) { 290 | $e->getTraceAsString(); 291 | self::fail($e->getMessage()); 292 | } 293 | 294 | $this->assertEquals($basicBill->getId(), $retrievedBill->getId()); 295 | $this->assertEquals($basicBill->getItems(), $retrievedBill->getItems()); 296 | $this->assertEquals("Success", $result); 297 | $this->assertNotEquals($basicBill->getStatus(), $retrievedBill->getStatus()); 298 | $this->assertEquals($retrievedBill->getStatus(), BillStatus::Sent); 299 | } 300 | 301 | public function testShouldGetExchangeRates() 302 | { 303 | $ratesList = null; 304 | try { 305 | $rates = $this->_client->getRates(); 306 | $ratesList = $rates->getRates(); 307 | } catch (\Exception $e) { 308 | $e->getTraceAsString(); 309 | self::fail($e->getMessage()); 310 | } 311 | 312 | $this->assertNotNull($ratesList); 313 | } 314 | 315 | public function testShouldGetEURExchangeRate() 316 | { 317 | $rate = null; 318 | try { 319 | $rates = $this->_client->getRates(); 320 | $rate = $rates->getRate(Currency::EUR); 321 | } catch (\Exception $e) { 322 | $e->getTraceAsString(); 323 | self::fail($e->getMessage()); 324 | } 325 | 326 | $this->assertNotEquals(0, $rate); 327 | } 328 | 329 | public function testShouldGetCNYExchangeRate() 330 | { 331 | $rate = null; 332 | try { 333 | $rates = $this->_client->getRates(); 334 | $rate = $rates->getRate(Currency::CNY); 335 | } catch (\Exception $e) { 336 | $e->getTraceAsString(); 337 | self::fail($e->getMessage()); 338 | } 339 | 340 | $this->assertNotEquals(0, $rate); 341 | } 342 | 343 | public function testShouldUpdateExchangeRates() 344 | { 345 | $rates = null; 346 | $ratesList = null; 347 | try { 348 | $rates = $this->_client->getRates(); 349 | $rates->update(); 350 | $ratesList = $rates->getRates(); 351 | } catch (\Exception $e) { 352 | $e->getTraceAsString(); 353 | self::fail($e->getMessage()); 354 | } 355 | 356 | $this->assertNotNull($ratesList); 357 | } 358 | 359 | public function testShouldGetETHExchangeRates() 360 | { 361 | $ratesList = null; 362 | try { 363 | $rates = $this->_client->getCurrencyRates(Currency::ETH); 364 | $ratesList = $rates->getRates(); 365 | } catch (\Exception $e) { 366 | $e->getTraceAsString(); 367 | self::fail($e->getMessage()); 368 | } 369 | 370 | $this->assertNotNull($ratesList); 371 | } 372 | 373 | public function testShouldGetETHToUSDExchangeRate() 374 | { 375 | $rate = null; 376 | try { 377 | $rate = $this->_client->getCurrencyPairRate(Currency::ETH, Currency::USD); 378 | } catch (\Exception $e) { 379 | $e->getTraceAsString(); 380 | self::fail($e->getMessage()); 381 | } 382 | 383 | $this->assertNotNull($rate); 384 | } 385 | 386 | public function testShouldGetCurrencies() 387 | { 388 | $currencyList = null; 389 | try { 390 | $currencyList = $this->_client->getCurrencies(); 391 | } catch (\Exception $e) { 392 | $e->getTraceAsString(); 393 | self::fail($e->getMessage()); 394 | } 395 | 396 | $this->assertNotNull($currencyList); 397 | } 398 | } 399 | --------------------------------------------------------------------------------