I'm really happy with the results, and she wanted to raise some money for some of her interests so I did a site for her to sell her songs and the album I commissioned ("Perspectives"). She also is an avid photographer, and she loves to take photos as the Henry Doorly Zoo - so we added those to the site for sale as well (only $1.29 royalty-free, so hurry now before the internet runs out of bandwidth stock!).
To support the sales via PayPal, I thought about writing a library I could reuse in other projects. But then I had a better idea: Just put that code into an webapp that only processes PayPal IPNs, and have a convention so that the parms I send in to PayPal from a webapp can be picked up by this process during the IPN cycle and route requests to the originating webapp for fulfillment if required. It's really generic and I'm already using it on another site I'm doing for my sister-in-law.
The basic process is this: I use the "item_number" to hold the resource URI, and the "custom" field to hold the site domain/webapp that is originating the purchase. These resource URIs don't point to the real resource to discourage simple piracy, but the IPN webapp turns them into an email with the encoded real URI to send to the purchaser. Clicking the link is handled by a servlet in the IPN webapp that decodes the URI, and then streams the purchased content back to the user's browser. Even this URI is not accessible directly by the browser, and all the user can see in the emailed link is the encoded form. This prevents the user from trying different parms in that link to attempt downloading other content (like the names of other tracks that can be seen on the web page).
Works great, AND it's less filling - what more could you ask for?