Credit Card Charging

RdbHost ordinarily delivers the results of a query as an XML, JSON or binary page, where the data is just formatted per the indicated format and delivered to the client. If you use the charge mode, though, the server processes the results before responding. In this case, the server interprets the data content as one or more charges to process, and presents the requester with a different set of data, representing the status of each charge request.

Query Result Data

Each record from the query result dataset must contain the following fields:

Mode Parameter

The charging mode is requested with the mode parameter, using the value 'charge'.

A query example:

SELECT 'cPv~~~~~~~~~~~~~~~~~~~34PwL54SC' AS apikey, 'stripe' AS service, 'charge' AS action, 100 AS amount, '4242424242424242' AS cc_num, '123' AS cc_cvc, '01' AS cc_exp_mon, '2015' AS cc_exp_yr, 'usd' AS currency, 01 AS idx, 'INSERT INTO "charges" (idx, id) VALUES({idx}, {id})' AS postcall, 'INSERT INTO "badcharges" (idx) VALUES({idx})' AS errcall

This query, submitted to rdbhost.com with a mode='charge', would result in a charge being run against the cc_num 4242424242424242, using the stripe account given by the apikey value. That particular number is a test number, and would succeed when run against a valid test apikey. There is a valid test apikey for every free stripe account. The postcall and errcall lines get called if the charge succeeds or fails, respectively. They expect the preexistence of appropriate "charges" and "badcharges" tables with appropriate privileges.

The above query is not ideal, in that it potentially exposes the apikey. One way to address that risk is to keep the apikey in a table (with appropriate privileges), and select it. We can also use substitution tokens to make the query reusable with user provided data for the field values.

SELECT keytable.apikey AS apikey, 'stripe' AS service, 'charge' AS action, %s AS amount, %s AS cc_num, %s AS cc_cvc, %s AS cc_exp_mon, %s AS cc_exp_yr, 'usd' AS currency, 01 AS idx, 'INSERT INTO "charges" (idx, id) VALUES({idx}, {id})' AS postcall, 'INSERT INTO "badcharges" (idx) VALUES({idx})' AS errcall FROM keytable

This query, submitted with argument fields for the missing values, with a mode='charge' parameter, would work as above. An html form to charge a user (say a donation form) might resemble:

<form id=donation> Amount: <input name='arg000'><br/> CC Number: <input name='arg001'><br/> CVC code: <input name='arg002'><br/> CC expiration mo/yr: <input name='arg003'>/<input name='arg004'><br/> <input type=submit> </form>

The results returned by the credit card processing service are available for use in the postcall code. The available elements are:

{cc_um} The credit card number.
{cc_exp_yr} Credit card expiration year
{cc_exp_mon} Credit card expiration month
{cc_cvc} Credit card cvc value
{amount} Amount of charge attempted, as integer.
{currency} Currency
{idx} Value submitted as idx; nominally a unique identifier for the request.
{fee} Fee paid to cc processor, as integer cents.
{paid} Was amount paid? 'true' or 'false'
{refunded} Was amount refunded? 'true' or 'false'
{id} Transaction id. Use to refund or track transaction.
{created} Date/time stamp.
{error} Text error message (avail on failures)
{card[type]} Type of credit card. ('discover','visa',etc)
{card[cvc_check]} Result of cvc_check. ('pass','fail', or 'unchecked')
{card[address_line1_check]} Result of address line check. ('pass','fail', or 'unchecked')
{card[address_zip_check]} Result of address zip check. ('pass','fail', or 'unchecked')
{card[last4]} Last 4 digits of cc_num
{card[country]} Country of card

Charge queries can be stored in the preauth_queries table, and the mode recorded there is not overridable. A pre-authorized query can be saved and made available to an anonymous user to run charges without disclosing the apikey to that anonymous user.

Stripe.com allows for selecting how strictly to evaluate charge approval (for example, cvc ommissions can be ignored). RdbHost uses the strictest variants.

Result Page to Client

If the query succeeds, and the data includes the necessary fields (as described above), the server will run a charge for each record, via the stripe.com server, and record 'Success' or an error message for each record. The result page will be a list of 2-tuples, including the unique 'Idx' value and the result for each charge, formatted per the format parameter.

If the query fails altogether, without getting a response from the charging api, the error message sent to the client browser is the same as if mode were not specified. ie: a json error message about why the query failed.