Chargify API coupon creation - ruby-on-rails

I am currently working on a project and facing a problem with a task. I am trying to randomly generate a 6 digit coupon number and post it to chargify account via there API. If the coupon creation is successful I want the same coupon code to be send to the customer through Email.
As per chargify documentation this is how I should send all the details to chargify from my application :
{"subscription":{
"product_handle":"[#product.handle]",
"customer_attributes":{
"first_name":"Joe",
"last_name":"Blow",
"email":"joe#example.com"
},
"credit_card_attributes":{
"full_number":"1",
"expiration_month":"10",
"expiration_year":"2020"
},
"coupon_code":"6 digit random code"
}}
"""
https://[#subdomain].chargify.com/subscriptions.json.
I am able to create a 6 digit random numerical code by this method :
rand(999999).to_s.center(6, rand(9).to_s).
However this does not seem to be working for me. Any suggestions would be highly appreciated.
Thanks

I'm not part of our tech or dev staff, but I'm 99% sure you can only specify a previously-defined coupon code in that API call. You must define coupon codes in the Chargify admin web interface. In the API call above, you can apply a coupon to the subscription, but the assumption is that you already defined that coupon code in the admin interface.
We will add that capability in the future, but I don't have a specific date for you.
Sorry about that.
--- Lance Walley
--- Chargify

I'm not sure what you're trying to do with your call to center. The most sensible thing to do would be to zero-fill the coupon code. This would do it:
"%06d" % rand(1000000)
This will generate codes such as "664001" and "061532".
Note that you want rand(1000000) rather than rand(999999). That's because rand gives you random integers between 0 and one less than the argument. rand(999999) will only give you random numbers up to 999998.
There's a violation of DRY (Don't Repeat Yourself) in the above code: Both the "06" and the "1000000" depend upon the length of the coupon code. Here's a fix for that:
COUPON_CODE_LENGTH = 6
"%0#{COUPON_CODE_LENGTH}d" % rand(10 ** COUPON_CODE_LENGTH)
Although longer, there's now only one thing to change if the coupon code length should change. The replacement of "magic numbers" with a named constant also helps the code to communicate its intent.

Related

Describe positive test in gherkin language

We're trying to express our requirements following the specification by example approach in the gherkin language. One part of the functionality is a check that under some conditions fails and should otherwise be positive. So we have many scenarios like this:
Given a <condition> //condition changes between scenario
When the check is performed
Then the result is negative
So after describing all the conditions under which check can fail, we would need one positive scenario like:
Given ... // this is what we're missing.
When the check is performed
Then the result is positive
We can't come up with a good way to formulate this one. Please note, this is part of a generic piece of functionality that can be extended by different products, so we can't just write: 'none of the above conditions apply'
Can any of you come up with a formulation that would mean something like Given there are no conflicting conditions, but is more testable?
Perhaps you could just do
When the check is performed
Then it works
It would be much better though if the scenarios talked about what is. Say we are signing in. I'd start with
When I sign in
Then I should be signed in
and then extend that for the sad paths
Given my email is invalid
When I sign in
Then I should not be signed in
All of the above would probably need some background e.g.
Given I am registered.
You don't have to have a given for every scenario
Here is an example imlementation for the Given
module RegistrationStepHelper do
def create_registered_user
# return a user who is registered and can sign in
...
def sign_in_as(user)
end
World RegistrationStepHelper
"Given I am registered" do
#i=create_registered_user
end
When "I sign in" do
sign_in_as: #i
end
...
for a slightly expanded example see here

Stripe webhook for when trial ends

I'm aware of the customer.subscriptions.trial_will_end event. It fires 3 days before a trial ends.
I couldn't find an event that actually fires when the trial is over and the customer hasn't paid. This would be useful to do something simple like this to turn off features:
customer.update_attributes(active_account: false)
Without a webhook like that, I'm looking at scheduling some tasks to check unconfirmed customers periodically and turn off features accordingly. The webhook seems cleaner though and less prone to errors on my side. Is there an event/webhook in line with these goals? FYI, customers don't have to put in a card when they start the trial - so autobilling is not an option.
When the trial period ends, there will be a customer.subscription.updated event and an invoice.created event. An hour (or so) later, you'll then either see an invoice.payment_succeeded event or an invoice.payment_failed event. From those, you'll know whether the payment went through or not.
Cheers,
Larry
PS I work on Support at Stripe.
To add to Larry's answer and share how I got around the lack of a trial ended webhook, here's what I did.
In invoice.payment_failed webhook, I checked:
Is this the first invoice since the subscription start?
Does the customer have any cards saved?
If these checks fail, then I assume the trial has just ended with no billing details entered, and I cancel the subscription.
Example in Python:
# get account from my database
account = models.account.get_one({ 'stripe.id': invoice['customer'] })
# get stripe customer and subscription
customer = stripe.Customer.retrieve(account['stripe']['id'])
subscription = customer.subscriptions.retrieve(account['stripe']['subscription']['id'])
# perform checks
cards_count = customer['sources']['total_count']
now = datetime.fromtimestamp(int(invoice['date']))
trial_start = datetime.fromtimestamp(int(subscription['start']))
days_since = (now - trial_start).days
# cancel if 14 days since subscription start and no billing details added
if days_since == 14 and cards_count < 1:
subscription.delete()
Just add 3 days to the free trial period and use the customer.subscriptions.trial_will_end event and update the subscription with 'trial_end=now'
I think there is another way that can be handled easly. So invoice.payment_failed should be listened, in all invoice related events, inside event.data.object, there is subscription id or subscription object, you should get subscription id and retrieve subscription then you can get both product id and price id.
By price id or by product id you can know current subscription.

Activemerchant not being able to register a bogus card

I am trying to register a test credit card so I could test my application. I am using ActiveMerchant. I have a registration form where user inputs data and then I collect the parameters, and transfer it to payment, but I am only getting a nil as a response.
I have a code like this:
user.rb
def store_credit_card(payment_attributes)
pay = Payment.new(payment_attributes) # this return always nil. Why?
pay.build_contact_info
pay.contact_info.name = name
pay.contact_info.email = email
pay.contact_info.phone = phone
pay.first_name = first_name
pay.last_name = last_name
pay.construct_billing_address(self)
pay.escrow_amount = (0.01).to_money
pay.authorize!
end
I transfer parameters to store_credit_card and they look like this:
payment_attributes
{"card_type"=>"bogus", "card_number"=>"1", "card_expires_month"=>"12", "card_expires_year"=>"2015", "security_code"=>"123"}
But when I call:
pay = Payment.new(payment_attributes)
the pay is always returning a nil.
What should I do in order to make it possible to register a bogus card with ActiveMerchant? And why it is returning a nil?
I am developing in my local development environment. I am using Ubuntu.
Hi have fond an answer to my own question.
After digging in deeper into debugger and stepping into a Payment methods, I have found out that the zip code that I was transferring to ActiveMerchant was reporting an error. But the error itself didn't report on some upper level functions, which is strange. Anyway, the error was that I was sending a json data wich have had
billing_attributes { zipcode: $scope.zipcode}
But when I have looked at my view, I have found that I have used ng-model zipcode
I have accidentally missed _ in the data that is sent to the ActiveMerchant, it should have been:
billing_attributes { zip_code: $scope.zipcode}
All this problem because of typo. Not a big problem, but wanted to note the place where to first look if someone runs on this problem. The data seemed good, but for all others please pay attention if the data you are sending is really formatted like it should.

Devise invite code

I would like to add a invite code requirement for users to register in my application. I investigated the devise_invitable gem for devise and this looks very promising. However, It should not be possible to continuously invite people to the application, like devise_invitable does.
To solve the problem, I need to implant user levels in my application. I found this project on github and now I got the following idea: Once a user registers (invited by another existing user) it starts in level 1 and must complete tasks in order to archive experience points. He works his/her way up to the next level where he can invite 1 new member and then in the next level he can invite 1 other and in the next level, the user can invite 2 members, so on, so on.
I am fairy new to Ruby and I'd like to know how to encomplish this and to know if this is even possible to insert in my users controller.
Thank you for reading and have a nice day.
This should be a fairly straight forward process, as the number of invitations a user has is just an integer stored in your database. It could be something as simple as:
def level_up(level)
self.invitation_limit += level
self.save
end
While a very simple implementation, you just pass in the users level, add it to their current number of invitations, and save the user. It all really depends on how fancy you want to get, but it really comes down to basic math, and saving it to the database.
I'm not sure if this changed since the question was asked in 2012, but devise_invitable has an invitation_limit parameter:
invitation_limit: The number of invitations users can send. The default value of nil means users can send as many invites as they want, there is no limit for any user, invitation_limit column is not used. A setting of 0 means they can't send invitations. A setting n > 0 means they can send n invitations. You can change invitation_limit column for some users so they can send more or less invitations, even with global invitation_limit = 0.
You can see how this parameter is used by looking at the source here. One important part:
# Return true if this user has invitations left to send
def has_invitations_left?
if self.class.invitation_limit.present?
if invitation_limit
return invitation_limit > 0
else
return self.class.invitation_limit > 0
end
else
return true
end
end

Should we use a module with constants to define Rails app API params?

Is there a pattern or best practice in Rails whereby we can specify, in one place, the names/symbols of params that are to be used in the API, so that we can reference it throughout our code and tests?
Our application entails a user passing in parameters to our API via HTTP POST. We use symbols to get at the values as follows:
first_name = params[:firstname]
last_name = params[:lastname]
...
We also set the values of params within our RSpec tests:
params = {
firstname: 'John',
lastname: 'Doe',
...
}
Obviously the above examples are rather simplistic, and in our application we have many more parameters. As such it would be good to have a definitive set of API parameters that can be used. The main benefit being that other developers can then know what parameters are available in the application. Furthermore, we want to safeguard against symbols being typed incorrectly.
My thinking at the minute is to use a module called API with some constants defined:
Module API
FIRST_NAME = :firstname
LAST_NAME = :lastname
...
end
We could then use the module as follows:
first_name = params[API::FIRST_NAME]
last_name = params[API::LAST_NAME]
...
Is this approach even correct? Will there be a performance cost?
Note: We will have the same parameters for every call. Furthermore, the parameters may change as we're currently in the early stages of development and the final set of API fields along with their names haven't been decided on yet.
It is likely your API will not have the same parameters for every call. Also, you probably won't want to change the parameters frequently unless you are the only consumer of your API as changes in the API will break things for your customers. For these reasons I don't think constantizing the params in a module is going to buy you that much.
While there are plenty of places to try to remove redundant code, I'm doubting that your proposed strategy is going to work well for you in the long term. If you find you are repeating yourself a lot in your tests (which certainly happens with APIs), you may want to take a look at rack-test-rest, a gem which can take care of a lot of the pain of API testing.
Basically it makes reasonable assumptions about arguments you don't provide to keep you on track for code http status codes, responses, etc. Hope this helps!

Resources