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
Sender's Account

Receiver’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
Sender's Account

Receiver’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.