ActiveMerchant recurring payment - cycles parameters has no effects? - ruby-on-rails

I'm using ActiveMerchant to process a recurring payment. I want the payment to have a limited number of occurence but even if I pass the 'cycles' parameters my payment has no end or any trace of limited number of occurence when I go to see the results of my transaction in the sandbox site ??
Here is my gateway definition :
config.after_initialize do
ActiveMerchant::Billing::Base.mode = :test
paypal_options = {
login: "my_api.ca",
password: "QNBW72G3Q999999",
signature: "AFcWxV21C7fd0v3bYYYRCpSSRl31AmVtuyteuytuetwuytwtwEyY5cTGMA"
}
::MY_PAYMENT_GATEWAY = ActiveMerchant::Billing::PaypalCaGateway.new(paypal_options)
end
And here is my code to process the recurring payment :
response = MY_PAYMENT_GATEWAY.recurring(amount,
#publisher.credit_card.active_merchant_credit_card,
{:ip => request.remote_ip,
:email => current_publisher.user.email,
:period => 'Month',
:frequency => 1,
:cycles => #chosen_package.duration.to_i,
:start_date => Time.now.to_date,
:description => "Try to pay only #chosen_package.duration times !? "})
My comprehension is that the 'cycles' parameters should reflect as a maximum number of charge in sandbox test site but I'm stuck... like like it's not working !?
Any help appreciated ! Thx a lot !
Serge

I have found it by digging into ActiveMerchant source... The good parameters name is :total_billing_cycles, not :cycles as stated in the documentation that I have...
Work like a charm now :-)

Related

Stripe API Invalid Request: Must provide source or customer

I'm working on the Stripe API and building a custom checkout function - My error is specifically telling me I must provide a source or customer. This is my controller for creating charges:
I thought I was successfully creating a source and/or customer with the following code (I also included the post logs on my stripe dashboard)
Stripe::Charge.create(
:amount => #amount,
:currency => 'usd',
:source => params[:stripeToken],
)
Stripe::Customer.create(
:email => params[:stripeEmail],
:source => params[:stripeToken]
)
"error": {
"code": "parameter_missing",
"doc_url": "https://stripe.com/docs/error-codes/parameter-missing",
"message": "Must provide source or customer.",
"type": "invalid_request_error"
}
}
I did go through the docs but I guess I'm still a little lost
Thanks for any assistance!
Update: here is the return of my API POST requests.
Update2: I see that a customer is being created when I send a charge.
Update 3: Source property is set to the stripeToken parameter, representing the payment method provided. The token is automatically created by Checkout. - this seems possibly connected to my issue - maybe it's not correctly posting?
So it did turn out to be a token request - since I was using a test card for test purposes I imagine I had to pass a test token to ensure that the test card would work.
I believe the Rails Params I was using (: source => params[:stripeToken]
) are fine for production but not when checking against given cards. In case someone comes across this as I did (and of course this probably isn't the first time it was asked on SO)
When using the Stripe API you see there is a token tab beside the test card numbers - I assumed those were optional or "for something else" for some reason. THEY ARE NOT.
You'll want to make sure the token matches whatever test card you plan on using (I think)
My Stripe controller now looks like this
Stripe::Charge.create({
:amount => #amount,
:currency => 'usd',
:source => 'tok_visa', #params[:stripeToken] might be for in production I think this is for testing.,
:description => 'Your Donation to Victoria University',
:statement_descriptor => 'Victoria University'
# it seems test tokens must be set as string.
})
Decided to leave my comments in there - because why not?
P.S You'll need different token types for different card payment types. If you switch cards - switch tokens as well !!!! - the tokens are tabbed beside the test card numbers.

Rails PayPal Chained Payment Fees

I have a ruby on rails app; where I wish to have one user be able to pay another user, less 10% 'commission' to the app; My client wants the fees to come out of the 10% the app keeps, for two reasons 1) not nickel/diming their customer 2) after a certain amount of transactions (per month), the percentage apparently gets lower
So, for example, if User 1 pays User 2 $100, I want it to show up as:
User 1 sends $100 to app -> App receives $97.09 ($100 less the fees) ->
App sends 90.00 (90%) to User 2 -> User 2 receives the full $90 (no fees on his side)
However, despite setting the app as the primary receiver, it posted the fees on the secondary receiver, making User 2 pay the fees. I also attempted to set User 2 as the primary, and only send 10% forward to the app afterwards, but then it moved the fees to the primary receiver. The only thing I changed in the code was the percentage being charged, and the primary/secondary emails. My code looks like this:
<!-- app/lib/pay_pal_api.rb -->
require "pp-adaptive"
class PayPalAPI
def self.payment_url(submission)
amount = submission.amount_in_cents.to_f / 100.0
recipient_cut = amount * 0.9
recipient_email = submission.submitter.paypal_email
client.execute(:Pay,
:action_type => "PAY",
:currency_code => "USD",
:cancel_url => "http://localhost:3000/my-studio",
:return_url => "http://localhost:3000/submissions/#{submission.id}",
:receivers => [
{ :email => recipient_email, :amount => recipient_cut, :primary => false },
{ :email => "TestApp#gmail.com", :amount => amount, :primary => true }
]
) do |response|
if response.success?
puts "Pay key: #{response.pay_key}"
# send the user to PayPal to make the payment
# e.g. https://www.sandbox.paypal.com/webscr?cmd=_ap-payment&paykey=abc
return client.payment_url(response)
else
puts "#{response.ack_code}: #{response.error_message}"
end
end
return nil
end
I figured out that in the pp-adaptive gem, it requires this syntax:
:fees_payer => "PRIMARYRECEIVER",
Now it is working perfectly.
Use the feesPayer field and set it to either PRIMARYRECEIVER or SECONDARYONLY depending on who is receiving the payment first. The ruby SDK version of this is fees_payer -- from the API Reference:
feesPayer xs:string (Optional) The payer of PayPal fees. Allowable values are:
SENDER – Sender pays all fees (for personal, implicit simple/parallel payments; do not use for chained or unilateral payments)
PRIMARYRECEIVER – Primary receiver pays all fees (chained payments only)
EACHRECEIVER – Each receiver pays their own fee (default, personal and unilateral payments)
SECONDARYONLY – Secondary receivers pay all fees (use only for chained payments with one secondary receiver)
EG:
client.execute(:Pay,
:action_type => "PAY",
:currency_code => "USD",
:cancel_url => "http://localhost:3000/my-studio",
:return_url => "http://localhost:3000/submissions/#{submission.id}",
:fees_payer => "SECONDARYONLY",
:receivers => [
{ :email => recipient_email, :amount => recipient_cut, :primary => false },
{ :email => "TestApp#gmail.com", :amount => amount, :primary => true }
]
)

