-
Notifications
You must be signed in to change notification settings - Fork 312
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
save ct api errors as errored payment records. if request to ct api .…
…create fails, post payment form to payment error endpoint, which saves a new payment to the campaign with status='error' and accompanying information. add jquery function to serialize form object instead of field-by-field assignment move serializeObject() coffeescript definition to main.js.coffee require `params` parameter for basic_payment_info instead of relying on external definition of params delete sensitive attributes specifically from form data before posting errored payment keep track of ct_request_ids for tokenization and charge/auth requests. keep track of errors and timestamps for both.
- Loading branch information
Showing
9 changed files
with
119 additions
and
58 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -92,20 +92,38 @@ Crowdhoster.campaigns = | |
|
||
|
||
cardResponseHandler: (response) -> | ||
form = document.getElementById('payment_form') | ||
request_id_token = response.request_id | ||
|
||
# store our new request_id | ||
previous_token_elem = $("input[name='ct_tokenize_request_id']") | ||
if (previous_token_elem.length > 0) | ||
previous_token_elem.attr('value', request_id_token) | ||
else | ||
request_input = $('<input name="ct_tokenize_request_id" value="' + request_id_token + '" type="hidden" />'); | ||
form.appendChild(request_input[0]) | ||
|
||
$('#client_timestamp').val((new Date()).getTime()) | ||
switch response.status | ||
when 201 | ||
token = response.card.id | ||
input = $('<input name="ct_card_id" value="' + token + '" type="hidden" />'); | ||
form = document.getElementById('payment_form') | ||
form.appendChild(input[0]) | ||
$('#client_timestamp').val((new Date()).getTime()) | ||
card_token = response.card.id | ||
card_input = $('<input name="ct_card_id" value="' + card_token + '" type="hidden" />'); | ||
form.appendChild(card_input[0]) | ||
form.submit() | ||
else | ||
# show an error, re-enable the form submit button, save a record of errored payment | ||
$('#refresh-msg').hide() | ||
$('#errors').append('<p>An error occurred. Please check your credit card details and try again.</p><br><p>If you continue to experience issues, please <a href="mailto:[email protected]?subject=Support request for a payment issue&body=PLEASE DESCRIBE YOUR PAYMENT ISSUES HERE">click here</a> to contact support.</p>') | ||
$('#errors').show() | ||
$('.loader').hide() | ||
$button = $('button[type="submit"]') | ||
$button.attr('disabled', false).html('Confirm payment of $' + $button.attr('data-total') ) | ||
$('#card_number').attr('name', 'card_number'); | ||
$('#security_code').attr('name', 'security_code'); | ||
|
||
data = $(form).serializeObject() | ||
data.ct_tokenize_request_error_id = response.error_id | ||
# make sure we don't have sensitive info | ||
delete data.card_number | ||
delete data.security_code | ||
|
||
error_path = form.getAttribute('data-error-action') | ||
$.post(error_path, data) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,7 +40,7 @@ def checkout_payment | |
if params.has_key?(:reward) && params[:reward].to_i != 0 | ||
begin | ||
@reward = Reward.find(params[:reward]) | ||
rescue => exception | ||
rescue StandardError => exception | ||
redirect_to checkout_amount_url(@campaign), flash: { info: "This reward is unavailable. Please select a different reward!" } | ||
return | ||
end | ||
|
@@ -65,29 +65,12 @@ def checkout_payment | |
end | ||
|
||
def checkout_process | ||
|
||
client_timestamp = params.has_key?(:client_timestamp) ? params[:client_timestamp].to_i : nil | ||
ct_user_id = params[:ct_user_id] | ||
ct_card_id = params[:ct_card_id] | ||
fullname = params[:fullname] | ||
email = params[:email] | ||
billing_postal_code = params[:billing_postal_code] | ||
|
||
#calculate amount and fee in cents | ||
amount = (params[:amount].to_f*100).ceil | ||
fee = calculate_processing_fee(amount) | ||
quantity = params[:quantity].to_i | ||
|
||
#Shipping Info | ||
address_one = params.has_key?(:address_one) ? params[:address_one] : '' | ||
address_two = params.has_key?(:address_two) ? params[:address_two] : '' | ||
city = params.has_key?(:city) ? params[:city] : '' | ||
state = params.has_key?(:state) ? params[:state] : '' | ||
postal_code = params.has_key?(:postal_code) ? params[:postal_code] : '' | ||
country = params.has_key?(:country) ? params[:country] : '' | ||
|
||
#Additional Info | ||
additional_info = params.has_key?(:additional_info) ? params[:additional_info] : '' | ||
|
||
@reward = false | ||
if params[:reward].to_i != 0 | ||
|
@@ -114,20 +97,8 @@ def checkout_process | |
# TODO: Check to make sure the amount is valid here | ||
|
||
# Create the payment record in our db, if there are errors, redirect the user | ||
payment_params = {client_timestamp: client_timestamp, | ||
fullname: fullname, | ||
email: email, | ||
billing_postal_code: billing_postal_code, | ||
quantity: quantity, | ||
address_one: address_one, | ||
address_two: address_two, | ||
city: city, | ||
state: state, | ||
postal_code: postal_code, | ||
country: country, | ||
additional_info: additional_info} | ||
|
||
@payment = @campaign.payments.new(payment_params) | ||
payment_params = basic_payment_info(params) | ||
@payment = @campaign.payments.new(payment_params) | ||
|
||
if !@payment.valid? | ||
error_messages = @payment.errors.full_messages.join(', ') | ||
|
@@ -136,7 +107,7 @@ def checkout_process | |
|
||
# Check if there's an existing payment with the same payment_params and client_timestamp. | ||
# If exists, look at the status to route accordingly. | ||
if !client_timestamp.nil? && existing_payment = @campaign.payments.where(payment_params).first | ||
if !payment_params[:client_timestamp].nil? && (existing_payment = @campaign.payments.where(payment_params).first) | ||
case existing_payment.status | ||
when nil | ||
flash_msg = { info: "Your payment is still being processed! If you have not received a confirmation email, please try again or contact support by emailing [email protected]" } | ||
|
@@ -160,32 +131,39 @@ def checkout_process | |
user_id: ct_user_id, | ||
card_id: ct_card_id, | ||
metadata: { | ||
fullname: fullname, | ||
email: email, | ||
billing_postal_code: billing_postal_code, | ||
quantity: quantity, | ||
fullname: payment_params[:fullname], | ||
email: payment_params[:email], | ||
billing_postal_code: payment_params[:billing_postal_code], | ||
quantity: payment_params[:quantity], | ||
reward: @reward ? @reward.id : 0, | ||
additional_info: additional_info | ||
additional_info: payment_params[:additional_info] | ||
} | ||
} | ||
@campaign.production_flag ? Crowdtilt.production(@settings) : Crowdtilt.sandbox | ||
|
||
logger.info "CROWDTILT API REQUEST: /campaigns/#{@campaign.ct_campaign_id}/payments" | ||
logger.info payment | ||
|
||
response = Crowdtilt.post('/campaigns/' + @campaign.ct_campaign_id + '/payments', {payment: payment}) | ||
|
||
logger.info "CROWDTILT API RESPONSE:" | ||
logger.info response | ||
rescue => exception | ||
@payment.update_attribute(:status, 'error') | ||
logger.info "ERROR WITH POST TO /payments: #{exception.message}" | ||
rescue Crowdtilt::ApiError => api_error | ||
response = api_error.response | ||
logger.error "API ERROR WITH POST TO /payments: #{response.status} #{response.body}" | ||
error_attributes = {status: 'error'} | ||
error_attributes[:ct_charge_request_id] = response.body['request_id'] if response.body['request_id'] | ||
error_attributes[:ct_charge_request_error_id] = response.body['error_id'] if response.body['error_id'] | ||
@payment.update_attributes(error_attributes) | ||
redirect_to checkout_amount_url(@campaign), flash: { error: "There was an error processing your payment. Please try again or contact support by emailing [email protected]" } and return | ||
rescue StandardError => exception | ||
@payment.update_attributes({status: 'error'}) | ||
logger.error "ERROR WITH POST TO /payments: #{exception.message}" | ||
redirect_to checkout_amount_url(@campaign), flash: { error: "There was an error processing your payment. Please try again or contact support by emailing [email protected]" } and return | ||
end | ||
|
||
# Sync payment data | ||
@payment.reward = @reward if @reward | ||
@payment.update_api_data(response['payment']) | ||
@payment.ct_charge_request_id = response['request_id'] | ||
@payment.save | ||
|
||
# Sync campaign data | ||
|
@@ -212,7 +190,17 @@ def checkout_confirmation | |
end | ||
end | ||
|
||
private | ||
def checkout_error | ||
payment_info = basic_payment_info(params) | ||
payment_info[:ct_tokenize_request_error_id] = params[:ct_tokenize_request_error_id] | ||
payment_info[:status] = 'error' | ||
payment = @campaign.payments.new(payment_info) | ||
payment.save | ||
|
||
render nothing: true | ||
end | ||
|
||
private | ||
|
||
def load_campaign | ||
@campaign = Campaign.find(params[:id]) | ||
|
@@ -234,4 +222,26 @@ def check_exp | |
end | ||
end | ||
|
||
# create simple payment hash from params. does not include fees/payment amounts/cc info. | ||
# to be used in response to javascript payment-creation requests (eg checkout_process and checkout_error) | ||
def basic_payment_info(params) | ||
{ | ||
client_timestamp: params.has_key?(:client_timestamp) ? params[:client_timestamp].to_i : nil, | ||
ct_tokenize_request_id: params[:ct_tokenize_request_id], | ||
fullname: params[:fullname], | ||
email: params[:email], | ||
billing_postal_code: params[:billing_postal_code], | ||
quantity: params[:quantity].to_i, | ||
|
||
#Shipping Info | ||
address_one: params.has_key?(:address_one) ? params[:address_one] : '', | ||
address_two: params.has_key?(:address_two) ? params[:address_two] : '', | ||
city: params.has_key?(:city) ? params[:city] : '', | ||
state: params.has_key?(:state) ? params[:state] : '', | ||
postal_code: params.has_key?(:postal_code) ? params[:postal_code] : '', | ||
country: params.has_key?(:country) ? params[:country] : '', | ||
additional_info: params.has_key?(:additional_info) ? params[:additional_info] : '' | ||
} | ||
end | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
class AddErrorsToPayments < ActiveRecord::Migration | ||
def change | ||
add_column :payments, :ct_tokenize_request_id, :string | ||
add_column :payments, :ct_tokenize_request_error_id, :string | ||
add_column :payments, :ct_charge_request_id, :string | ||
add_column :payments, :ct_charge_request_error_id, :string | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters