This Devpay plugin is designed to ease integration with Amazon’s DevPay services, specifically for web-hosted DevPay products.
Note: DevPay products for the desktop will very likely not find this plugin terribly useful. Sorry.
DevPay is designed to be a very hands-off payment processing and subscription management system. It allows developers to nearly ignore the process altogether. The pieces which are of concern, however, are as follows:
-
Customer signs up for your product using a link you provide (see Devpay.purchase_url_for),
-
The customer successfully signs up for your product and is redirected to a URL you’d previously provided during product registration,
-
The redirection contains an activation key and product code which must be activated (see Devpay.activate!),
-
Following activation, you’ll receive a User Token and Persistent Identifier (both of which should be stored),
-
The customer happily uses your hosted DevPay product,
-
… you can periodically check the customer’s subscription status (see Devpay.active?) …
-
Profit!
First, you’ll need an Amazon Web Services account. Once you’ve got that, you’ll have to provide the following to this plugin:
- Access Key Id
-
Provided to you by Amazon when you signed up for Amazon Web Services
- Secret Access Key
-
Provided to you by Amazon when you signed up for Amazon Web Services
These can be set by telling the plugin to use the same credentials for all requests (i.e. Devpay.access_key_id = ‘ABCD1234’), or each request has optional parameters to allow for per-request credentials to be used.
You will have to register your DevPay products once you have an AWS account. At the moment, each product must be approved prior to use by an AWS employee, this may take up to a few days.
Once you’ve registered your products, you’ll need to record the following for each:
- Product Code
-
An 8-digit alphanumeric code, given to you by Amazon.
- Product Token
-
A 300+ digit hash that begins with {ProductToken}, given to you by Amazon.
- Offer Code
-
An 8-digit alphanumeric code. You’ll want to extract this from the purchase url Amazon provides to you (i.e. aws-portal.amazon.com/gp/aws/user/subscription/index.html?offeringCode=ABCD1234).
Lets say you’re loading up your credentials into a global constant hash called AWS_CREDS, and you’ve stored your product identifiers into an ActiveRecord ‘Product’ model as product_code, product_token, and offer_code, respectively.
You can globally set your credentials, like so:
Devpay.access_key_id = AWS_CREDS[:access_key_id] Devpay.secret_access_key = AWS_CREDS[:secret_access_key]
Or, you can pass your credentials as optional parameters to each Devpay method call you make:
Devpay.active?(pid, product_code, AWS_CREDS[:access_key_id], AWS_CREDS[:secret_access_key])
If you’ve got an object which responds to :offer_code, you can:
<%= link_to 'Buy Now', Devpay.purchase_url_for(product) %>
Otherwise, you can pass the offer code directly:
<%= link_to 'Buy Now', Devpay.purchase_url_for('ABCD1234') %>
See Devpay.purchase_url_for for more information.
Once the user comes back to your site, you’ll get an Activation Key and a Product Code. If you’re unlucky and the redirection failed, you may have to query your customer for these values, directly (probably a pull-down for the products would be better than asking for that one).
In your DevPayResponseController, you could:
# This URL was set in your DevPay product as the return URL (i.e. http://www.example.com/devpay_response/returned) def returned if product = Product.find_by_product_code(params['ProduceCode']) activation_response = Devpay.activate!(params['ActivationKey'], product) PaidUser.create!({ ... :user_token => activation_response.user_token, :persistent_identifier => activation_response.persistent_identifier, ... }) else # Handle unrecognized Product Code here. end end
See Devpay.activate! for more information
You could request a list of all active products which a customer is utilizing by your DevPay services:
Devpay.find_all_product_codes_for(paid_user) #=> [ "ABCD1234", "ABCD1235" ]
In the above example, we’re assuming paid_user responds with the correct persistent identifier when :persistent_identifier is called against it. See Devpay.find_all_product_codes_for for more information.
As Amazon does not alert you to changes in DevPay subscription states (like PayPal’s Instant Payment Notification service, for example), it is up to you to periodically determine the state of the customer’s subscription. This can be done with the following:
Devpay.active?(paid_user, product_paid_for) #=> true Devpay.active?(paid_user, product_not_paid_for) #=> false
In the above example, we’re assuming paid_user responds with the correct persistent identifier when :persistent_identifier is called against it. Further, we’re also assuming that product is an object which responds to :product_code and returns a valid DevPay product code. See Devpay.active? for more information.
All exceptions raised by this plugin inherit from Devpay::Error (a type of Exception). So, in general, a
rescue Devpay::Error => e puts "Devpay had a problem: #{e.class} '#{e.message}'"
Should catch any and all problems raised through the use of this plugin.
More specific errors are nearly always raised, however. Nearly a hundred more specific errors are not publicly documented, but can be found in lib/errors/errors.rb and lib/errors/license_service/errors.rb.
The Amazon License Service (used for activating and verifying DevPay subscriptions) may enter periods of request throttling. During these periods the service will respond with HTTP 503 Service Unavailable. Amazon’s documentation states that you should retry these requests, but fails to stipulate a retry delay. This implementation defaults the delay period to a half-second. :)
More information can be found in the documentation for Devpay::LicenseService.
Copyright © 2008 Nathaniel E. Bibler, released under the MIT license.
Thanks to david@aws and Amazon.com for providing basic Ruby samples for interaction with the Amazon License Service.