Add Discount to Braintree Rails Subscription

I'm trying to add a discount object to a subscription with the braintree-rails gem, but it is not applied. I'm guessing my code must be wrong, but I can't find a working example.
discount = BraintreeRails::Discount.find(params[:subscription_promo])
subscription = #plan.subscriptions.build permitted_params[:subscription]
subscription.discounts << discount
# ...
subscription.save
When I dump discount, it is loaded properly. The subscription is created just fine, but at full price. The discount is not there. How can I add the discount to the subscription?
Update: I tried modifying the direct query, but that has not helped.
#subscription.raw_object.discounts = {add:[{inherited_from_id: discount.id}]}
Update 2: I also ran a direct Braintree request against the API with the request expected of the above code, and it worked. There's something wrong happening between setting it and saving.
Update 3: A workaround is possible by extracting the attributes of the BraintreeRails::Subscription object, using Braintree::Subscription to call the API, and using BraintreeRails::Subscription.find to load it back into the object. This is definitely not optimal, though, since it's not very clean, and requires an extra API call.
gem author here.
Unfortunately neither BraintreeRails nor the Braintree ruby gem supports the subscription.discounts << discount style of adding discounts to subscriptions at the moment.
As you can see in braintree ruby doc, the adding/updating/overriding addon/discounts API is a little too flexible to be wrapped in a single subscription.discounts << discount line.
If your setup of addon/discounts for subscription is simple and doesn't vary much, you can try create one plan for each desired combination, and then use the right plan to create the subscription.
If your setup is quite dynamic(in terms of price, billing cycle, quantity etc), use the Braintree API directly is probably your best option. E.g.:
result = Braintree::Subscription.create(
:payment_method_token => "the_payment_method_token",
:plan_id => "the_plan_id",
:add_ons => {
:add => [
{
:inherited_from_id => "add_on_id_1",
:amount => BigDecimal.new("20.00")
}
],
:update => [
{
:existing_id => "add_on_id_2",
:quantity => 2
}
],
:remove => ["add_on_id_3"]
},
:discounts => {
:add => [
{
:inherited_from_id => "discount_id_1",
:amount => BigDecimal.new("15.00")
}
],
:update => [
{
:existing_id => "discount_id_2",
:quantity => 3
}
],
:remove => ["discount_id_3"]
}
)

