sallie_mae_gateway 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.md +94 -0
- data/Rakefile +37 -0
- data/app/helpers/sallie_mae_helper.rb +17 -0
- data/app/models/sallie_mae_gateway/line_item.rb +11 -0
- data/app/models/sallie_mae_gateway/payment.rb +23 -0
- data/app/models/sallie_mae_gateway/response.rb +79 -0
- data/app/models/sallie_mae_gateway/student.rb +11 -0
- data/app/views/sallie_mae/_sallie_mae_form.html.haml +49 -0
- data/config/initializers/config.rb +7 -0
- data/config/routes.rb +2 -0
- data/config/salliemae.yml +13 -0
- data/lib/sallie_mae_gateway.rb +5 -0
- data/lib/sallie_mae_gateway/engine.rb +10 -0
- data/lib/sallie_mae_gateway/version.rb +3 -0
- data/lib/tasks/sallie_mae_gateway_tasks.rake +4 -0
- metadata +106 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2011 Southern Illinois University Board of Trustees
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
SallieMae Electronic Payment Gateway SSO
|
2
|
+
===
|
3
|
+
|
4
|
+
A simple collection of models and helpers that speeds up the implementation of SallieMae EPG SSO within a **Rails 3.1.x** application.
|
5
|
+
|
6
|
+
Installation
|
7
|
+
===
|
8
|
+
In your _Gemfile_ add the following line
|
9
|
+
|
10
|
+
gem 'sallie_mae_gateway', '~> 0.0.1'
|
11
|
+
|
12
|
+
Configuration
|
13
|
+
===
|
14
|
+
You must create a YAML configuration file in your _config_ directory with the filename _salliemae.yml_. An example is included in the gem _config_ directory and is a good starting point.
|
15
|
+
|
16
|
+
$ cat config/salliemae.yml
|
17
|
+
|
18
|
+
default: &default
|
19
|
+
url: 'https://stg.bosebill.salliemae.com/NetPay/Products/Gateway.aspx'
|
20
|
+
product_id: "0000"
|
21
|
+
school_id: "123456789"
|
22
|
+
postback_url: 'http://localhost:3000/sallie_mae/process'
|
23
|
+
finish_url: 'http://localhost:3000/sallie_mae/process'
|
24
|
+
cancel_url: 'http://localhost:3000/sallie_mae/cancel'
|
25
|
+
development:
|
26
|
+
<<: *default
|
27
|
+
test:
|
28
|
+
<<: *default
|
29
|
+
production:
|
30
|
+
<<: *default
|
31
|
+
|
32
|
+
Example Usage
|
33
|
+
===
|
34
|
+
You'll use these models to create the payment object within your controller and to process the response from SallieMae. There are a couple of helpers to speed up creating your payment form within your views. That's it!
|
35
|
+
This gem makes no assumptions about your payment processing system and does not contain any controllers to handle the creation or handling of responses.
|
36
|
+
|
37
|
+
Controller - New Payment
|
38
|
+
---
|
39
|
+
Start in your controller by instantiating a _SallieMaeGateway::Student_ and at least one _SallieMaeGateway::LineItem_ objects. Then create a _SallieMaeGateway::Payment_ object providing your _student_ and *line_items*.
|
40
|
+
|
41
|
+
$ cat app/controllers/payment_controller.rb
|
42
|
+
.
|
43
|
+
.
|
44
|
+
.
|
45
|
+
def new
|
46
|
+
student = Student.find(123)
|
47
|
+
student_for_payment = SallieMaeGateway::Student.new(account: student.id, first_name: student.first_name, last_name: student.last_name, email: student.email )
|
48
|
+
line_items = [
|
49
|
+
SalieMaeGateway::LineItem.new(type: "AF", description: "Application Fee", amount: 75.00),
|
50
|
+
SalieMaeGateway::LineItem.new(type: "SCD", description: "Student Card Deposit", amount: 150.00)
|
51
|
+
]
|
52
|
+
@payment = SallieMaeGateway::Payment.new(student: student_for_payment, line_items: line_items)
|
53
|
+
end
|
54
|
+
.
|
55
|
+
.
|
56
|
+
.
|
57
|
+
View
|
58
|
+
---
|
59
|
+
In the view you can use the provided helpers to generate a simple button that can be clicked to take them to the payment gateway or you can display a read only form with more details
|
60
|
+
|
61
|
+
$ cat app/views/payment/new.html.erb
|
62
|
+
|
63
|
+
# This helper displays the button
|
64
|
+
<%= sallie_mae_button @payment %>
|
65
|
+
|
66
|
+
# This helper displays the read-only form
|
67
|
+
<%= sallie_mae_form @payment %>
|
68
|
+
Controller - Process Response
|
69
|
+
---
|
70
|
+
You'll need to pass the response provided by SallieMae to the _SallieMaeGateway::Response_ object. You can then access the details from that instance, passing it to a model in your application or doing additional processing on .
|
71
|
+
|
72
|
+
$ cat app/controllers/payment_controller.rb
|
73
|
+
.
|
74
|
+
.
|
75
|
+
.
|
76
|
+
def process
|
77
|
+
@sallie_mae_response = SallieMaeResponse::Response.new(params)
|
78
|
+
# Use this object to access the response data, for example:
|
79
|
+
transaction = Transaction.new
|
80
|
+
transaction.transaction_id = @sallie_mae_response.transaction_id
|
81
|
+
transaction.amount = @sallie_mae_response.amount_paid
|
82
|
+
transaction.save
|
83
|
+
end
|
84
|
+
.
|
85
|
+
.
|
86
|
+
.
|
87
|
+
|
88
|
+
|
89
|
+
|
90
|
+
Tests
|
91
|
+
===
|
92
|
+
Tests are written using Steak and RSpec 2 and are included in the _spec_ directory.
|
93
|
+
|
94
|
+
This project uses MIT-LICENSE.
|
data/Rakefile
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rdoc/task'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rdoc/rdoc'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
RDoc::Task = Rake::RDocTask
|
13
|
+
end
|
14
|
+
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'SallieMaeGateway'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
24
|
+
load 'rails/tasks/engine.rake'
|
25
|
+
|
26
|
+
|
27
|
+
Bundler::GemHelper.install_tasks
|
28
|
+
|
29
|
+
require 'rubygems'
|
30
|
+
require 'rspec'
|
31
|
+
|
32
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
33
|
+
t.spec_files = FileList['*_spec.rb']
|
34
|
+
t.options = '-v'
|
35
|
+
end
|
36
|
+
|
37
|
+
task :default => :spec
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module SallieMaeHelper
|
2
|
+
def sallie_mae_button(payment,options={})
|
3
|
+
options[:hide_form] = true
|
4
|
+
options[:student_firstname] = false
|
5
|
+
options[:student_lastname] = false
|
6
|
+
options[:student_email] = false
|
7
|
+
options[:account] = false
|
8
|
+
options[:line_items] = false
|
9
|
+
sallie_mae_form(payment,options)
|
10
|
+
end
|
11
|
+
|
12
|
+
def sallie_mae_form(payment,options={})
|
13
|
+
options[:button_label] ||= "Make a Payment"
|
14
|
+
options[:legend_text] ||= ""
|
15
|
+
render 'sallie_mae/sallie_mae_form', payment: payment, options: options
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module SallieMaeGateway
|
2
|
+
class Payment
|
3
|
+
CHECKING, CREDIT_CARD, DEBIT_CARD, SAVINGS = 'A', 'C', 'D', 'S'
|
4
|
+
|
5
|
+
attr_accessor :student, :line_items
|
6
|
+
attr_accessor :school_id, :postback_url, :finish_url, :cancel_url, :user_def1, :user_def2, :allow_edit, :payment_type
|
7
|
+
|
8
|
+
def initialize(args)
|
9
|
+
if args.is_a? Hash
|
10
|
+
args[:allow_edit] ||= false
|
11
|
+
args[:payment_type] ||= CREDIT_CARD
|
12
|
+
args.each { |key, value|
|
13
|
+
instance_variable_set "@#{key}", value
|
14
|
+
}
|
15
|
+
end
|
16
|
+
@line_items ||= []
|
17
|
+
end
|
18
|
+
|
19
|
+
def total_amount
|
20
|
+
@line_items.reduce(0.0) { |sum, item| sum += item.amount }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module SallieMaeGateway
|
2
|
+
class Response
|
3
|
+
SUCCESS_INDICATOR = {
|
4
|
+
'A' => 'Credit Card Accepted',
|
5
|
+
'S' => 'ACH Scheduled',
|
6
|
+
'D' => 'Declined',
|
7
|
+
'P' => 'Pending',
|
8
|
+
'C' => 'Canceled'
|
9
|
+
}.freeze
|
10
|
+
|
11
|
+
PAYMENT_INDICATOR = {
|
12
|
+
'AX' => 'American Express',
|
13
|
+
'DI' => 'Discover Card',
|
14
|
+
'DN' => 'Diners Club',
|
15
|
+
'CB' => 'Carte Blanche',
|
16
|
+
'JC' => 'JCB',
|
17
|
+
'MC' => 'Master Card',
|
18
|
+
'VI' => 'Visa',
|
19
|
+
'CK' => 'Checking Account',
|
20
|
+
'SV' => 'Savings Account'
|
21
|
+
}.freeze
|
22
|
+
|
23
|
+
CANCELED, PENDING, SUCCESS, SCHEDULED = 'C', 'P', 'A', 'S'
|
24
|
+
|
25
|
+
|
26
|
+
attr_reader :raw_response
|
27
|
+
|
28
|
+
def initialize(args=nil)
|
29
|
+
if args.is_a? Hash
|
30
|
+
@raw_response = args
|
31
|
+
process_response
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def raw_response=(response)
|
36
|
+
@raw_response = response
|
37
|
+
process_response
|
38
|
+
end
|
39
|
+
|
40
|
+
def canceled?
|
41
|
+
raise 'Unable to determine status. Has a response been provided?' unless self.respond_to? :success_indicator
|
42
|
+
self.success_indicator.eql? CANCELED
|
43
|
+
end
|
44
|
+
|
45
|
+
def success?
|
46
|
+
raise 'Unable to determine status. Has a response been provided?' unless self.respond_to? :success_indicator
|
47
|
+
self.success_indicator.eql? SUCCESS
|
48
|
+
end
|
49
|
+
|
50
|
+
def success_message
|
51
|
+
raise 'Unable to determine status. Has a response been provided?' unless self.respond_to? :success_indicator
|
52
|
+
SUCCESS_INDICATOR[self.success_indicator]
|
53
|
+
end
|
54
|
+
|
55
|
+
def payment_method
|
56
|
+
raise 'Unable to determine payment method. Has a response been provided?' unless self.respond_to? :pmt_indicator
|
57
|
+
PAYMENT_INDICATOR[self.pmt_indicator]
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
def process_response
|
62
|
+
raise TypeError, "Unable to locate the raw response from SallieMae. Has it been provided?" if @raw_response.nil?
|
63
|
+
@raw_response.each_pair do |key, value|
|
64
|
+
key = key.downcase
|
65
|
+
unless self.respond_to? key
|
66
|
+
class_eval do
|
67
|
+
define_method key do
|
68
|
+
self.instance_variable_get "@#{key}"
|
69
|
+
end
|
70
|
+
define_method "#{key}=" do |new_value|
|
71
|
+
self.instance_variable_set "@#{key}", new_value
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
self.send "#{key}=", value
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
= form_tag SALLIE_MAE_CONFIG["url"], :id => 'sallie_mae_gateway_form' do
|
2
|
+
= hidden_field_tag 'SCHOOL_ID', SALLIE_MAE_CONFIG["school_id"]
|
3
|
+
= hidden_field_tag 'ALT_OTPSSO_URL', SALLIE_MAE_CONFIG["postback_url"]
|
4
|
+
= hidden_field_tag 'FINISH_URL', SALLIE_MAE_CONFIG["finish_url"]
|
5
|
+
= hidden_field_tag 'CANCEL_URL', SALLIE_MAE_CONFIG["cancel_url"]
|
6
|
+
= hidden_field_tag 'PMT_INDICATOR', payment.payment_type
|
7
|
+
= hidden_field_tag 'EDIT_INDICATOR', payment.allow_edit ? "Y" : "N"
|
8
|
+
- if options[:account].eql? false
|
9
|
+
= hidden_field_tag 'ACCOUNT', payment.student.account
|
10
|
+
- else
|
11
|
+
%p
|
12
|
+
= label_tag 'ACCOUNT', 'Student Account', :class => 'label'
|
13
|
+
= text_field_tag 'ACCOUNT', payment.student.account, :class => 'text_field', :readonly => 'readonly'
|
14
|
+
- if options[:student_firstname].eql? false
|
15
|
+
= hidden_field_tag 'STUDENT_FIRSTNAME', payment.student.first_name
|
16
|
+
- else
|
17
|
+
%p
|
18
|
+
= label_tag 'STUDENT_FIRSTNAME', 'Student First Name', :class => 'label'
|
19
|
+
= text_field_tag 'STUDENT_FIRSTNAME', payment.student.first_name, :class => 'text_field', :readonly => 'readonly'
|
20
|
+
- if options[:student_lastname].eql? false
|
21
|
+
= hidden_field_tag 'STUDENT_LASTNAME', payment.student.last_name
|
22
|
+
- else
|
23
|
+
%p
|
24
|
+
= label_tag 'STUDENT_LASTNAME', 'Student Last Name', :class => 'label'
|
25
|
+
= text_field_tag 'STUDENT_LASTNAME', payment.student.last_name, :class => 'text_field', :readonly => 'readonly'
|
26
|
+
- if options[:student_email].eql? false
|
27
|
+
= hidden_field_tag 'STUDENT_EMAIL_1', payment.student.email
|
28
|
+
- else
|
29
|
+
%p
|
30
|
+
= label_tag 'STUDENT_EMAIL', 'Student Email', :class => 'label'
|
31
|
+
= text_field_tag 'STUDENT_EMAIL_1', payment.student.email, :class => 'text_field', :readonly => 'readonly'
|
32
|
+
- unless options[:line_items].eql? false
|
33
|
+
%table#sallie_mae_line_items.table
|
34
|
+
%tr
|
35
|
+
%th Description
|
36
|
+
%th Amount
|
37
|
+
- payment.line_items.each_with_index do |line_item, i|
|
38
|
+
%tr{class: cycle('odd','even', name: 'sallie_mae_line_items')}
|
39
|
+
%td= line_item.description
|
40
|
+
%td.currency= "$" + "%.02f" % line_item.amount
|
41
|
+
%tr.total
|
42
|
+
%td.total Total
|
43
|
+
%td.currency= "$" + "%.02f" % payment.line_items.reduce(0.0) { |sum, item| sum += item.amount }
|
44
|
+
- payment.line_items.each_with_index do |line_item, i|
|
45
|
+
- item = (i.eql? 0) ? nil : i+1
|
46
|
+
= hidden_field_tag "PMT_TYPE#{item}", line_item.type
|
47
|
+
= hidden_field_tag "PMT_TYPE_DESC#{item}", line_item.description
|
48
|
+
= hidden_field_tag "AMOUNT_PAID#{item}", ("%.02f" % line_item.amount)
|
49
|
+
= submit_tag options[:button_label]
|
data/config/routes.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
default: &default
|
2
|
+
url: 'https://stg.bosebill.salliemae.com/NetPay/Products/Gateway.aspx'
|
3
|
+
product_id: "0000"
|
4
|
+
school_id: "123456789"
|
5
|
+
postback_url: 'http://localhost:3000/sallie_mae/process'
|
6
|
+
finish_url: 'http://localhost:3000/sallie_mae/process'
|
7
|
+
cancel_url: 'http://localhost:3000/sallie_mae/cancel'
|
8
|
+
development:
|
9
|
+
<<: *default
|
10
|
+
test:
|
11
|
+
<<: *default
|
12
|
+
production:
|
13
|
+
<<: *default
|
metadata
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sallie_mae_gateway
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Daniel Reedy
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-11-02 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rails
|
16
|
+
requirement: &70135701650540 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 3.1.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70135701650540
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: haml
|
27
|
+
requirement: &70135701650040 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70135701650040
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: sqlite3
|
38
|
+
requirement: &70135701649580 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70135701649580
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: steak
|
49
|
+
requirement: &70135701648960 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.0.0
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70135701648960
|
58
|
+
description: To accommodate the SSO functionality of SallieMae Business Office Solutions
|
59
|
+
Electronic Payment Gateway within a Rails applicaiton.
|
60
|
+
email:
|
61
|
+
- dreedy@housing.siu.edu
|
62
|
+
executables: []
|
63
|
+
extensions: []
|
64
|
+
extra_rdoc_files: []
|
65
|
+
files:
|
66
|
+
- app/helpers/sallie_mae_helper.rb
|
67
|
+
- app/models/sallie_mae_gateway/line_item.rb
|
68
|
+
- app/models/sallie_mae_gateway/payment.rb
|
69
|
+
- app/models/sallie_mae_gateway/response.rb
|
70
|
+
- app/models/sallie_mae_gateway/student.rb
|
71
|
+
- app/views/sallie_mae/_sallie_mae_form.html.haml
|
72
|
+
- config/initializers/config.rb
|
73
|
+
- config/routes.rb
|
74
|
+
- config/salliemae.yml
|
75
|
+
- lib/sallie_mae_gateway/engine.rb
|
76
|
+
- lib/sallie_mae_gateway/version.rb
|
77
|
+
- lib/sallie_mae_gateway.rb
|
78
|
+
- lib/tasks/sallie_mae_gateway_tasks.rake
|
79
|
+
- MIT-LICENSE
|
80
|
+
- Rakefile
|
81
|
+
- README.md
|
82
|
+
homepage: http://www.housing.siu.edu
|
83
|
+
licenses: []
|
84
|
+
post_install_message:
|
85
|
+
rdoc_options: []
|
86
|
+
require_paths:
|
87
|
+
- lib
|
88
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
|
+
none: false
|
96
|
+
requirements:
|
97
|
+
- - ! '>='
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
requirements: []
|
101
|
+
rubyforge_project:
|
102
|
+
rubygems_version: 1.8.6
|
103
|
+
signing_key:
|
104
|
+
specification_version: 3
|
105
|
+
summary: SallieMae Electronic Payment Gateway SSO Integration
|
106
|
+
test_files: []
|