Introduction
Invoicing is very important aspect of any business and any tool that eases this process is generally welcomed. PayPal has a great invoicing tool that’s actually been around for a while now, but merchants were forced to use it from directly within their PayPal account. It wasn’t until the Adaptive Payments platform was introduced that developers were given direct access to invoicing web services.
We developers now have the freedom to build PayPal invoicing into our own applications. This provides a tremendous opportunity, much like the many other PayPal services that are available, to use creativity in design and user interaction to ease the process for end users as much as possible.
As usual, I’m going leave the creativity up to you and get straight into the technical details of working with the PayPal invoicing API’s using this PHP library, which greatly reduces the amount of time needed to build these API calls. If you’re not familiar with it, you may want to skim that article first, but you can still follow along and probably pick it up here as well because it’s very straight forward.
We’ll be covering the following web service API’s:
- CreateInvoice
- SendInvoice
- CreateAndSendInvoice
- MarkInvoiceAsPaid
- GetInvoiceDetails
- CancelInvoice
- SearchInvoices
- UpdateInvoice
The library includes pre-written code templates for each of these calls so all you have to do is fill in the request parameters. We’ll take a look at some code samples of each call, and we’ll also look at some screen-shots of what users will see in their PayPal account (when available). We’re going to cover the first 4 API calls in detail within this article, but the sample files will include all 8.
CreateInvoice
To create a new invoice in the PayPal system without actually sending the invoice, we use the CreateInvoice API. This will prepare the invoice in the merchant’s PayPal account but leave it for further processing at a later time.
Let’s take a look at a code sample for creating an invoice.
<?php // Include required library files. require_once('includes/config.php'); require_once('includes/paypal.class.php'); // Create PayPal object. $PayPalConfig = array( 'Sandbox' => $sandbox, 'DeveloperAccountEmail' => $developer_account_email, 'ApplicationID' => $application_id, 'DeviceID' => $device_id, 'IPAddress' => $_SERVER['REMOTE_ADDR'], 'APIUsername' => $api_username, 'APIPassword' => $api_password, 'APISignature' => $api_signature, 'APISubject' => $api_subject ); $PayPal = new PayPal_Adaptive($PayPalConfig); // Prepare request arrays $CreateInvoiceFields = array( 'MerchantEmail' => 'sandbo_1215254764_biz@angelleye.com', // Required. Merchant email address. 'PayerEmail' => 'sandbo_1204199080_biz@angelleye.com', // Required. Payer email address. 'Number' => 'ABC-111', // Unique ID for the invoice. 'CurrencyCode' => 'USD', // Required. Currency used for all invoice item amounts and totals. 'InvoiceDate' => '', // Date on which the invoice is enabled. 'DueDate' => '', // Date on which the invoice payment is due. 'PaymentTerms' => 'DueOnReceipt', // Required. Terms by which the invoice payment is due. Values are: DueOnReceipt, DueOnSpecified, Net10, Net15, Net30, Net45 'DiscountPercent' => '', // Discount percent applied to the invoice. 'DiscountAmount' => '', // Discount amount applied to the invoice. If DiscountPercent is provided, DiscountAmount is ignored. 'Terms' => '', // General terms for the invoice. 'Note' => 'This is a test invoice.', // Note to the payer company. 'MerchantMemo' => 'This is a test invoice.', // Memo for bookkeeping that is private to the merchant. 'ShippingAmount' => '10.00', // Cost of shipping 'ShippingTaxName' => '', // Name of the applicable tax on the shipping cost. 'ShippingTaxRate' => '', // Rate of the applicable tax on the shipping cost. 'LogoURL' => 'https://www.usbswiper.com/images/angelley-clients/cpp-header-image.jpg' // Complete URL to an external image used as the logo, if any. ); $BusinessInfo = array( 'FirstName' => 'Tester', // First name of the company contact. 'LastName' => 'Testerson', // Last name of the company contact. 'BusinessName' => 'Testers, LLC', // Company business name. 'Phone' => '555-555-5555', // Phone number for contacting the company. 'Fax' => '555-555-5556', // Fax number used by the company. 'Website' => 'http://www.domain.com', // Website used by the company. 'Custom' => 'Some custom info.' // Custom value to be displayed in the contact information details. ); $BusinessInfoAddress = array( 'Line1' => '123 Main St.', // Required. First line of address. 'Line2' => '', // Second line of address. 'City' => 'Grandview', // Required. City of thte address. 'State' => 'MO', // State for the address. 'PostalCode' => '64030', // Postal code of the address 'CountryCode' => 'US' // Required. Country code of the address. ); $BillingInfo = array( 'FirstName' => 'Tester', // First name of the company contact. 'LastName' => 'Testerson', // Last name of the company contact. 'BusinessName' => 'Testers, LLC', // Company business name. 'Phone' => '555-555-5555', // Phone number for contacting the company. 'Fax' => '555-555-5556', // Fax number used by the company. 'Website' => 'http://www.domain.com', // Website used by the company. 'Custom' => 'Some custom info.' // Custom value to be displayed in the contact information details. ); $BillingInfoAddress = array( 'Line1' => '123 Main St.', // Required. First line of address. 'Line2' => '', // Second line of address. 'City' => 'Grandview', // Required. City of thte address. 'State' => 'MO', // State for the address. 'PostalCode' => '64030', // Postal code of the address 'CountryCode' => 'US' // Required. Country code of the address. ); $ShippingInfo = array( 'FirstName' => 'Tester', // First name of the company contact. 'LastName' => 'Testerson', // Last name of the company contact. 'BusinessName' => 'Testers, LLC', // Company business name. 'Phone' => '555-555-5555', // Phone number for contacting the company. 'Fax' => '555-555-5556', // Fax number used by the company. 'Website' => 'http://www.domain.com', // Website used by the company. 'Custom' => 'Some custom info.' // Custom value to be displayed in the contact information details. ); $ShippingInfoAddress = array( 'Line1' => '123 Main St.', // Required. First line of address. 'Line2' => '', // Second line of address. 'City' => 'Grandview', // Required. City of thte address. 'State' => 'MO', // State for the address. 'PostalCode' => '64030', // Postal code of the address 'CountryCode' => 'US' // Required. Country code of the address. ); // For invoice items you populate a nested array with multiple $InvoiceItem arrays. Normally you'll be looping through cart items to populate the $InvoiceItem // array and then push it into the $InvoiceItems array at the end of each loop for an entire collection of all items in $InvoiceItems. $InvoiceItems = array(); $InvoiceItem = array( 'Name' => 'Test Widget 1', // Required. SKU or name of the item. 'Description' => 'This is a test widget #1', // Item description. 'Date' => '2012-02-18', // Date on which the product or service was provided. 'Quantity' => '1', // Required. Item count. Values are: 0 to 10000 'UnitPrice' => '10.00', // Required. Price of the item, in the currency specified by the invoice. 'TaxName' => '', // Name of the applicable tax. 'TaxRate' => '' // Rate of the applicable tax. ); array_push($InvoiceItems,$InvoiceItem); $InvoiceItem = array( 'Name' => 'Test Widget 2', // Required. SKU or name of the item. 'Description' => 'This is a test widget #2', // Item description. 'Date' => '2012-02-18', // Date on which the product or service was provided. 'Quantity' => '2', // Required. Item count. Values are: 0 to 10000 'UnitPrice' => '20.00', // Required. Price of the item, in the currency specified by the invoice. 'TaxName' => '', // Name of the applicable tax. 'TaxRate' => '' // Rate of the applicable tax. ); array_push($InvoiceItems,$InvoiceItem); $PayPalRequestData = array( 'CreateInvoiceFields' => $CreateInvoiceFields, 'BusinessInfo' => $BusinessInfo, 'BusinessInfoAddress' => $BusinessInfoAddress, 'BillingInfo' => $BillingInfo, 'BillingInfoAddress' => $BillingInfoAddress, 'ShippingInfo' => $ShippingInfo, 'ShippingInfoAddress' => $ShippingInfoAddress, 'InvoiceItems' => $InvoiceItems ); // Pass data into class for processing with PayPal and load the response array into $PayPalResult $PayPalResult = $PayPal->CreateInvoice($PayPalRequestData); // Write the contents of the response array to the screen for demo purposes. echo '<pre />'; print_r($PayPalResult); ?>
As you can see, the use of the PHP library makes this very simple. The code consists of simple array data that is passed into the library which handles all of the processing for us and returns a simple array of result data.
The request array data is split up into groups similar to how PayPal splits it in their documentation. You’ll notice that we have array groups for general request data ($CreateInvoiceFields) as well as separate groups for business information, billing and shipping information, and individual items that should go on the invoice.
These array groups are then nested into a single $PayPalRequestData array which is passed into the library to get our result.
The request parameters are all pretty straight forward, and there are comments next to each field in the code that was pulled directly from the PayPal documentation if you have any questions about individual fields. The one thing I will mention specifically is that the MerchantEmail should be the PayPal email address of the account the invoice is being created from. All of the other request information refers to the person/company receiving the invoice.
There is no redirection involved for the user when simply creating an invoice, so we’ll get an immediate result back from PayPal. When we run our current code sample we get the following result back from the library:
Array ( [Errors] => Array() [Ack] => Success [Build] => 2573586 [CorrelationID] => 55008b7d484e6 [Timestamp] => 2012-04-02T02:30:47.871-07:00 [InvoiceID] => INV2-F3MK-CBYE-XLGL-6EF8 [InvoiceNumber] => ABC-111 [InvoiceURL] => https://www.sandbox.paypal.com/us/cgi-bin/?cmd=_inv-details&id=INV2-F3MK-CBYE-XLGL-6EF8 [XMLRequest] => … [XMLResponse] => … )
The response fields for the API call are available in this result array, and the raw XML request and response are also available if we need to take a look at those directly (although I’ve cleared those in the sample here to keep this clean). Here we can see the call was successful and we were given an InvoiceID as well as an InvoiceURL for the new invoice. This URL can be used to view the invoice in PayPal; however, the sandbox is not currently providing this feature so I’m unable to include a screen-shot of that at this time.
At this point we have a new invoice created in the PayPal system, but as mentioned previously, it has not yet been sent to anybody for payment. We could now update the invoice, cancel the invoice, mark it as paid, or simply send it in its current state.  Let’s take a look at that, next.
SendInvoice
Now that we’ve prepared our invoice and created it in the PayPal system, let’s take a look at a code sample to complete the process of sending the invoice to another user for payment. We’ll use the SendInvoice API with the InvoiceID we got back from our CreateInvoice request in the previous section: INV2-F3MK-CBYE-XLGL-6EF8.
<?php // Include required library files. require_once('includes/config.php'); require_once('includes/paypal.class.php'); // Create PayPal object. $PayPalConfig = array( 'Sandbox' => $sandbox, 'DeveloperAccountEmail' => $developer_account_email, 'ApplicationID' => $application_id, 'DeviceID' => $device_id, 'IPAddress' => $_SERVER['REMOTE_ADDR'], 'APIUsername' => $api_username, 'APIPassword' => $api_password, 'APISignature' => $api_signature, 'APISubject' => $api_subject ); $PayPal = new PayPal_Adaptive($PayPalConfig); // Pass data into class for processing with PayPal and load the response array into $PayPalResult $InvoiceID = 'INV2-F3MK-CBYE-XLGL-6EF8'; $PayPalResult = $PayPal->SendInvoice($InvoiceID); // Write the contents of the response array to the screen for demo purposes. echo '<pre />'; print_r($PayPalResult); ?>
Again, we simply fill in the request parameter for SendInvoice file included with the library. In this case it consists if a single variable, $InvoiceID.
When run, this code results in the following:
Array ( [Errors] => Array() [Ack] => Success [Build] =>2573586 [CorrelationID] =>0cf3c5545f9f0 [Timestamp] =>2012-04-02T02:49:51.750-07:00 [InvoiceID] => INV2-F3MK-CBYE-XLGL-6EF8 [InvoiceURL] => https://www.sandbox.paypal.com/us/cgi-bin/?cmd=_inv-details&id=INV2-F3MK-CBYE-XLGL-6EF8 [XMLRequest] => … [XMLResponse] => … )
The result here is very similar to the CreateInvoice result in that we’re given our InvoiceID and InvoiceURL again. This allows you to provide those details accordingly within your application, and redirect the user to the invoice URL if you choose to at this point.
We can now see the invoice in the Overview of both the sender and the receiver’s accounts.
Sender’s Account
Receiver’s Account
Note: Both my sandbox seller and my sandbox payer account have the same name: Drew Angell’s Test Store. Don’t let that confuse you here.
Both parties will also receive the standard emails that PayPal sends to users when they send or receive a new payment request. The receiver will be able to pay the invoice from their PayPal account just like any other payment request they may receive.
CreateAndSendInvoice
As the name suggests, The CreateAndSendInvoice API will take care of both actions with a single request as oppose to splitting them up as we discussed previously. The request is actually exactly the same as the CreateInvoice sample we looked at previously, so I won’t bother to include the same code again here. There are separate samples included in the source files for the article, though, so feel free to take a look there.   Again, though, the request and result are nearly identical. We’ve simply changed the call name from CreateInvoice to CreateAndSendInvoice.
MarkInvoiceAsPaid
Consider a scenario where the receiver submits payment somehow outside of the PayPal system. Maybe they call and give you a payment over the phone, or maybe they pay cash in person. Let’s go ahead and consider that example and mark our invoice as paid via cash using thte MarkInvoiceAsPaid API. Here’s our code:
<?php // Include required library files. require_once('includes/config.php'); require_once('includes/paypal.class.php'); // Create PayPal object. $PayPalConfig = array( 'Sandbox' => $sandbox, 'DeveloperAccountEmail' => $developer_account_email, 'ApplicationID' => $application_id, 'DeviceID' => $device_id, 'IPAddress' => $_SERVER['REMOTE_ADDR'], 'APIUsername' => $api_username, 'APIPassword' => $api_password, 'APISignature' => $api_signature, 'APISubject' => $api_subject ); $PayPal = new PayPal_Adaptive($PayPalConfig); // Prepare request arrays $MarkInvoiceAsPaidFields = array( 'InvoiceID' => 'INV2-F3MK-CBYE-XLGL-6EF8', // Required. ID of the invoice to mark paid. 'Method' => 'Cash', // Method t hat can be used to mark an invoice as paid when the payer p ays offline. Values are: BankTransfer, Cash, Check, CreditCard, DebitCard, Other, PayPal, WireTransfer 'Note' => 'User paid cash.', // Optional note associated with the payment. 'Date' => '2012-03-31' // Date the invoice was paid. ); $PayPalRequestData = array('MarkInvoiceAsPaidFields' => $MarkInvoiceAsPaidFields); // Pass data into class for processing with PayPal and load the response array into $PayPalResult $PayPalResult = $PayPal->MarkInvoiceAsPaid($PayPalRequestData); // Write the contents of the response array to the screen for demo purposes. echo '<pre />'; print_r($PayPalResult);
Once again, we’re simply passing in our InvoiceID that we received when we created the invoice using CreateInvoice/CreateAndSendInvoice. The request also includes a parameter called “Method” which we’re sending as the value “Cash” as well as a note and a date parameter.
The result…
Array ( [Errors] => Array() [Ack] => Success [Build] => 2573586 [CorrelationID] => cc7d7ce0f6a8e [Timestamp] =>2012-04-02T03:17:38.326-07:00 [InvoiceID] => INV2-F3MK-CBYE-XLGL-6EF8 [InvoiceNumber] => ABC-111 [InvoiceURL] => https://www.sandbox.paypal.com/us/cgi-bin/?cmd=_inv-details&id=INV2-F3MK-CBYE-XLGL-6EF8 [XMLRequest] => … [XMLResponse] => … )
As usual, we’re given a successful response that includes the InvoiceID, Invoice Number, and InvoiceURL for application purposes. We can now see the invoice has been paid from each user’s PayPal account:
Sender’s Account
Receiver’s Account
Conclusion
While the invoicing API is fairly straight forward and simple to implement, the ability to build these services directly into your application can greatly enhance the ease of use for end users and reduce bottlenecks with invoicing and payments.
We covered creating and sending an invoice as well as marking it as paid in detail. The sample files also include code for using the CancelInvoice, GetInvoiceDetails, SearchInvoices, and UpdateInvoice API’s. They all work in exactly the same way with the included PHP library. It’s just a matter of opening up the request file you’d like to work with and filling in the request parameters accordingly.
Have fun, and happy coding!
Looking for Live Help?
Schedule a live meeting with Drew Angell, PayPal Certified Developer, and get all of your questions or concerns answered.
Featured PayPal Products and Services
-
PayPal Support
$100.00 -
PayPal for WooCommerce
FREE! -
WooCommerce Multiple PayPal Accounts Plugin
$119.99 -
PayPal Shipment Tracking for WooCommerce
$49.99 -
Sale!
PayPal for WooCommerce – Credit Card Split Payment
$49.99 -
Offers for WooCommerce
$59.99 -
WordPress PayPal Invoice Plugin
$20.00 -
PayPal Webhooks for WordPress
$79.99
Hi!
I want to use your code to create invoices in paypal. I am tried to use the CreateInvoce.php but everytime I acess the template I get the error as response:
(
[Receiver] =>
[Category] => Application
[Domain] => PLATFORM
[ErrorID] => 570054
[ExceptionID] =>
[Message] => Invalid token
[Parameter] =>
[Severity] => Error
[Subdomain] => Application
)
I basically changed the values of username/password/signature for my data
Can you help me on this? The code below is my config file:
Please submit a ticket here and attach the file that you are working with. I’ll take a look and let you know what the problem is.
I couldn’t find how to configure sandbox credentials. Could you highlight on that please?
I have a guide on how to create PayPal sandbox accounts that might help. You would obtain API credentials for the account from within its profile after it’s created. Does that help?
Is there a way to use the AllowPartialPayment variable in the CreateAndSendInvoice php? I have a similar question as well about the MarkInvoiceAsPaid php…can I mark that a certain amount has been paid? I have the invoice creation part working in the sandbox, but I want to be able to force a minimum amount due, but I cannot find anywhere to do it automatically. All I can find is how to go into the invoice manually to check that box. Is there even a way to do this using this code?
The Invoicing API currently supported by our library is the old one, which does not support partial payments. We are just about to release the 1.3.0 update to our library, though, which adds all of the REST APIs. These new APIs include a new Invoicing system that does provide the ability to handle partial payments. We have this all done in our GitHub repo already. I’ll be doing final review/testing this week and will hopefully be releasing it by the end of the week.
Hi, how to use the Amount Only template? I don’t need the Quantity in my case.
Thank you!
In that case you could just use Quantity 1..??
I’m trying to use your template to create an invoice. I don’t understand this line near the top of the CreateInvoice.php file. Can you tell me what it is for and where the path resides?
$PayPal = new \angelleye\PayPal\rest\invoice\InvoiceAPI($configArray);
I’m getting this error: Fatal error: Class ‘PayPal\Rest\ApiContext’ not found in /home/doyle52/public_html/members_area/paypal-php-library/src/angelleye/PayPal/rest/invoice/InvoiceAPI.php on line 36
I would appreciate your help.
Obviously I’m just a novice at this paypal stuff.
That line pulls in the PayPal class to create the object. Based on the error it looks like you’re running on an old version of PHP. Can you verify what version you are running?
Hi There,
I’m trying to use this to simply send an invoice.
As far as im aware, this is considered an Adaptive Payments applications, and i need an APP ID, but i cant figure out how to get one.
Please help.
I’m sorry, I need to update this guide. The Adaptive Payments API is no longer available for new sign-ups. The Invoicing API is still available now as part of the REST services, and the dev branch of our library on GitHub includes this, but we have not yet merged it and officially released the update to our library. We’re hoping to get that done within the next month or so along with a bunch of new demo kits, but until then you should be able to work with the dev branch and all the samples/templates it comes with.
Can’t find config.php in package that i have installed.
You should see it under /samples/config.php, and you’ll need to save that out to the /includes folder.
Can’t find paypal.class.php in package that i have installed.
If you installed via Composer you just need to include the config file and the autoloader into your project file(s). Where exactly are you getting stuck?
Hi,
for about a month when I run the createandsendinvoice I receive the empty ACK value, as in the example below:
Array (
[Errors] => Array ( )
[Ack] =>
[Build] =>
[CorrelationID] =>
[Timestamp] =>
[InvoiceID] => INV2-YL7K-S9JF-….-….
[InvoiceNumber] => My-number
[InvoiceURL] => https://www.paypal.com/invoice/details/INV2-YL7K-S9JF-….-….
[XMLRequest] => …
[XMLResponse] => INV…
before the “Success” value returned correctly.
From the looks of it the invoice did get created successfully, is that right? Did you look at the raw XML request? I’m guessing that maybe it’s there, but something about the format is keeping it from parsing properly into the array fields.