Testing association methods with Mocha

I have a Rails app with an Order and a Refund model. Order has_many :refunds. All well and good. I'm trying to write a functional test for refund logic in a controller. Here's what I have right now:
test "should not process partial paypal refund for partially refunded order when refund total plus refund amount is greater than order total" do
set_super_admin_login_credentials
o = Order.new
o.stubs({:id => 1234567, :source => "PayPal", :total => 39.95, :user => users(:dave)})
Order.stubs(:find).with(1234567).returns(o)
get :refund, {:order_id => 1234567}
assert_equal o, assigns(:order)
o.refunds.build.stubs({:amount => 1.0})
o.refunds.build.stubs({:amount => 30.00})
assert_raise do
post :refund, {:order_id => 1234567, :refund_amount => 10.00}
end
end
And in the controller, the refund method looks like this:
def refund
#order = Order.find(params[:order_id])
return if request.get?
amount = params[:refund_amount].to_f
raise "Cannot refund order for more than total" if (#order.refunds.sum(&:amount) + amount)
# Do refund stuff
end
Some notes:
I'm basing the o.refunds.build bit on Ryan Bates' Railscast. If this is not right or no longer relevant, that's helpful information.
I've seen a lot of conflicting information about how to actually do the sum method, some with the & and some without. In script/console, the & blows up but without it, I get an actual sum. In my controller, however, if I switch from &:amount to :amount, I get this message: NoMethodError: undefined method+' for :amount:Symbol`
I feel like there's some conceptual information missing rather than a bug somewhere, so I'll appreciate some pointers.
Finally figured out the issue. I was stubbing an empty association as [] rather than leaving it nil for Rails to handle on some other methods. So, when I would change one, the other would fail. Word to the wise: Enumerable#sum and ActiveRecord::Associations::AssociationCollection#sum take entirely different parameters. :)
So, by changing the stubs to leave off :refunds => [] and using a string for the field name in sum I got things back to normal. So, here's the functional version of the above code:
test "should not process partial paypal refund for partially refunded order when refund total plus refund amount is greater than order total" do
set_super_admin_login_credentials
o = Order.new
o.stubs({:id => 1234567, :source => "PayPal", :total => 39.95, :user => users(:dave)})
Order.stubs(:find).with(1234567).returns(o)
get :refund, {:order_id => 1234567}
assert_equal o, assigns(:order)
o.refunds.build.stubs({:amount => 1.0})
o.refunds.build.stubs({:amount => 30.00})
assert_raise do
post :refund, {:order_id => 1234567, :refund_amount => 10.00}
end
end
def refund
#order = Order.find(params[:order_id])
return if request.get?
amount = params[:refund_amount].to_f
raise "Cannot refund order for more than total" if (#order.refunds.sum('amount') + amount)
# Do refund stuff
end

Authorize.net Parameters with activemerchant

I'm using authorize.net and activemerchant in a rails app.
When I make a purchase authorize.net sends back an email with information about the purchase. I should be able to send them the billing and shipping address information and have that returned in the email, but it's not returning any of the information, obviously I've got the varable names wrong, anybody know what they should be? I've been pouring over the authorize.net api docs and activemerchant's but can't find what I need.
My purchase method on an orders model looks like this:
def purchase
purchase_options = {
:ip => ip_address,
:first_name => first_name,
:last_name => last_name,
:address => billing_street_address,
:city => billing_city,
:state => billing_state,
:country => "US",
:zip => billing_zip,
:ship_to_first_name => first_name,
:ship_to_last_name => last_name,
:ship_to_address => shipping_street_address,
:ship_to_city => shipping_city,
:ship_to_state => shipping_state,
:ship_to_country => "US",
:ship_to_zip => shipping_zip
}
response = GATEWAY.purchase(price_in_cents, credit_card, purchase_options)
# other transaction stuff
response.success?
end
The billing address variables are: x_first_name, x_last_name, x_company, x_address, x_city, x_state, x_zip, x_country, x_phone, x_fax
The shipping variables are: x_ship_to_first_name, x_ship_to_last_name, x_ship_to_company, x_ship_to_address, x_ship_to_city, x_ship_to_state, x_ship_to_zip, x_ship_to_country
You can omit any you do not wish to provide as they are all optional.
You can find these in the AIM Guide on pages 21 - 25.
Install fiddler and look at the raw response you are getting back. authorize.net should give you some hints on what is wrong.

Resources