Skip to content

survival/donation-system

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Build Status Coverage Status Dependency Status Maintainability

Donation System

This is the new donation system for the Survival International site.

Installation

This gem is still under development and in an unstable state. Hence, it is not in rubygems yet.

To install it, add this line to your application's Gemfile:

gem 'donation-system', git: 'https://github.com/survival/donation-system'

and run bundle install. Then append bundle exec in front of any CLI command that requires this gem.

Usage

require 'donation_system'

Data = Struct.new(
  :type, :amount, :currency, :giftaid, :token,
  :name, :email,
  :address, :city, :state, :zip, :country,
  :method
)

data = Data.new(
  'one-off', '10.50', 'gbp', true, 'tok_visa',
  'Jane Doe', 'jane@doe.com',
  'Main Street, 1', 'London', 'London', 'Z1PC0D3', 'UK',
  'stripe'
)

errors = DonationSystem::Payment.attempt(data)

if errors.empty?
  # Do something cool
else
  # Log errors, maybe
end

For PayPal tokens, you need two things: a payment id, and a payer id, hence:

PaypalToken = Struct.new(:payment_id, :payer_id)
token = PaypalToken.new('PAY-13J25512E99606838LJU7M4Y', 'DUFRQ8GWYMJXC')

If there are no errors, it means that:

  • The payment was saved in your Stripe/PayPal account
  • A thank you email was sent to the donor
  • The relevant records were saved in Salesforce (a one-off donation and a new supporter if they didn't exist in the database)

The data that the gem consumes can be anything that responds to at least the following (all these should return strings except the giftaid, which is a boolean):

  • data.type: The type of donation. Valid values: 'one-off' for one-off donations or 'recurring' for recurring dontaions.
  • data.amount: The amount of money to be donated, in currency units. This can be an amount with cents, and will be converted to cents by the gem. For example: 10.50
  • data.currency: The currency that the amount is in, should be a valid ISO 4217 code for currencies and supported by the Money gem, which is used by this gem to handle money. Check here for a list of supported currencies in JSON format
  • data.giftaid: This can be true or false, depending if you allow the donors to Gift Aid their donation to you
  • data.token is a one-use valid token generated by Stripe, or the payment and payer ids generated by PayPal. To get them you need to use their JavaScript libraries in the frontend
  • data.name: the name of the donor
  • data.email: the email of the donor
  • data.address: the address of the donor
  • data.city: the city of the donor
  • data.state: the state of the donor
  • data.zip: the zip code of the donor
  • data.country: the country of the donor
  • data.method: the payment method. Valid values: 'stripe' for Stripe donations or 'paypal' for PayPal donations.

Due to an error thrown by the Money gem (see this issue) you will also have to set this in some relevant place of your application:

I18n.enforce_available_locales = false

Credentials

For the gem to work you need to set some environment variables:

  1. The Stripe API keys of your Stripe account:

    export STRIPE_SECRET_KEY=...
    export STRIPE_PUBLIC_KEY=...
  2. The PayPal API keys of your PayPal account:

    export PAYPAL_MODE=... # 'sandbox' or 'live' only
    export PAYPAL_CLIENT_ID=...
    export PAYPAL_CLIENT_SECRET=...
  3. Your email server data:

    export EMAIL_SERVER=...
    export EMAIL_USERNAME=...
    export EMAIL_PASSWORD=...
  4. Some data from your Salesforce account:

    export SALESFORCE_HOST=...
    export SALESFORCE_USERNAME=...
    export SALESFORCE_PASSWORD=...
    export SALESFORCE_SECURITY_TOKEN=...
    export SALESFORCE_CLIENT_ID=...
    export SALESFORCE_CLIENT_SECRET=...
    export SALESFORCE_API_VERSION=...

NOTE: If the Salesforce password is updated, the security token will have to be updated at the same time. The new token should be provided in the email confirming a change of password.

These variables are set in Travis and Heroku as well so that the tests are green and the applicaiton runs. Everytime you need to add new credentials or update existing ones, remember to also update:

  • The credentials repo (test credentials only)
  • Travis (test credentials only)
  • Heroku staging (production credentials only)
  • Heroku production (poduction credentials only)

Payment flows

Stripe

Use their JavaScript library in the frontend (i.e., Stripe Checkout custom integration) to send the supporter card data and receive a token for that card. Then send the form data and the token to your server and use this gem as in the example above to make the payment.

PayPal

This gem uses the new PayPal express checkout

As opposed to Stripe, the PayPal REST SDK needs an extra previous step where your server creates a payment and returns the id to the checkout.js library. PayPal doesn't allow you to have a custom button anymore, so you have to use their PayPal button, which will be injected in an iframe.

require 'donation_system'

Data = Struct.new(:amount, :currency, :return_url, :cancel_url)
data = PaypalCreatorData.new(
  '12.345', 'gbp', 'https://your-return-url.com', 'https://your-cancel-url.com'
).freeze

result = DonationSystem::PaypalWrapper::PaymentCreator.execute(data)

if result.okay?
  # Pass the payment id (result.item.id ) to the checkout.js library
else
  # Log result.errors, maybe
end

The return url is an endpoint in your web application where PayPal should send the supporter once they have authorized the payment. The cancel url is another endpoint in your application where PayPal will send the user if they cancel the payment.

Once you have passed the payment id to the checkout.js library, a pop-up will open for the donor to authorize the payment. After authorization, Paypal will call the onAuthorize method in the client, where you can then use this gem as in the example above to make the payment.

Development

To initialise the project

You need to have git and bundler installed.

Run the setup script (Beware: Needs permissions to access the credentials repo):

. ./scripts/setup.sh

This script will:

  • download the credentials
  • run the credentials to set the environment
  • run bundle install to install gems.
  • run bundle exec rake to run the tests.

Tests

You need to set your environment by running the credentials. These will be loaded when you run the setup.sh script, but will also be loaded when you run the tests as described below. Make sure your credentials are up to date:

cd credentials && git push origin master && cd -

Currently, when you run the tests, any HTTP request will be recorded once in spec/cassettes, which are then replayed every time you run the tests. So the first time that you run them, they will take a while, but once they are recorded, they should run fast. Also, the first time you run the tests, you need to be connected to the internet.

If you ever get any weird errors when running the tests, try removing the cassettes and then running the tests again:

rm -rf spec/cassettes
bundle exec rake

This folder is safe to delete as it will be regenerated by the tests if it doesn't exist.

To run all tests and rubocop

. ./test.sh

To run one file

bundle exec rspec path/to/test/file.rb && rubocop

To run one test

bundle exec rspec path/to/test/file.rb:TESTLINENUMBER && rubocop

Note: You may see a failing test for setting up Stripe subscriptions if the number of subscriptions for the test user exceeds 25. To solve this error, it is necessary to log on to the Stripe dashboard and delete previous subscriptions for the test user.

To release a new version

To release a new version, update the version number in version.rb, and describe your changes in the changelog. Then run:

git tag -a VERSION_HERE -m "DESCRIPTION_HERE"

which will create a git tag for the version. Then push git commits and tags:

git push origin master --tags

and push the .gem file to rubygems.org:

gem build donation_system.gemspec
gem push donation_system-VERSION_HERE.gem

Testing emails in production

You can send an email to any email address using the test_email_server.rb script, and making sure that you set your environment with an email server, username and password, by running the credentials:

. credentials/.email_server
bundle exec ruby scripts/test_email_server.rb 'YOUR_EMAIL_HERE'

Contributing

Please check out our contribution guides and our code of conduct

License

License MIT License