├── src ├── TaxType.php ├── Exceptions │ └── Facturapi_Exception.php ├── InvoiceType.php ├── InvoiceRelation.php ├── PaymentForm.php ├── Resources │ ├── Tools.php │ ├── Catalogs.php │ ├── Products.php │ ├── Webhooks.php │ ├── Customers.php │ ├── Retentions.php │ ├── Receipts.php │ ├── CartaPorteCatalogs.php │ ├── Invoices.php │ └── Organizations.php ├── Facturapi.php └── Http │ └── BaseClient.php ├── .gitignore ├── composer.json ├── LICENSE ├── example.php └── README.md /src/TaxType.php: -------------------------------------------------------------------------------- 1 | =5.5.0" 24 | }, 25 | "require-dev": { 26 | "phpspec/phpspec": "~2.0", 27 | "phpunit/phpunit": "~4.0" 28 | }, 29 | "autoload": { 30 | "classmap": [ 31 | "/src" 32 | ] 33 | }, 34 | "minimum-stability": "stable" 35 | } 36 | -------------------------------------------------------------------------------- /src/Resources/Tools.php: -------------------------------------------------------------------------------- 1 | execute_get_request( 25 | $this->get_request_url( "tax_id_validation" ).$this->array_to_params( 26 | array( 27 | "tax_id" => $tax_id 28 | ) 29 | ) 30 | ) 31 | ); 32 | } catch ( Facturapi_Exception $e ) { 33 | throw new Facturapi_Exception( 'Failed to validate tax id: ' .$e->getMessage() ); 34 | } 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Facturapi 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 | -------------------------------------------------------------------------------- /src/Resources/Catalogs.php: -------------------------------------------------------------------------------- 1 | execute_get_request( 26 | $this->get_request_url("products") . $this->array_to_params($params) 27 | ) 28 | ); 29 | } catch (Facturapi_Exception $e) { 30 | throw new Facturapi_Exception('Unable to search products: ' . $e->getMessage()); 31 | } 32 | } 33 | 34 | /** 35 | * Search a unit key in SAT's catalog 36 | * 37 | * @param $params Search parameters 38 | * 39 | * @return JSON search result 40 | * 41 | * @throws Facturapi_Exception 42 | **/ 43 | public function searchUnits($params = null) 44 | { 45 | try { 46 | return json_decode( 47 | $this->execute_get_request( 48 | $this->get_request_url("units") . $this->array_to_params($params) 49 | ) 50 | ); 51 | } catch (Facturapi_Exception $e) { 52 | throw new Facturapi_Exception('Unable to search unit keys: ' . $e->getMessage()); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Facturapi.php: -------------------------------------------------------------------------------- 1 | Customers = new Customers($api_key, $api_version); 50 | $this->Organizations = new Organizations($api_key, $api_version); 51 | $this->Products = new Products($api_key, $api_version); 52 | $this->Invoices = new Invoices($api_key, $api_version); 53 | $this->Receipts = new Receipts($api_key, $api_version); 54 | $this->Catalogs = new Catalogs($api_key, $api_version); 55 | $this->CartaPorteCatalogs = new CartaPorteCatalogs($api_key, $api_version); 56 | $this->Retentions = new Retentions($api_key, $api_version); 57 | $this->Tools = new Tools($api_key, $api_version); 58 | $this->Webhooks = new Webhooks($api_key, $api_version); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /example.php: -------------------------------------------------------------------------------- 1 | Invoices->retrieve( "5a3f54cff508333611ad6b40" ) ); 12 | 13 | $invoice = array( 14 | "type" => \Facturapi\InvoiceType::EGRESO, 15 | "customer" => "5a3ff03bf508333611ad6b44", 16 | "items" => array( 17 | array( 18 | "quantity" => 1, 19 | "product" => "5a3f4890f508333611ad6b3f" 20 | ), 21 | array( 22 | "quantity" => 2, 23 | "product" => array( 24 | "description" => "Guitarra", 25 | "product_key" => "01234567", 26 | "price" => 420.69, 27 | "sku" => "ABC4567" 28 | ) 29 | ) 30 | ), 31 | "payment_form" => \Facturapi\PaymentForm::EFECTIVO, 32 | "relation" => \Facturapi\InvoiceRelation::DEVOLUCION, 33 | "related" => [ 'UUID_de_factura_relacionada' ], 34 | "folio_number" => "581", 35 | "series" => "F" 36 | ); 37 | 38 | var_dump( $facturapi->Invoices->create( $invoice ) ); 39 | 40 | var_dump( $facturapi->Invoices->retrieve( "59914af9b1bece552fcaaafd" ) ); 41 | 42 | var_dump( $facturapi->Invoices->all() ); 43 | 44 | 45 | var_dump( $facturapi->Products->all() ); 46 | 47 | $product = array( 48 | "description" => "Hukulele", 49 | "product_key" => "60131303", 50 | "price" => 345.60, 51 | "sku" => "ABC1234" 52 | ); 53 | 54 | var_dump( $facturapi->Products->create( $product ) ); 55 | 56 | $product = array( 57 | "description" => "Guitarra" 58 | ); 59 | 60 | $updated_product = $facturapi->Products->update( "5a3f3e35f508333611ad6b3e", $product ); 61 | var_dump( $updated_product ); 62 | 63 | $facturapi->Products->delete( "5a3f3e35f508333611ad6b3e" ); 64 | 65 | var_dump( $facturapi->Customers->all() ); 66 | 67 | 68 | var_dump( $facturapi->Customers->retrieve( "5a3ee743f508333611ad6b3c" ) ); 69 | 70 | 71 | $customer = array( 72 | "email" => "test@test.com", 73 | "legal_name" => "Testa Mesta", 74 | "tax_id" => "RFC", 75 | "address" => array( 76 | "zip" => "44940", 77 | "street" => "Sunset Blvd" 78 | ) 79 | ); 80 | 81 | $new_customer = $facturapi->Customers->create( $customer ); 82 | var_dump( $new_customer ); 83 | 84 | 85 | $customer = array( 86 | "email" => "testa@mestapapa.com", 87 | "legal_name" => "Testa Mesta Papa", 88 | ); 89 | 90 | $updated_customer = $facturapi->Customers->update( "5a3ee743f508333611ad6b3c", $customer ); 91 | var_dump( $updated_customer ); 92 | 93 | 94 | $facturapi->Customers->delete( "5a3fefd9f508333611ad6b43" ); 95 | -------------------------------------------------------------------------------- /src/Resources/Products.php: -------------------------------------------------------------------------------- 1 | execute_get_request( $this->get_request_url( $params ) ) ); 24 | } catch ( Facturapi_Exception $e ) { 25 | throw new Facturapi_Exception( 'Unable to get products: ' . $e->getMessage() ); 26 | } 27 | } 28 | 29 | /** 30 | * Get a Product by ID 31 | * 32 | * @param id : Unique ID for Product 33 | * 34 | * @return JSON object for requested Product 35 | * 36 | * @throws Facturapi_Exception 37 | **/ 38 | public function retrieve( $id ) { 39 | try { 40 | return json_decode( $this->execute_get_request( $this->get_request_url( $id ) ) ); 41 | } catch ( Facturapi_Exception $e ) { 42 | throw new Facturapi_Exception( 'Unable to get product: ' . $e->getMessage() ); 43 | } 44 | } 45 | 46 | /** 47 | * Create a Product in your organization 48 | * 49 | * @param params : array of properties and property values for new Product 50 | * 51 | * @return Response body with JSON object 52 | * for created Product from HTTP POST request 53 | * 54 | * @throws Facturapi_Exception 55 | **/ 56 | public function create( $params ) { 57 | try { 58 | return json_decode( $this->execute_JSON_post_request( $this->get_request_url(), $params ) ); 59 | } catch ( Facturapi_Exception $e ) { 60 | throw new Facturapi_Exception( 'Unable to create product: ' . $e->getMessage() ); 61 | } 62 | } 63 | 64 | 65 | /** 66 | * Update a Product in your organization 67 | * 68 | * @param $id 69 | * @param $params array of properties and property values for Product 70 | * 71 | * @return Response body from HTTP POST request 72 | * 73 | * @throws Facturapi_Exception 74 | * 75 | */ 76 | public function update( $id, $params ) { 77 | try { 78 | return json_decode( $this->execute_JSON_put_request( $this->get_request_url( $id ), $params ) ); 79 | } catch ( Facturapi_Exception $e ) { 80 | throw new Facturapi_Exception( 'Unable to update product: ' . $e->getMessage() ); 81 | } 82 | } 83 | 84 | /** 85 | * Delete a Product in your organization 86 | * 87 | * @param id : Unique ID for the Product 88 | * 89 | * @return Response body from HTTP POST request 90 | * 91 | * @throws Facturapi_Exception 92 | **/ 93 | public function delete( $id ) { 94 | try { 95 | return json_decode( $this->execute_delete_request( $this->get_request_url( $id ), null ) ); 96 | } catch ( Facturapi_Exception $e ) { 97 | throw new Facturapi_Exception( 'Unable to delete product: ' . $e->getMessage() ); 98 | } 99 | } 100 | 101 | } -------------------------------------------------------------------------------- /src/Resources/Webhooks.php: -------------------------------------------------------------------------------- 1 | execute_get_request($this->get_request_url($params))); 25 | } catch (Facturapi_Exception $e) { 26 | throw new Facturapi_Exception('Unable to get webhooks: ' . $e->getMessage()); 27 | } 28 | } 29 | 30 | /** 31 | * Get a Webhook by ID 32 | * 33 | * @param id : Unique ID for webhook 34 | * 35 | * @return JSON object for requested Webhook 36 | * 37 | * @throws Facturapi_Exception 38 | **/ 39 | public function retrieve($id) 40 | { 41 | try { 42 | return json_decode($this->execute_get_request($this->get_request_url($id))); 43 | } catch (Facturapi_Exception $e) { 44 | throw new Facturapi_Exception('Unable to get webhook: ' . $e->getMessage()); 45 | } 46 | } 47 | 48 | /** 49 | * Create a Webhook in your organization 50 | * 51 | * @param params : array of properties and property values for new webhook 52 | * 53 | * @return Response body with JSON object 54 | * for created Webhook from HTTP POST request 55 | * 56 | * @throws Facturapi_Exception 57 | **/ 58 | public function create($params) 59 | { 60 | try { 61 | return json_decode($this->execute_JSON_post_request($this->get_request_url(), $params)); 62 | } catch (Facturapi_Exception $e) { 63 | throw new Facturapi_Exception('Unable to create webhook: ' . $e->getMessage()); 64 | } 65 | } 66 | 67 | 68 | /** 69 | * Update a Webhook in your organization 70 | * 71 | * @param $id 72 | * @param $params array of properties and property values for webhook 73 | * 74 | * @return Response body from HTTP POST request 75 | * 76 | * @throws Facturapi_Exception 77 | * 78 | */ 79 | public function update($id, $params) 80 | { 81 | try { 82 | return json_decode($this->execute_JSON_put_request($this->get_request_url($id), $params)); 83 | } catch (Facturapi_Exception $e) { 84 | throw new Facturapi_Exception('Unable to update webhook: ' . $e->getMessage()); 85 | } 86 | } 87 | 88 | /** 89 | * Delete a Webhook in your organization 90 | * 91 | * @param id : Unique ID for the webhook 92 | * 93 | * @return Response body from HTTP POST request 94 | * 95 | * @throws Facturapi_Exception 96 | **/ 97 | public function delete($id) 98 | { 99 | try { 100 | return json_decode($this->execute_delete_request($this->get_request_url($id), null)); 101 | } catch (Facturapi_Exception $e) { 102 | throw new Facturapi_Exception('Unable to delete webhook: ' . $e->getMessage()); 103 | } 104 | } 105 | 106 | /** 107 | * Validate the response of webhook with the secret and facturapi-secret 108 | * @param data: Array of properties according to the signature body [$secret, $facturapi-secret, $payload] 109 | * @return Response Webhook object 110 | */ 111 | public function validateSignature($data) 112 | { 113 | try { 114 | return json_decode($this->execute_JSON_post_request($this->get_request_url() . '/validate-signature', $data)); 115 | } catch (Facturapi_Exception $e) { 116 | throw new Facturapi_Exception($e); 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/Resources/Customers.php: -------------------------------------------------------------------------------- 1 | execute_get_request( $this->get_request_url( $params ) ) ); 23 | } catch ( Facturapi_Exception $e ) { 24 | throw new Facturapi_Exception( 'Unable to get customers: ' . $e->getMessage() ); 25 | } 26 | } 27 | 28 | /** 29 | * Get a Customer by ID 30 | * 31 | * @param string $id : Unique ID for customer 32 | * 33 | * @return JSON object for requested Customer 34 | * 35 | * @throws Facturapi_Exception 36 | **/ 37 | public function retrieve( $id ) { 38 | try { 39 | return json_decode( $this->execute_get_request( $this->get_request_url( $id ) ) ); 40 | } catch ( Facturapi_Exception $e ) { 41 | throw new Facturapi_Exception( 'Unable to get customer: ' . $e->getMessage() ); 42 | } 43 | } 44 | 45 | /** 46 | * Create a Customer in your organization 47 | * 48 | * @param $data : array of properties and property values for new customer 49 | * @param $params : array of optional query parameters 50 | * 51 | * @return Response body with JSON object 52 | * for created Customer from HTTP POST request 53 | * 54 | * @throws Facturapi_Exception 55 | **/ 56 | public function create( $data, $params = null ) { 57 | try { 58 | return json_decode( $this->execute_JSON_post_request( $this->get_request_url($params), $data ) ); 59 | } catch ( Facturapi_Exception $e ) { 60 | throw new Facturapi_Exception( 'Unable to create customer: ' . $e->getMessage() ); 61 | } 62 | } 63 | 64 | 65 | /** 66 | * Update a Customer in your organization 67 | * 68 | * @param string $id 69 | * @param $data Array of properties and property values for customer 70 | * @param $params Array of optional query parameters 71 | * 72 | * @return Response body from HTTP POST request 73 | * 74 | * @throws Facturapi_Exception 75 | * 76 | */ 77 | public function update( $id, $data, $params = null ) { 78 | try { 79 | return json_decode( $this->execute_JSON_put_request( $this->get_request_url( $id, $params ), $data ) ); 80 | } catch ( Facturapi_Exception $e ) { 81 | throw new Facturapi_Exception( 'Unable to update customer: ' . $e->getMessage() ); 82 | } 83 | } 84 | 85 | /** 86 | * Delete a Customer in your organization 87 | * 88 | * @param string $id : Unique ID for the customer 89 | * 90 | * @return Response body from HTTP POST request 91 | * 92 | * @throws Facturapi_Exception 93 | **/ 94 | public function delete( $id ) { 95 | try { 96 | return json_decode( $this->execute_delete_request( $this->get_request_url( $id ), null ) ); 97 | } catch ( Facturapi_Exception $e ) { 98 | throw new Facturapi_Exception( 'Unable to delete customer: ' . $e->getMessage() ); 99 | } 100 | } 101 | 102 | /** 103 | * Validates that a Customer's tax info is still valid 104 | * 105 | * @param string $id : Unique ID for the customer 106 | * @return Response body from HTTP POST request 107 | * 108 | * @throws Facturapi_Exception 109 | **/ 110 | public function validateTaxInfo( $id ) { 111 | try { 112 | return json_decode( $this->execute_get_request( $this->get_request_url( $id ) . "/tax-info-validation" ) ); 113 | } catch ( Facturapi_Exception $e ) { 114 | throw new Facturapi_Exception( 'Unable to validate customer\'s tax info: ' . $e->getMessage() ); 115 | } 116 | } 117 | 118 | } -------------------------------------------------------------------------------- /src/Resources/Retentions.php: -------------------------------------------------------------------------------- 1 | execute_get_request( $this->get_request_url( $params ) ) ); 24 | } catch ( Facturapi_Exception $e ) { 25 | throw new Facturapi_Exception( 'Unable to get Retentions: ' . $e->getMessage() ); 26 | } 27 | } 28 | 29 | /** 30 | * Get a Retention by ID 31 | * 32 | * @param id : Retention ID 33 | * 34 | * @return JSON Retention object 35 | * 36 | * @throws Facturapi_Exception 37 | **/ 38 | public function retrieve( $id ) { 39 | try { 40 | return json_decode( $this->execute_get_request( $this->get_request_url( $id ) ) ); 41 | } catch ( Facturapi_Exception $e ) { 42 | throw new Facturapi_Exception( 'Unable to get Retention: ' . $e->getMessage() ); 43 | } 44 | } 45 | 46 | /** 47 | * Creates a Retention for the organization 48 | * 49 | * @param params : array of properties and property values for new Retention 50 | * 51 | * @return Response body with JSON object with created Retention 52 | * 53 | * @throws Facturapi_Exception 54 | **/ 55 | public function create( $params ) { 56 | try { 57 | return json_decode( $this->execute_JSON_post_request( $this->get_request_url(), $params ) ); 58 | } catch ( Facturapi_Exception $e ) { 59 | throw new Facturapi_Exception( 'Unable to create Retention: ' . $e->getMessage() ); 60 | } 61 | } 62 | 63 | 64 | /** 65 | * Cancels a Retention 66 | * 67 | * @param id : Retention ID 68 | * 69 | * @return Response Updated Retention object 70 | * 71 | * @throws Facturapi_Exception 72 | **/ 73 | public function cancel( $id ) { 74 | try { 75 | return json_decode( $this->execute_delete_request( $this->get_request_url( $id ), null ) ); 76 | } catch ( Facturapi_Exception $e ) { 77 | throw new Facturapi_Exception( 'Unable to cancel Retention: ' . $e->getMessage() ); 78 | } 79 | } 80 | 81 | /** 82 | * Sends the retention to the customer's email 83 | * 84 | * @param id : Retention ID 85 | * 86 | * @param email : String or array of strings with email address(es) 87 | * 88 | * @return JSON Result object 89 | * 90 | * @throws Facturapi_Exception 91 | **/ 92 | public function send_by_email( $id, $email = null ) { 93 | try { 94 | return json_decode( $this->execute_JSON_post_request( 95 | $this->get_request_url($id) . "/email", 96 | array("email" => $email) 97 | )); 98 | } catch ( Facturapi_Exception $e ) { 99 | throw new Facturapi_Exception( 'Unable to send Retention: ' . $e->getMessage() ); 100 | } 101 | } 102 | 103 | /** 104 | * Downloads the specified Retention in a ZIP package containing both PDF and XML files 105 | * 106 | * @param id : Retention ID 107 | * 108 | * @return ZIP file in a stream 109 | * 110 | * @throws Facturapi_Exception 111 | **/ 112 | public function download_zip( $id ) { 113 | try { 114 | return $this->execute_get_request( $this->get_request_url( $id ) . "/zip" ); 115 | } catch ( Facturapi_Exception $e ) { 116 | throw new Facturapi_Exception( 'Unable to download ZIP file: ' . $e->getMessage() ); 117 | } 118 | } 119 | 120 | /** 121 | * Downloads the specified Retention in a PDF file 122 | * 123 | * @param id : Retention ID 124 | * 125 | * @return PDF file in a stream 126 | * 127 | * @throws Facturapi_Exception 128 | **/ 129 | public function download_pdf( $id ) { 130 | try { 131 | return $this->execute_get_request( $this->get_request_url( $id ) . "/pdf" ); 132 | } catch ( Facturapi_Exception $e ) { 133 | throw new Facturapi_Exception( 'Unable to download PDF file: ' . $e->getMessage() ); 134 | } 135 | } 136 | 137 | /** 138 | * Downloads the specified Retention in a XML file 139 | * 140 | * @param id : Retention ID 141 | * 142 | * @return XML file in a stream 143 | * 144 | * @throws Facturapi_Exception 145 | **/ 146 | public function download_xml( $id ) { 147 | try { 148 | return $this->execute_get_request( $this->get_request_url( $id ) . "/xml" ); 149 | } catch ( Facturapi_Exception $e ) { 150 | throw new Facturapi_Exception( 'Unable to download XML file: ' . $e->getMessage() ); 151 | } 152 | } 153 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Facturapi PHP Library 2 | ========= 3 | 4 | This is the official PHP wrapper for https://www.facturapi.io 5 | 6 | FacturAPI makes it easy for developers to generate valid Invoices in Mexico (known as Factura Electrónica or CFDI). 7 | 8 | If you've ever used [Stripe](https://stripe.com) or [Conekta](https://conekta.io), you'll find FacturAPI very straightforward to understand and integrate in your server app. 9 | 10 | ## Install 11 | 12 | ```bash 13 | composer require "facturapi/facturapi-php" 14 | ``` 15 | 16 | ## Before you begin 17 | 18 | Make sure you have created your free account on [FacturAPI](https://www.facturapi.io) and that you have your **API Keys**. 19 | 20 | ## Getting started 21 | 22 | ### Import the library 23 | 24 | Don't forget to reference the library at the top of your code: 25 | 26 | ```php 27 | use Facturapi\Facturapi; 28 | ``` 29 | 30 | ### Create a customer 31 | 32 | ```php 33 | 34 | // Create an instance of the client. 35 | // You can use different instances for uusing different API Keys 36 | $facturapi = new Facturapi( FACTURAPI_KEY ); 37 | 38 | $customer = array( 39 | "email" => "walterwhite@gmail.com", //Optional but useful to send invoice by email 40 | "legal_name" => "Walter White", // Razón social 41 | "tax_id" => "WIWA761018", //RFC 42 | "address" => array( 43 | "zip"=> "06800", 44 | "street" => "Av. de los Rosales", 45 | "exterior" => "123", 46 | "neighborhood" => "Tepito" 47 | // city, municipality and state are filled automatically from the zip code 48 | // but if you want to, you can override their values 49 | // city: 'México', 50 | // municipality: 'Cuauhtémoc', 51 | // state: 'Ciudad de México' 52 | ) 53 | ); 54 | 55 | // Remember to store the customer.id in your records. 56 | // You will need it to create an invoice for this customer. 57 | $new_customer = $facturapi->Customers->create($customer); 58 | ``` 59 | 60 | ### Create a product 61 | 62 | ```php 63 | $facturapi = new Facturapi( FACTURAPI_KEY ); 64 | $product = array( 65 | "product_key" => "4319150114", // Clave Producto/Servicio from SAT's catalog. Log in to FacturAPI and use our tool to look it up. 66 | "description" => "Apple iPhone 8", 67 | "price" => 345.60 // price in MXN. 68 | // By default, taxes are calculated from the price with IVA 16% 69 | // But again, you can override that by explicitly providing a taxes array 70 | // "taxes" => array( 71 | // array ( "type" => \Facturapi\TaxType::IVA, "rate" => 0.16 ), 72 | // array ( "type" => \Facturapi\TaxType::ISR, "rate" => 0.03666, "withholding" => true ) 73 | // ) 74 | ); 75 | 76 | $facturapi->Products->create( $product ); 77 | ``` 78 | 79 | ### Create an invoice 80 | 81 | ```php 82 | $facturapi = new Facturapi( FACTURAPI_KEY ); 83 | 84 | $invoice = array( 85 | "customer" => "YOUR_CUSTOMER_ID", 86 | "items" => array( 87 | array( 88 | "quantity" => 1, // Optional. Defaults to 1. 89 | "product" => "YOUR_PRODUCT_ID" // You can also pass a product object instead 90 | ), 91 | array( 92 | "quantity" => 2, 93 | "product" => array( 94 | "description" => "Guitarra", 95 | "product_key" => "01234567", 96 | "price" => 420.69, 97 | "sku" => "ABC4567" 98 | ) 99 | ) // Add as many products as you want to include in your invoice 100 | ), 101 | "payment_form" => \Facturapi\PaymentForm::EFECTIVO, 102 | "folio_number" => "581", 103 | "series" => "F" 104 | ); 105 | 106 | $facturapi->Invoices->create( $invoice ); 107 | ``` 108 | 109 | #### Download your invoice 110 | 111 | ```php 112 | // Once you have successfully created your invoice, you can... 113 | $facturapi = new Facturapi( FACTURAPI_KEY ); 114 | 115 | $facturapi->Invoices->download_zip("INVOICE_ID") // stream containing the PDF and XML as a ZIP file or 116 | 117 | $facturapi->Invoices->download_pdf("INVOICE_ID") // stream containing the PDF file or 118 | 119 | $facturapi->Invoices->download_xml("INVOICE_ID") // stream containing the XML file or 120 | ``` 121 | 122 | #### Send your invoice by email 123 | 124 | ```php 125 | // Send the invoice to your customer's email (if any) 126 | $facturapi = new Facturapi( FACTURAPI_KEY ); 127 | 128 | $facturapi->Invoices->send_by_email("INVOICE_ID"); 129 | ``` 130 | 131 | ## Documentation 132 | 133 | There's more you can do with this library: List, retrieve, update, and remove Customers, Products and Invoices. 134 | 135 | Visit the full documentation at http://docs.facturapi.io. 136 | 137 | ## Help 138 | 139 | ### Found a bug? 140 | 141 | Please report it on the Issue Tracker 142 | 143 | ### Want to contribute? 144 | 145 | Send us your PR! We appreciate your help :) 146 | 147 | ### Contact us! 148 | 149 | contacto@facturapi.io -------------------------------------------------------------------------------- /src/Resources/Receipts.php: -------------------------------------------------------------------------------- 1 | execute_get_request( $this->get_request_url( $params ) ) ); 24 | } catch ( Facturapi_Exception $e ) { 25 | throw new Facturapi_Exception( 'Unable to get receipts: ' . $e->getMessage() ); 26 | } 27 | } 28 | 29 | /** 30 | * Get a Receipt by ID 31 | * 32 | * @param id : Unique ID for Receipt 33 | * 34 | * @return JSON object for requested Receipt 35 | * 36 | * @throws Facturapi_Exception 37 | **/ 38 | public function retrieve( $id ) { 39 | try { 40 | return json_decode( $this->execute_get_request( $this->get_request_url( $id ) ) ); 41 | } catch ( Facturapi_Exception $e ) { 42 | throw new Facturapi_Exception( 'Unable to get receipt: ' . $e->getMessage() ); 43 | } 44 | } 45 | 46 | /** 47 | * Create a Receipt in your organization 48 | * 49 | * @param params : array of properties and property values for new Receipt 50 | * 51 | * @return Response The Receipt object we just created 52 | * 53 | * @throws Facturapi_Exception 54 | **/ 55 | public function create( $params ) { 56 | try { 57 | return json_decode( $this->execute_JSON_post_request( $this->get_request_url(), $params ) ); 58 | } catch ( Facturapi_Exception $e ) { 59 | throw new Facturapi_Exception( 'Unable to create receipt: ' . $e->getMessage() ); 60 | } 61 | } 62 | 63 | 64 | /** 65 | * Creates an invoice for a Receipt 66 | * 67 | * @param $id Receipt Id 68 | * @param $params Array of properties and property values for invoicing a receipt 69 | * 70 | * @return Response The Invoice object of the invoice we just created 71 | * 72 | * @throws Facturapi_Exception 73 | * 74 | */ 75 | public function invoice( $id, $params ) { 76 | try { 77 | return json_decode( $this->execute_JSON_post_request( $this->get_request_url( $id ) . "/invoice", $params ) ); 78 | } catch ( Facturapi_Exception $e ) { 79 | throw new Facturapi_Exception( 'Unable to invoice receipt: ' . $e->getMessage() ); 80 | } 81 | } 82 | 83 | /** 84 | * Creates a global invoice from the open receipts in the last completed period 85 | * 86 | * @param $params Array of properties and property values for creating a global invoice 87 | * 88 | * @return Response the Invoice object of the global invoice we just created 89 | * 90 | * @throws Facturapi_Exception 91 | * 92 | */ 93 | public function createGlobalInvoice( $params ) { 94 | try { 95 | return json_decode( $this->execute_JSON_post_request( $this->get_request_url() . "/global-invoice", $params ) ); 96 | } catch ( Facturapi_Exception $e ) { 97 | throw new Facturapi_Exception( 'Unable to create global invoice: ' . $e->getMessage() ); 98 | } 99 | } 100 | 101 | /** 102 | * Cancel a Receipt 103 | * 104 | * @param $id : Unique ID for the Receipt 105 | * 106 | * @return Response the Receipt object 107 | * 108 | * @throws Facturapi_Exception 109 | **/ 110 | public function cancel( $id ) { 111 | try { 112 | return json_decode( $this->execute_delete_request( $this->get_request_url( $id ), null ) ); 113 | } catch ( Facturapi_Exception $e ) { 114 | throw new Facturapi_Exception( 'Unable to cancel receipt: ' . $e->getMessage() ); 115 | } 116 | } 117 | 118 | /** 119 | * Sends the receipt to the customer's email 120 | * 121 | * @param id : Unique ID for Receipt 122 | * 123 | * @return JSON object for requested Receipt 124 | * 125 | * @throws Facturapi_Exception 126 | **/ 127 | public function send_by_email( $id, $email = null ) { 128 | try { 129 | return json_decode( $this->execute_JSON_post_request( 130 | $this->get_request_url($id) . "/email", 131 | $email == null ? null : array("email" => $email) 132 | )); 133 | } catch ( Facturapi_Exception $e ) { 134 | throw new Facturapi_Exception( 'Unable to send Receipt: ' . $e->getMessage() ); 135 | } 136 | } 137 | 138 | /** 139 | * Downloads the specified receipt in a PDF file 140 | * 141 | * @param id : Unique ID for Receipt 142 | * 143 | * @return PDF file in a stream 144 | * 145 | * @throws Facturapi_Exception 146 | **/ 147 | public function download_pdf( $id ) { 148 | try { 149 | return $this->execute_get_request( $this->get_request_url( $id ) . "/pdf" ); 150 | } catch ( Facturapi_Exception $e ) { 151 | throw new Facturapi_Exception( 'Unable to download PDF file: ' . $e->getMessage() ); 152 | } 153 | } 154 | } -------------------------------------------------------------------------------- /src/Resources/CartaPorteCatalogs.php: -------------------------------------------------------------------------------- 1 | execute_get_request( 23 | $this->get_request_url("air-transport-codes") . $this->array_to_params($params) 24 | ) 25 | ); 26 | } catch (Facturapi_Exception $e) { 27 | throw new Facturapi_Exception('Unable to search air transport codes: ' . $e->getMessage()); 28 | } 29 | } 30 | 31 | /** 32 | * Auto transport configurations (Carta Porte 3.1) 33 | */ 34 | public function searchTransportConfigs($params = null) 35 | { 36 | try { 37 | return json_decode( 38 | $this->execute_get_request( 39 | $this->get_request_url("transport-configs") . $this->array_to_params($params) 40 | ) 41 | ); 42 | } catch (Facturapi_Exception $e) { 43 | throw new Facturapi_Exception('Unable to search transport configurations: ' . $e->getMessage()); 44 | } 45 | } 46 | 47 | /** 48 | * Rights of passage (Carta Porte 3.1) 49 | */ 50 | public function searchRightsOfPassage($params = null) 51 | { 52 | try { 53 | return json_decode( 54 | $this->execute_get_request( 55 | $this->get_request_url("rights-of-passage") . $this->array_to_params($params) 56 | ) 57 | ); 58 | } catch (Facturapi_Exception $e) { 59 | throw new Facturapi_Exception('Unable to search rights of passage: ' . $e->getMessage()); 60 | } 61 | } 62 | 63 | /** 64 | * Customs documents (Carta Porte 3.1) 65 | */ 66 | public function searchCustomsDocuments($params = null) 67 | { 68 | try { 69 | return json_decode( 70 | $this->execute_get_request( 71 | $this->get_request_url("customs-documents") . $this->array_to_params($params) 72 | ) 73 | ); 74 | } catch (Facturapi_Exception $e) { 75 | throw new Facturapi_Exception('Unable to search customs documents: ' . $e->getMessage()); 76 | } 77 | } 78 | 79 | /** 80 | * Packaging types (Carta Porte 3.1) 81 | */ 82 | public function searchPackagingTypes($params = null) 83 | { 84 | try { 85 | return json_decode( 86 | $this->execute_get_request( 87 | $this->get_request_url("packaging-types") . $this->array_to_params($params) 88 | ) 89 | ); 90 | } catch (Facturapi_Exception $e) { 91 | throw new Facturapi_Exception('Unable to search packaging types: ' . $e->getMessage()); 92 | } 93 | } 94 | 95 | /** 96 | * Trailer types (Carta Porte 3.1) 97 | */ 98 | public function searchTrailerTypes($params = null) 99 | { 100 | try { 101 | return json_decode( 102 | $this->execute_get_request( 103 | $this->get_request_url("trailer-types") . $this->array_to_params($params) 104 | ) 105 | ); 106 | } catch (Facturapi_Exception $e) { 107 | throw new Facturapi_Exception('Unable to search trailer types: ' . $e->getMessage()); 108 | } 109 | } 110 | 111 | /** 112 | * Hazardous materials (Carta Porte 3.1) 113 | */ 114 | public function searchHazardousMaterials($params = null) 115 | { 116 | try { 117 | return json_decode( 118 | $this->execute_get_request( 119 | $this->get_request_url("hazardous-materials") . $this->array_to_params($params) 120 | ) 121 | ); 122 | } catch (Facturapi_Exception $e) { 123 | throw new Facturapi_Exception('Unable to search hazardous materials: ' . $e->getMessage()); 124 | } 125 | } 126 | 127 | /** 128 | * Naval authorizations (Carta Porte 3.1) 129 | */ 130 | public function searchNavalAuthorizations($params = null) 131 | { 132 | try { 133 | return json_decode( 134 | $this->execute_get_request( 135 | $this->get_request_url("naval-authorizations") . $this->array_to_params($params) 136 | ) 137 | ); 138 | } catch (Facturapi_Exception $e) { 139 | throw new Facturapi_Exception('Unable to search naval authorizations: ' . $e->getMessage()); 140 | } 141 | } 142 | 143 | /** 144 | * Port stations (air/sea/land) (Carta Porte 3.1) 145 | */ 146 | public function searchPortStations($params = null) 147 | { 148 | try { 149 | return json_decode( 150 | $this->execute_get_request( 151 | $this->get_request_url("port-stations") . $this->array_to_params($params) 152 | ) 153 | ); 154 | } catch (Facturapi_Exception $e) { 155 | throw new Facturapi_Exception('Unable to search port stations: ' . $e->getMessage()); 156 | } 157 | } 158 | 159 | /** 160 | * Marine containers (Carta Porte 3.1) 161 | */ 162 | public function searchMarineContainers($params = null) 163 | { 164 | try { 165 | return json_decode( 166 | $this->execute_get_request( 167 | $this->get_request_url("marine-containers") . $this->array_to_params($params) 168 | ) 169 | ); 170 | } catch (Facturapi_Exception $e) { 171 | throw new Facturapi_Exception('Unable to search marine containers: ' . $e->getMessage()); 172 | } 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /src/Resources/Invoices.php: -------------------------------------------------------------------------------- 1 | execute_get_request( $this->get_request_url( $query ) ) ); 21 | } catch ( Facturapi_Exception $e ) { 22 | throw new Facturapi_Exception( 'Unable to get Invoices: ' . $e->getMessage() ); 23 | } 24 | } 25 | 26 | /** 27 | * Get an Invoice by ID 28 | * @param id : Unique ID for Invoice 29 | * @return JSON object for requested Invoice 30 | * @throws Facturapi_Exception 31 | **/ 32 | public function retrieve( $id ) { 33 | try { 34 | return json_decode( $this->execute_get_request( $this->get_request_url( $id ) ) ); 35 | } catch ( Facturapi_Exception $e ) { 36 | throw new Facturapi_Exception( 'Unable to get Invoice: ' . $e->getMessage()); 37 | } 38 | } 39 | 40 | /** 41 | * Create an Invoice in your organization 42 | * 43 | * @param body : array of properties and property values for new Invoice 44 | * @param query : array of query parameters 45 | * @return Response body with JSON object 46 | * for created Invoice from HTTP POST request 47 | * @throws Facturapi_Exception 48 | **/ 49 | public function create( $body, $query = null) { 50 | try { 51 | return json_decode( $this->execute_JSON_post_request( $this->get_request_url($query), $body) ); 52 | } catch ( Facturapi_Exception $e ) { 53 | throw new Facturapi_Exception( 'Unable to create Invoice: ' . $e->getMessage()); 54 | } 55 | } 56 | 57 | 58 | /** 59 | * Cancel an Invoice in your organization 60 | * @param id : Unique ID for the Invoice 61 | * @param query URL query params 62 | * @return Response body from HTTP POST request 63 | * @throws Facturapi_Exception 64 | **/ 65 | public function cancel( $id, $query ) { 66 | try { 67 | return json_decode( $this->execute_delete_request( $this->get_request_url( $id, $query ), null ) ); 68 | } catch ( Facturapi_Exception $e ) { 69 | throw new Facturapi_Exception( 'Unable to cancel Invoice: ' . $e->getMessage()); 70 | } 71 | } 72 | 73 | /** 74 | * Sends the invoice to the customer's email 75 | * @param id : Unique ID for Invoice 76 | * @return JSON object for requested Invoice 77 | * @throws Facturapi_Exception 78 | **/ 79 | public function send_by_email( $id, $email = null ) { 80 | try { 81 | return json_decode( $this->execute_JSON_post_request( 82 | $this->get_request_url($id) . "/email", 83 | array("email" => $email) 84 | )); 85 | } catch ( Facturapi_Exception $e ) { 86 | throw new Facturapi_Exception( 'Unable to send Invoice: ' . $e->getMessage()); 87 | } 88 | } 89 | 90 | /** 91 | * Downloads the specified invoice in a ZIP package containing both PDF and XML files 92 | * @param id : Unique ID for Invoice 93 | * @return ZIP file in a stream 94 | * @throws Facturapi_Exception 95 | **/ 96 | public function download_zip( $id ) { 97 | try { 98 | return $this->execute_get_request( $this->get_request_url( $id ) . "/zip" ); 99 | } catch ( Facturapi_Exception $e ) { 100 | throw new Facturapi_Exception( 'Unable to download ZIP file: ' . $e->getMessage()); 101 | } 102 | } 103 | 104 | /** 105 | * Downloads the specified invoice in a PDF file 106 | * @param id : Unique ID for Invoice 107 | * @return PDF file in a stream 108 | * @throws Facturapi_Exception 109 | **/ 110 | public function download_pdf( $id ) { 111 | try { 112 | return $this->execute_get_request( $this->get_request_url( $id ) . "/pdf" ); 113 | } catch ( Facturapi_Exception $e ) { 114 | throw new Facturapi_Exception( 'Unable to download PDF file: ' . $e->getMessage()); 115 | } 116 | } 117 | 118 | /** 119 | * Downloads the specified invoice in a XML file 120 | * @param id : Unique ID for Invoice 121 | * @return XML file in a stream 122 | * @throws Facturapi_Exception 123 | **/ 124 | public function download_xml( $id ) { 125 | try { 126 | return $this->execute_get_request( $this->get_request_url( $id ) . "/xml" ); 127 | } catch ( Facturapi_Exception $e ) { 128 | throw new Facturapi_Exception( 'Unable to download XML file: ' . $e->getMessage()); 129 | } 130 | } 131 | 132 | /** 133 | * Downloads the cancellation receipt of a canceled invoice in XML format 134 | * @param id : Unique ID for Invoice 135 | * @return XML file in a stream 136 | * @throws Facturapi_Exception 137 | **/ 138 | public function download_cancellation_receipt_xml( $id ) { 139 | try { 140 | return $this->execute_get_request( $this->get_request_url( $id . "/cancellation_receipt/xml" ) ); 141 | } catch ( Facturapi_Exception $e ) { 142 | throw new Facturapi_Exception( 'Unable to download cancellation receipt: ' . $e->getMessage()); 143 | } 144 | } 145 | 146 | /** 147 | * Downloads the cancellation receipt of a canceled invoice in PDF format 148 | * 149 | * @param id : Unique ID for Invoice 150 | * 151 | * @return XML file in a stream 152 | * 153 | * @throws Facturapi_Exception 154 | **/ 155 | public function download_cancellation_receipt_pdf( $id ) { 156 | try { 157 | return $this->execute_get_request( $this->get_request_url( $id ) . "/cancellation_receipt/pdf" ); 158 | } catch ( Facturapi_Exception $e ) { 159 | throw new Facturapi_Exception( 'Unable to download cancellation receipt: ' . $e->getMessage()); 160 | } 161 | } 162 | 163 | /** 164 | * Updates the status of an Invoice with the latest information from the SAT. 165 | * In Test mode, this method will simulate a status update to a "canceled" status. 166 | * @param id : Unique ID for Invoice 167 | * @return JSON Updated Invoice object 168 | * @throws Facturapi_Exception 169 | */ 170 | public function update_status( $id ) { 171 | try { 172 | return json_decode( $this->execute_JSON_put_request( $this->get_request_url( $id . "/status" ), null ) ); 173 | } catch ( Facturapi_Exception $e ) { 174 | throw new Facturapi_Exception( 'Unable to update status: ' . $e ); 175 | } 176 | } 177 | 178 | /** 179 | * Updates an Invoice with "draft" status 180 | * 181 | * @param id : Unique ID for Invoice 182 | * @param body : array of properties and property values for the fields to edit 183 | * @return JSON Edited draft Invoice object 184 | * @throws Facturapi_Exception 185 | */ 186 | public function update_draft( $id, $body ) { 187 | try { 188 | return json_decode( $this->execute_JSON_put_request( $this->get_request_url( $id ), $body ) ); 189 | } catch ( Facturapi_Exception $e ) { 190 | throw new Facturapi_Exception( 'Unable to edit draft: ' . $e ); 191 | } 192 | } 193 | 194 | /** 195 | * Stamps a draft invoice 196 | * 197 | * @param id : Unique ID for Invoice 198 | * @param query : URL query params 199 | * @return JSON Stamped Invoice object 200 | * @throws Facturapi_Exception 201 | */ 202 | public function stamp_draft( $id, $query = null ) { 203 | try { 204 | return json_decode( $this->execute_JSON_post_request( $this->get_request_url( $id . "/stamp", $query ) ) ); 205 | } catch ( Facturapi_Exception $e ) { 206 | throw new Facturapi_Exception( 'Unable to stamp draft: ' . $e ); 207 | } 208 | } 209 | 210 | /** 211 | * Creates a new draft Invoice copying the information from the specified Invoice 212 | * @param id : Unique ID for Invoice 213 | * @return JSON Copied draft Invoice object 214 | * @throws Facturapi_Exception 215 | */ 216 | public function copy_to_draft( $id ) { 217 | try { 218 | return json_decode( $this->execute_JSON_post_request( $this->get_request_url( $id . "/copy" ), null ) ); 219 | } catch ( Facturapi_Exception $e ) { 220 | throw new Facturapi_Exception( 'Unable to copy draft: ' . $e ); 221 | } 222 | } 223 | 224 | /** 225 | * Generates a preview of an invoice in PDF format without stamping it or saving it 226 | * @param array $body Array of properties and property values for new Invoice 227 | * @return string PDF file contents 228 | * @throws Facturapi_Exception 229 | **/ 230 | public function preview_pdf( $body ) { 231 | try { 232 | return $this->execute_JSON_post_request( $this->get_request_url( "preview/pdf" ), $body ); 233 | } catch ( Facturapi_Exception $e ) { 234 | throw new Facturapi_Exception( 'Unable to generate PDF preview: ' . $e->getMessage()); 235 | } 236 | } 237 | } -------------------------------------------------------------------------------- /src/Http/BaseClient.php: -------------------------------------------------------------------------------- 1 | FACTURAPI_KEY = base64_encode($FACTURAPI_KEY . ":"); 45 | $this->API_VERSION = $API_VERSION; 46 | } 47 | 48 | /** 49 | * Gets the status code from the most recent curl request 50 | * 51 | * @return integer 52 | */ 53 | public function getLastStatus() 54 | { 55 | return (int) $this->lastStatus; 56 | } 57 | 58 | /** 59 | * Returns ENDPOINT that is set in specific api clients. All 60 | * clients that extend BaseClient should set $ENDPOINT to the 61 | * base path for the API (e.g.: the customers api sets the value to 62 | * 'customers') 63 | * 64 | * @throws Facturapi_Exception 65 | */ 66 | protected function get_endpoint() 67 | { 68 | if (empty($this->ENDPOINT)) { 69 | throw new Facturapi_Exception('ENDPOINT must be defined'); 70 | } else { 71 | return $this->ENDPOINT; 72 | } 73 | } 74 | 75 | /** 76 | * Returns API_VERSION that is set in specific api clients. All 77 | * clients that extend BaseClient should set $API_VERSION to the 78 | * version that the client is developed for (e.g.: the customers v1 79 | * client sets the value to 'v1') 80 | * 81 | * @throws Facturapi_Exception 82 | */ 83 | protected function get_api_version() 84 | { 85 | if (empty($this->API_VERSION)) { 86 | throw new Facturapi_Exception('API_VERSION must be defined'); 87 | } else { 88 | return $this->API_VERSION; 89 | } 90 | } 91 | 92 | /** 93 | * Creates the url to be used for the api request 94 | * 95 | * @param params : Array containing query parameters and values 96 | * 97 | * @returns String 98 | */ 99 | protected function get_request_url($params = null, $query = null) 100 | { 101 | $param_string = $params == null ? "" : ( 102 | is_string($params) 103 | ? ($query == null 104 | ? "/" . $params 105 | : "/" . $params . "/" . $this->array_to_params($query) 106 | ) : $this->array_to_params($params) 107 | ); 108 | 109 | return $this->BASE_URL . $this->get_api_version() . "/" . $this->get_endpoint() . $param_string; 110 | } 111 | 112 | /** 113 | * Executes HTTP GET request 114 | * 115 | * @param URL : String value for the URL to GET 116 | * 117 | * @return String Body of request result 118 | * 119 | * @throws Facturapi_Exception 120 | */ 121 | protected function execute_get_request($url) 122 | { 123 | $headers[] = 'Authorization: Basic ' . $this->FACTURAPI_KEY; 124 | 125 | $ch = curl_init(); 126 | curl_setopt($ch, CURLOPT_URL, $url); 127 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 128 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 129 | curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); 130 | curl_setopt($ch, CURLOPT_ENCODING, "gzip"); 131 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); 132 | 133 | $output = curl_exec($ch); 134 | $errno = curl_errno($ch); 135 | $error = curl_error($ch); 136 | $responseCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); 137 | $this->setLastStatusFromCurl($ch); 138 | curl_close($ch); 139 | if ($errno > 0) { 140 | throw new Facturapi_Exception('cURL error: ' . $error); 141 | } elseif ($responseCode < 200 || $responseCode > 299) { 142 | throw new Facturapi_Exception($output); 143 | } else { 144 | return $output; 145 | } 146 | } 147 | 148 | /** 149 | * Executes HTTP POST request 150 | * 151 | * @param URL : String value for the URL to POST to 152 | * @param fields : Array containing names and values for fields to post 153 | * 154 | * @return Body of request result 155 | * 156 | * @throws Facturapi_Exception 157 | */ 158 | protected function execute_post_request($url, $body, $formenc = false) 159 | { 160 | $headers[] = 'Authorization: Basic ' . $this->FACTURAPI_KEY; 161 | if ($formenc) { 162 | $headers[] = 'Content-Type: application/x-www-form-urlencoded'; 163 | } 164 | // initialize cURL and send POST data 165 | $ch = curl_init(); 166 | curl_setopt($ch, CURLOPT_POST, true); 167 | curl_setopt($ch, CURLOPT_POSTFIELDS, $body); 168 | curl_setopt($ch, CURLOPT_URL, $url); 169 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 170 | curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); 171 | 172 | 173 | $output = curl_exec($ch); 174 | $errno = curl_errno($ch); 175 | $error = curl_error($ch); 176 | $responseCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); 177 | $this->setLastStatusFromCurl($ch); 178 | curl_close($ch); 179 | if ($errno > 0) { 180 | throw new Facturapi_Exception('cURL error: ' . $error); 181 | } elseif ($responseCode < 200 || $responseCode > 299) { 182 | throw new Facturapi_Exception($output); 183 | } else { 184 | return $output; 185 | } 186 | } 187 | 188 | /** 189 | * Executes HTTP POST request with JSON as the POST body 190 | * 191 | * @param URL String value for the URL to POST to 192 | * @param fields array containing names and values for fields to post 193 | * 194 | * @return String Body of request result 195 | * 196 | * @throws Facturapi_Exception 197 | */ 198 | protected function execute_JSON_post_request($url, $body = null) 199 | { 200 | $headers[] = 'Authorization: Basic ' . $this->FACTURAPI_KEY; 201 | $headers[] = 'Content-Type: application/json'; 202 | 203 | // initialize cURL and send POST data 204 | $ch = curl_init(); 205 | curl_setopt($ch, CURLOPT_POST, true); 206 | curl_setopt($ch, CURLOPT_POSTFIELDS, $body ? json_encode($body) : null); 207 | curl_setopt($ch, CURLOPT_URL, $url); 208 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 209 | curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); 210 | 211 | $output = curl_exec($ch); 212 | $errno = curl_errno($ch); 213 | $error = curl_error($ch); 214 | //Get response code, only numbers in range from 200 to 299 are valid 215 | $responseCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); 216 | $this->setLastStatusFromCurl($ch); 217 | curl_close($ch); 218 | if ($errno > 0) { 219 | throw new Facturapi_Exception('cURL error: ' . $error); 220 | } elseif ($responseCode < 200 || $responseCode > 299) { 221 | throw new Facturapi_Exception($output); 222 | } else { 223 | return $output; 224 | } 225 | } 226 | 227 | /** 228 | * Executes HTTP PUT request 229 | * 230 | * @param URL String value for the URL to PUT to 231 | * @param array $body 232 | * 233 | * @return String Body of request result 234 | * 235 | * @throws Facturapi_Exception 236 | */ 237 | protected function execute_JSON_put_request($url, $body) 238 | { 239 | $headers[] = 'Authorization: Basic ' . $this->FACTURAPI_KEY; 240 | $headers[] = 'Content-Type: application/json'; 241 | 242 | $ch = curl_init(); 243 | curl_setopt($ch, CURLOPT_URL, $url); 244 | curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); 245 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 246 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT"); 247 | curl_setopt($ch, CURLOPT_POSTFIELDS, $body ? json_encode($body) : null); 248 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); 249 | 250 | $result = curl_exec($ch); 251 | $errno = curl_errno($ch); 252 | $error = curl_error($ch); 253 | $responseCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); 254 | $this->setLastStatusFromCurl($ch); 255 | curl_close($ch); 256 | if ($errno > 0) { 257 | throw new Facturapi_Exception('cURL error: ' . $error); 258 | } elseif ($responseCode < 200 || $responseCode > 299) { 259 | throw new Facturapi_Exception($result); 260 | } else { 261 | return $result; 262 | } 263 | } 264 | 265 | /** 266 | * Executes HTTP PUT request 267 | * 268 | * @param URL String value for the URL to PUT to 269 | * @param array $body 270 | * 271 | * @return String Body of request result 272 | * 273 | * @throws Facturapi_Exception 274 | */ 275 | protected function execute_data_put_request($url, $body) 276 | { 277 | $headers[] = 'Authorization: Basic ' . $this->FACTURAPI_KEY; 278 | $headers[] = 'Content-Type: multipart/form-data'; 279 | 280 | $data = is_array($body) ? array( 281 | 'cer' => new \CURLFile($body['cerFile']), 282 | 'key' => new \CURLFile($body['keyFile']), 283 | 'password' => $body['password'] 284 | ) : array( 285 | 'file' => new \CURLFile($body) 286 | ); 287 | 288 | $ch = curl_init(); 289 | curl_setopt($ch, CURLOPT_URL, $url); 290 | curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); 291 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 292 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT"); 293 | curl_setopt($ch, CURLOPT_POSTFIELDS, $data); 294 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); 295 | 296 | $result = curl_exec($ch); 297 | $errno = curl_errno($ch); 298 | $error = curl_error($ch); 299 | $this->setLastStatusFromCurl($ch); 300 | curl_close($ch); 301 | if ($errno > 0) { 302 | throw new Facturapi_Exception('cURL error: ' . $error); 303 | } else { 304 | return $result; 305 | } 306 | } 307 | 308 | /** 309 | * Executes HTTP DELETE request 310 | * 311 | * @param URL String value for the URL to DELETE to 312 | * @param String $body 313 | * 314 | * @return String Body of request result 315 | * 316 | * @throws Facturapi_Exception 317 | */ 318 | protected function execute_delete_request($url, $body) 319 | { 320 | $headers[] = 'Authorization: Basic ' . $this->FACTURAPI_KEY; 321 | $headers[] = 'Content-Type: application/json'; 322 | $headers[] = 'Content-Length: ' . strlen($body); 323 | 324 | $ch = curl_init(); 325 | curl_setopt($ch, CURLOPT_URL, $url); 326 | curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); 327 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 328 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE"); 329 | curl_setopt($ch, CURLOPT_POSTFIELDS, $body); 330 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); 331 | 332 | $result = curl_exec($ch); 333 | $errno = curl_errno($ch); 334 | $error = curl_error($ch); 335 | $this->setLastStatusFromCurl($ch); 336 | curl_close($ch); 337 | if ($errno > 0) { 338 | throw new Facturapi_Exception('cURL error: ' . $error); 339 | } else { 340 | return $result; 341 | } 342 | } 343 | 344 | /** 345 | * Converts an array into url friendly list of parameters 346 | * 347 | * @param array params Multidimensional array of parameters (name=>value) 348 | * 349 | * @return String of url friendly parameters (&name=value&foo=bar) 350 | */ 351 | protected function array_to_params($params) 352 | { 353 | $param_string = '?'; 354 | if ($params != null) { 355 | foreach ($params as $parameter => $value) { 356 | if (is_array($value)) { 357 | foreach ($value as $key => $sub_param) { 358 | $param_string = $param_string . '&' . $parameter . '[' . $key . ']' . '=' . urlencode($sub_param); 359 | } 360 | } else { 361 | $param = gettype($value) == 'boolean' ? json_encode($value) : urlencode($value); 362 | $param_string = $param_string . '&' . $parameter . '=' . $param; 363 | } 364 | } 365 | } 366 | 367 | return $param_string; 368 | } 369 | 370 | /** 371 | * Sets the status code from a curl request 372 | */ 373 | protected function setLastStatusFromCurl($ch) 374 | { 375 | $info = curl_getinfo($ch); 376 | $this->lastStatus = (isset($info['http_code'])) ? $info['http_code'] : null; 377 | } 378 | } 379 | -------------------------------------------------------------------------------- /src/Resources/Organizations.php: -------------------------------------------------------------------------------- 1 | execute_get_request($this->get_request_url($params))); 26 | } catch (Facturapi_Exception $e) { 27 | throw new Facturapi_Exception('Unable to get organizations: ' . $e->getMessage()); 28 | } 29 | } 30 | 31 | /** 32 | * Get a Organization by ID 33 | * 34 | * @param id : Unique ID for Organization 35 | * 36 | * @return JSON object for requested Organization 37 | * 38 | * @throws Facturapi_Exception 39 | **/ 40 | public function retrieve($id) 41 | { 42 | try { 43 | return json_decode($this->execute_get_request($this->get_request_url($id))); 44 | } catch (Facturapi_Exception $e) { 45 | throw new Facturapi_Exception('Unable to get organization: ' . $e->getMessage()); 46 | } 47 | } 48 | 49 | /** 50 | * Create a Organization 51 | * 52 | * @param params : array of properties and property values for new Organization 53 | * 54 | * @return Response body with JSON object 55 | * for created Organization from HTTP POST request 56 | * 57 | * @throws Facturapi_Exception 58 | **/ 59 | public function create($params) 60 | { 61 | try { 62 | return json_decode($this->execute_JSON_post_request($this->get_request_url(), $params)); 63 | } catch (Facturapi_Exception $e) { 64 | throw new Facturapi_Exception('Unable to create organization: ' . $e->getMessage()); 65 | } 66 | } 67 | 68 | /** 69 | * Update a Organization's legal information 70 | * 71 | * @param $id 72 | * @param $params array of properties and property values for Organization's legal information 73 | * 74 | * @return Response body from HTTP PUT request 75 | * 76 | * @throws Facturapi_Exception 77 | * 78 | */ 79 | public function updateLegal($id, $params) 80 | { 81 | try { 82 | return json_decode($this->execute_JSON_put_request($this->get_request_url($id) . "/legal", $params)); 83 | } catch (Facturapi_Exception $e) { 84 | throw new Facturapi_Exception('Unable to update organization\'s legal information: ' . $e->getMessage()); 85 | } 86 | } 87 | 88 | /** 89 | * Update a Organization's customization information 90 | * 91 | * @param $id 92 | * @param $params array of properties and property values for Organization's customization information 93 | * 94 | * @return Response body from HTTP PUT request 95 | * 96 | * @throws Facturapi_Exception 97 | * 98 | */ 99 | public function updateCustomization($id, $params) 100 | { 101 | try { 102 | return json_decode($this->execute_JSON_put_request($this->get_request_url($id) . "/customization", $params)); 103 | } catch (Facturapi_Exception $e) { 104 | throw new Facturapi_Exception('Unable to update organization\'s customization information: ' . $e->getMessage()); 105 | } 106 | } 107 | 108 | /** 109 | * Update a Organization's receipt settings 110 | * 111 | * @param $id 112 | * @param $params array of properties and property values for Organization's receipt settings 113 | * 114 | * @return Response body from HTTP PUT request 115 | * 116 | * @throws Facturapi_Exception 117 | * 118 | */ 119 | public function updateReceiptSettings($id, $params) 120 | { 121 | try { 122 | return json_decode($this->execute_JSON_put_request($this->get_request_url($id) . "/receipts", $params)); 123 | } catch (Facturapi_Exception $e) { 124 | throw new Facturapi_Exception('Unable to update organization\'s receipt settings: ' . $e->getMessage()); 125 | } 126 | } 127 | 128 | /** 129 | * Update the Organization's domain 130 | * 131 | * @param $id Organization Id 132 | * @param $params array of properties and property values for the Organization's domain 133 | * 134 | * @return Response body from HTTP PUT request 135 | * 136 | * @throws Facturapi_Exception 137 | * 138 | */ 139 | public function updateDomain($id, $params) 140 | { 141 | try { 142 | return json_decode($this->execute_JSON_put_request($this->get_request_url($id) . "/domain", $params)); 143 | } catch (Facturapi_Exception $e) { 144 | throw new Facturapi_Exception('Unable to update organization\'s domain: ' . $e->getMessage()); 145 | } 146 | } 147 | 148 | /** 149 | * Update the Organization's domain 150 | * 151 | * @param $id Organization Id 152 | * @param $params array of properties and property values for the Organization's domain 153 | * 154 | * @return Response body from HTTP PUT request 155 | * 156 | * @throws Facturapi_Exception 157 | * 158 | */ 159 | public function checkDomainIsAvailable($id, $params) 160 | { 161 | try { 162 | return json_decode( 163 | $this->execute_get_request( 164 | $this->get_request_url("domain-check" . $this->array_to_params($params)) 165 | ) 166 | ); 167 | } catch (Facturapi_Exception $e) { 168 | throw new Facturapi_Exception('Unable to check domain\'s availability: ' . $e->getMessage()); 169 | } 170 | } 171 | 172 | /** 173 | * Uploads the organization's logo 174 | * 175 | * @param $id 176 | * @param $params array of properties and property values for Organization's logo 177 | * 178 | * @return Response body from HTTP PUT request 179 | * 180 | * @throws Facturapi_Exception 181 | * 182 | */ 183 | public function uploadLogo($id, $params) 184 | { 185 | try { 186 | return json_decode($this->execute_data_put_request($this->get_request_url($id) . "/logo", $params)); 187 | } catch (Facturapi_Exception $e) { 188 | throw new Facturapi_Exception('Unable to upload organization\'s logo: ' . $e->getMessage()); 189 | } 190 | } 191 | 192 | /** 193 | * Uploads the organization's certificate (CSD) 194 | * 195 | * @param $id 196 | * @param $params array of properties and property values for organization's certificate (CSD) 197 | * 198 | * @return Response body from HTTP PUT request 199 | * 200 | * @throws Facturapi_Exception 201 | * 202 | */ 203 | public function uploadCertificate($id, $params) 204 | { 205 | try { 206 | return json_decode($this->execute_data_put_request($this->get_request_url($id) . "/certificate", $params)); 207 | } catch (Facturapi_Exception $e) { 208 | throw new Facturapi_Exception('Unable to upload organization\'s certificate (CSD): ' . $e->getMessage()); 209 | } 210 | } 211 | 212 | /** 213 | * Get the Test Api Key for an Organization 214 | * 215 | * @param id : Unique ID for Organization 216 | * 217 | * @return String Test Api Key 218 | * 219 | * @throws Facturapi_Exception 220 | **/ 221 | public function getTestApiKey($id) 222 | { 223 | try { 224 | return json_decode($this->execute_get_request($this->get_request_url($id) . "/apikeys/test")); 225 | } catch (Facturapi_Exception $e) { 226 | throw new Facturapi_Exception('Unable to get organization\'s test key: ' . $e->getMessage()); 227 | } 228 | } 229 | 230 | /** 231 | * Renews the Test Api Key for an Organization and makes the previous one inactive 232 | * 233 | * @param id : Unique ID for Organization 234 | * 235 | * @return String Test Api Key 236 | * 237 | * @throws Facturapi_Exception 238 | **/ 239 | public function renewTestApiKey($id) 240 | { 241 | try { 242 | return json_decode( 243 | $this->execute_JSON_put_request( 244 | $this->get_request_url($id) . "/apikeys/test", 245 | [] 246 | ) 247 | ); 248 | } catch (Facturapi_Exception $e) { 249 | throw new Facturapi_Exception('Unable to renew organization\'s test key: ' . $e->getMessage()); 250 | } 251 | } 252 | 253 | /** 254 | * Renews the Test Api Key for an Organization and makes the previous one inactive 255 | * 256 | * @param id : Unique ID for Organization 257 | * 258 | * @return Array Array of object with first_12 characters, created_at field and id field 259 | * 260 | * @throws Facturapi_Exception 261 | **/ 262 | public function lisLiveApiKeys($id) 263 | { 264 | try { 265 | return json_decode( 266 | $this->execute_get_request( 267 | $this->get_request_url($id) . "/apikeys/live", 268 | [] 269 | ) 270 | ); 271 | } catch (Facturapi_Exception $e) { 272 | throw new Facturapi_Exception($e); 273 | } 274 | } 275 | 276 | 277 | /** 278 | * Renews the Test Api Key for an Organization and makes the previous one inactive 279 | * 280 | * @param id : Unique ID for Organization 281 | * 282 | * @return String Live Api Key 283 | * 284 | * @throws Facturapi_Exception 285 | **/ 286 | public function renewLiveApiKey($id) 287 | { 288 | try { 289 | return json_decode( 290 | $this->execute_JSON_put_request( 291 | $this->get_request_url($id) . "/apikeys/live", 292 | [] 293 | ) 294 | ); 295 | } catch (Facturapi_Exception $e) { 296 | throw new Facturapi_Exception('Unable to renew organization\'s live key: ' . $e->getMessage()); 297 | } 298 | } 299 | 300 | /** 301 | * Deletes the Test Api Key for an Organization and makes the previous one inactive 302 | * 303 | * @param organizationId : Unique ID for Organization 304 | * @param apiKeyId: Unique ID for the Api Key 305 | * 306 | * @return Array Array of object with first_12 characters, created_at field and id field 307 | * 308 | * @throws Facturapi_Exception 309 | **/ 310 | public function deleteLiveApiKey($organizationId, $apiKeyId) 311 | { 312 | try { 313 | return json_decode( 314 | $this->execute_JSON_put_request( 315 | $this->get_request_url($organizationId) . "/apikeys/live" . "/" . $apiKeyId, 316 | [] 317 | ) 318 | ); 319 | } catch (Facturapi_Exception $e) { 320 | throw new Facturapi_Exception($e); 321 | } 322 | } 323 | 324 | /** 325 | * Delete a Organization 326 | * 327 | * @param id : Unique ID for the Organization 328 | * 329 | * @return Response body from HTTP DELETE request 330 | * 331 | * @throws Facturapi_Exception 332 | **/ 333 | public function delete($id) 334 | { 335 | try { 336 | return json_decode($this->execute_delete_request($this->get_request_url($id), null)); 337 | } catch (Facturapi_Exception $e) { 338 | throw new Facturapi_Exception('Unable to delete organization: ' . $e->getMessage()); 339 | } 340 | } 341 | 342 | /** 343 | * Delete a Organization's Certificate 344 | * 345 | * @param id : Unique ID for the Organization 346 | * 347 | * @return Response body from HTTP DELETE request 348 | * 349 | * @throws Facturapi_Exception 350 | **/ 351 | public function deleteCertificate($id) 352 | { 353 | try { 354 | return json_decode($this->execute_delete_request($this->get_request_url($id) . "/certificate", null)); 355 | } catch (Facturapi_Exception $e) { 356 | throw new Facturapi_Exception('Unable to delete organization: ' . $e->getMessage()); 357 | } 358 | } 359 | 360 | /** 361 | * Get the series of an Organization 362 | * 363 | * @param id : Unique ID for the Organization 364 | * 365 | * @return Response body from HTTP GET request 366 | * 367 | * @throws Facturapi_Exception 368 | **/ 369 | public function getSeriesGroup($id) 370 | { 371 | try { 372 | return json_decode($this->execute_get_request($this->get_request_url($id) . "/series-group")); 373 | } catch (Facturapi_Exception $e) { 374 | throw new Facturapi_Exception('Unable to find series: ' . $e); 375 | } 376 | } 377 | 378 | /** 379 | * Create a Series Organization 380 | * 381 | * @param id : Unique ID for the Organization 382 | * 383 | * 384 | * @param params : object of properties and property values for new Series Organization 385 | * 386 | * @return Response body with JSON object 387 | * for created Organization from HTTP POST request 388 | * 389 | * @throws Facturapi_Exception 390 | **/ 391 | public function createSeriesGroup($id, $params) 392 | { 393 | try { 394 | return json_decode($this->execute_JSON_post_request($this->get_request_url($id) . "/series-group", $params)); 395 | } catch (Facturapi_Exception $e) { 396 | throw new Facturapi_Exception('Unable to create series: ' . $e); 397 | } 398 | } 399 | 400 | /** 401 | * Update a Series Organization 402 | * 403 | * @param id : Unique ID for the Organization 404 | * 405 | * @param series_name: Name of the series to update 406 | * 407 | * @param params : object of properties and property values for updated Series Organization 408 | * 409 | * @return Response body with JSON object 410 | * for updated Series Organization from HTTP POST request 411 | * 412 | * @throws Facturapi_Exception 413 | **/ 414 | public function updateSeriesGroup($id, $series_name, $params) 415 | { 416 | try { 417 | return json_decode($this->execute_JSON_put_request($this->get_request_url($id) . "/series-group" . "/" . $series_name, $params)); 418 | } catch (Facturapi_Exception $e) { 419 | throw new Facturapi_Exception('Unable to create series: ' . $e); 420 | } 421 | } 422 | 423 | /** 424 | * Delete a Series Organization 425 | * 426 | * @param id : Unique ID for the Organization 427 | * 428 | * @param series_name: Name of the series to update 429 | * 430 | * @param params : object of properties and property values for new Series Organization 431 | * 432 | * @return Response body with JSON object 433 | * for delete Series Organization from HTTP DELETE request 434 | * 435 | * @throws Facturapi_Exception 436 | **/ 437 | public function deleteSeriesGroup($id, $series_name) 438 | { 439 | try { 440 | return json_decode($this->execute_delete_request($this->get_request_url($id) . "/series-group" . "/" . $series_name, null)); 441 | } catch (Facturapi_Exception $e) { 442 | throw new Facturapi_Exception('Unable to create series: ' . $e); 443 | } 444 | } 445 | 446 | /** 447 | * Update self-invoice settings for an Organization 448 | * 449 | * @param string $id : Unique ID for the Organization 450 | * @param array $params : Properties and values for self-invoice settings 451 | * 452 | * @return Response body from HTTP PUT request 453 | * 454 | * @throws Facturapi_Exception 455 | **/ 456 | public function updateSelfInvoiceSettings($id, $params) 457 | { 458 | try { 459 | return json_decode($this->execute_JSON_put_request($this->get_request_url($id) . "/self-invoice", $params)); 460 | } catch (Facturapi_Exception $e) { 461 | throw new Facturapi_Exception('Unable to update organization\'s self-invoice settings: ' . $e->getMessage()); 462 | } 463 | } 464 | } 465 | --------------------------------------------------------------------------------