Class: Paypkg
- Inherits:
-
Object
- Object
- Paypkg
- Includes:
- JSON, Version
- Defined in:
- lib/paypkg.rb,
lib/paypkg.rb,
lib/paypkg/refund-sale.rb,
lib/paypkg/accept-pp-payment.rb,
lib/paypkg/store-credit-card.rb,
lib/paypkg/delete-credit-card.rb,
lib/paypkg/retrieve-credit-card.rb,
lib/paypkg/validate-credit-card.rb,
lib/paypkg/accept-stored-cc-payment.rb,
lib/paypkg/retrieve-payment-resource.rb,
lib/paypkg/retrieve-sale-transaction.rb,
lib/paypkg/accept-tendered-cc-payment.rb,
lib/paypkg/retrieve-refund-transaction.rb
Overview
Retrieve Refund Transaction ###
Constant Summary
Constants included from Version
Version::MODIFIED, Version::VERSION
Instance Attribute Summary collapse
-
#hash ⇒ Object
readonly
Returns the value of attribute hash.
-
#json ⇒ Object
readonly
Returns the value of attribute json.
-
#link ⇒ Object
readonly
Returns the value of attribute link.
-
#mode ⇒ Object
readonly
Returns the value of attribute mode.
-
#request ⇒ Object
readonly
Returns the value of attribute request.
-
#status ⇒ Object
readonly
Returns the value of attribute status.
Instance Method Summary collapse
-
#accept_pp_payment(amount, desc, approved_url, cancelled_url) ⇒ Object
This method is intended for use when you want to charge a user’s PayPay account.
-
#accept_stored_cc_payment(card_id, amount, desc, email, payer_id) ⇒ Object
This method is intended for use when you want to charge a card stored in the vault.
-
#accept_tendered_cc_payment(type, number, expire_month, expire_year, cvv2, first_name, last_name, amount, desc) ⇒ Object
This call is intended for use when the card is presented, but not stored in the vault.
-
#call_paypal(endpoint, data = nil, options = {reset: :yes, method: :get}) ⇒ json String, ...
The call_paypal method is used to call PayPal with a json string, and return the response json string and HTTP exit code – The json response, the response converted into a hash, and the status code are all stored – some calls (like validate_credit_card) actually make two PayPal calls, so the json, hash, and status are arrays.
-
#delete_credit_card(vault_id) ⇒ Object
Delete a card from the vault.
-
#error_data ⇒ Object
This method collects the response data in such a way as to guarantee valid Ruby stuctures will be generated, i.e., you won’t get a runtime error because of nil, etc.
-
#execute_payment(payer_id, payment_id) ⇒ Object
This is executed by the code at the ‘accepted’ url.
-
#refund_sale(sale_id, amount) ⇒ Object
You can request a partial or full refund of a previous sale.
-
#response ⇒ PaypkgResponse Instance
This is a getter which is used to obtain the PaypkgResponse Object from the hash.
-
#retrieve_credit_card(vault_id) ⇒ Hash
Retrieve a card from the vault.
-
#retrieve_payment_resource(payment_id) ⇒ json String
Use the payment_id to look up a payment.
-
#retrieve_refund_transaction(refund_id) ⇒ json String
Use the refund_id to look up the refund.
-
#retrieve_sale_transaction(sale_id) ⇒ json String
Use the sale_id to look up the sale.
-
#store_credit_card(type, number, expire_month, expire_year, cvv2, first_name, last_name, line1, line2, city, state, postal_code, country_code, payer_id) ⇒ String
Store a credit card on the PalPal servers (in the vault, as the refer to it).
-
#validate_credit_card(type, number, expire_month, expire_year, cvv2, first_name, last_name, line1, city, state, postal_code, country_code) ⇒ Object
Validate a credit card by charging $0.01, then voiding the authorization.
Instance Attribute Details
#hash ⇒ Object (readonly)
Returns the value of attribute hash.
45 46 47 |
# File 'lib/paypkg.rb', line 45 def hash @hash end |
#json ⇒ Object (readonly)
Returns the value of attribute json.
45 46 47 |
# File 'lib/paypkg.rb', line 45 def json @json end |
#link ⇒ Object (readonly)
Returns the value of attribute link.
45 46 47 |
# File 'lib/paypkg.rb', line 45 def link @link end |
#mode ⇒ Object (readonly)
Returns the value of attribute mode.
45 46 47 |
# File 'lib/paypkg.rb', line 45 def mode @mode end |
#request ⇒ Object (readonly)
Returns the value of attribute request.
45 46 47 |
# File 'lib/paypkg.rb', line 45 def request @request end |
#status ⇒ Object (readonly)
Returns the value of attribute status.
45 46 47 |
# File 'lib/paypkg.rb', line 45 def status @status end |
Instance Method Details
#accept_pp_payment(amount, desc, approved_url, cancelled_url) ⇒ Object
This method is intended for use when you want to charge a user’s PayPay account. The user will be required to give an on-line approval.
The two urls shown here must be in your controller, and in your config/routes.rb file. See the execute_payment method below. You should store the payment_id you get back from this call (in session here).
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/paypkg/accept-pp-payment.rb', line 19 def accept_pp_payment(amount, desc, approved_url, cancelled_url) set_access_token # we need this here to set the @website formatted_amount = "%0.2f"%amount json, status = call_paypal("/v1/payments/payment", "{ 'intent':'sale', 'redirect_urls':{ 'return_url':'#{@website}/#{approved_url}/', 'cancel_url':'#{@website}/#{cancelled_url}/' }, 'payer':{ 'payment_method':'paypal' }, 'transactions':[ { 'amount':{ 'total':'#{formatted_amount}', 'currency':'USD' }, 'description':'#{desc}' } ] }") if (@status.last=='201') && (@hash.last[:state]=='created') @session[:payment_id] = @hash.last[:id] @link = @hash.last[:links].select{|link| link[:rel]=='approval_url'}[0][:href] return true else return false end end |
#accept_stored_cc_payment(card_id, amount, desc, email, payer_id) ⇒ Object
This method is intended for use when you want to charge a card stored in the vault.
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/paypkg/accept-stored-cc-payment.rb', line 13 def accept_stored_cc_payment(card_id, amount, desc, email, payer_id) formatted_amount = "%0.2f"%amount call_paypal("/v1/payments/payment", "{ 'intent':'sale', 'payer':{ 'payment_method':'credit_card', 'payer_info':{ 'email':'#{email}' }, 'funding_instruments':[ { 'credit_card_token':{ 'credit_card_id':'#{card_id}', 'payer_id':'#{payer_id}' } } ] }, 'transactions':[ { 'amount':{ 'total':'#{formatted_amount}', 'currency':'USD' }, 'description':'#{desc}' } ] }") return (@status.last=='201') && (@hash.last[:state]=='approved') end |
#accept_tendered_cc_payment(type, number, expire_month, expire_year, cvv2, first_name, last_name, amount, desc) ⇒ Object
This call is intended for use when the card is presented, but not stored in the vault.
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/paypkg/accept-tendered-cc-payment.rb', line 16 def accept_tendered_cc_payment(type, number, expire_month, expire_year, cvv2, first_name, last_name, amount, desc) formatted_amount = "%0.2f"%amount json = "{ 'intent':'sale', 'payer':{ 'payment_method':'credit_card', 'funding_instruments':[ { 'credit_card':{ 'type':'#{type}', 'number':'#{number}'," json << " 'cvv2':'#{cvv2}'," if cvv2 json << " 'first_name':'#{first_name}'," if first_name json << " 'last_name':'#{last_name}'," if last_name json << " 'expire_month':'#{expire_month}', 'expire_year':'#{expire_year}' } } ] }, 'transactions':[ { 'amount':{ 'total':'#{formatted_amount}', 'currency':'USD' }, 'description':'#{desc}' } ] }" call_paypal("/v1/payments/payment", json) return (@status.last=='201') && (@hash.last[:state]=='approved') end |
#call_paypal(endpoint, data = nil, options = {reset: :yes, method: :get}) ⇒ json String, ...
The call_paypal method is used to call PayPal with a json string, and return the response json string and HTTP exit code – The json response, the response converted into a hash, and the status code are all stored – some calls (like validate_credit_card) actually make two PayPal calls, so the json, hash, and status are arrays
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/paypkg.rb', line 121 def call_paypal(endpoint, data=nil, ={reset: :yes, method: :get}) set_access_token = {:reset => :yes, :method => :get}.merge() if [:reset]==:yes @json = [] @hash = [] @status = [] @request = [] end case when [:method]==:delete request = Net::HTTP::Delete.new(endpoint) when [:method]==:post || data # a json string request = Net::HTTP::Post.new(endpoint) when [:method]==:get request = Net::HTTP::Get.new(endpoint) end @request << data request.add_field("Content-Type","application/json") request.add_field("Authorization", "Bearer #{@access_token}") request.body = data.gsub("'",'"') if data response = @http.request(request) response.body = nil if response.body.empty? @json << response.body @hash << if response.body then JSON.parse(response.body, :symbolize_names=>true) else nil end @status << response.code end |
#delete_credit_card(vault_id) ⇒ Object
Delete a card from the vault. If Paypal already removed the card because it expired, just ignore the error. NO JSON STRING is returned with this call.
9 10 11 12 |
# File 'lib/paypkg/delete-credit-card.rb', line 9 def delete_credit_card(vault_id) call_paypal("/v1/vault/credit-card/#{vault_id}", nil, :method => :delete) return (@status.last=='204') && (@hash.last==nil) end |
#error_data ⇒ Object
This method collects the response data in such a way as to guarantee valid Ruby stuctures will be generated, i.e., you won’t get a runtime error because of nil, etc.
It produces 3 outputs:
(1) A non-nil error hash
{
:name => "VALIDATION_ERROR",
:details => [
{
:field => "payer.funding_instruments[0].credit_card.number",
:issue => "Value is invalid"
},
{
:field => "payer.funding_instruments[0].credit_card.number",
:issue => "Number is crap"
}
],
:message => "Invalid request - see details",
:information_link => "https://developer.paypal.com/webapps/developer/docs/api/#VALIDATION_ERROR",
:debug_id => "88dcf0c1730bb"
}
(2) A non-nil response object
<PaypkgResponse:0x00000001e60040 @name="VALIDATION_ERROR",
@details=[
<PaypkgResponse:0x00000001e73e10 @field="payer.funding_instruments[0].credit_card.number", @issue="Value is invalid">, \
<PaypkgResponse:0x00000001e73988 @field="payer.funding_instruments[0].credit_card.number", @issue="Invalid card type"> \
],
="Invalid request - see details", \
@information_link="https://developer.paypal.com/webapps/developer/docs/api/#VALIDATION_ERROR", \
@debug_id="88dcf0c1730bb"
>
(3) A non-nil details array
[
{
:field => "payer.funding_instruments[0].credit_card.number",
:issue => "Value is invalid"
},
{
:field => "payer.funding_instruments[0].credit_card.number",
:issue => "Number is crap"
}
]
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
# File 'lib/paypkg.rb', line 199 def error_data conditioned_details = [] if @hash.last conditioned_hash = @hash.last # sometimes there's details, sometimes not if conditioned_hash.has_key?(:details) # process errors conditioned_hash[:details].each do |detail| conditioned_details << detail end end else status = @status.last case status[0] when '4' name = "CLIENT ERROR" = "The request sent to PayPal was invalid" when '5' name = "SERVER ERROR" = "PayPay's servers had a problem" else name = "UNKNOWN ERROR" = "" end conditioned_hash = { :name => name, :message => "%s. PayPal returned status code %s"%[,status], :information_link => "https://developer.paypal.com/webapps/developer/docs/api", :debug_id => "0000000000000" } end conditioned_response = PaypkgResponse.new(conditioned_hash) return conditioned_hash, conditioned_response, conditioned_details end |
#execute_payment(payer_id, payment_id) ⇒ Object
This is executed by the code at the ‘accepted’ url.
Your controller must provide two url’s that look like the code below, and are in your config/routes.rb
def approved
pp = Paypkg.new(session)
@ok = pp.execute_payment(params[:PayerID],session[:payment_id])
... more logic ...
end
def cancelled
... handle the user cancelling out ...
end
You should save the sale_id returned from this call in your database.
70 71 72 73 74 75 |
# File 'lib/paypkg/accept-pp-payment.rb', line 70 def execute_payment(payer_id, payment_id) call_paypal("/v1/payments/payment/#{payment_id}/execute/", "{ 'payer_id' : '#{payer_id}' }") return (@status.last=='200') && (@hash.last[:state]=='approved') end |
#refund_sale(sale_id, amount) ⇒ Object
You can request a partial or full refund of a previous sale. You CANNOT, however, refund more than the original sale. If you need to do that, you’ll have to do it manually through your PalPal account.
If you think you’ll ever want to look up the refund, you’ll have to save the refund_id in your database.
16 17 18 19 20 21 22 23 24 25 |
# File 'lib/paypkg/refund-sale.rb', line 16 def refund_sale(sale_id, amount) formatted_amount = "%0.2f"%amount call_paypal("/v1/payments/sale/#{sale_id}/refund", "{ 'amount': { 'total': #{formatted_amount}, 'currency': 'USD' } }") return (@status.last=='201') && (@hash.last[:state]=='completed') end |
#response ⇒ PaypkgResponse Instance
This is a getter which is used to obtain the PaypkgResponse Object from the hash
152 153 154 |
# File 'lib/paypkg.rb', line 152 def response if hash.last then PaypkgResponse.new(hash.last) else nil end end |
#retrieve_credit_card(vault_id) ⇒ Hash
Retrieve a card from the vault.
14 15 16 17 |
# File 'lib/paypkg/retrieve-credit-card.rb', line 14 def retrieve_credit_card(vault_id) call_paypal("/v1/vault/credit-card/#{vault_id}") return (@status.last=='200') && (@hash.last[:state]=='ok') end |
#retrieve_payment_resource(payment_id) ⇒ json String
Use the payment_id to look up a payment.
10 11 12 13 |
# File 'lib/paypkg/retrieve-payment-resource.rb', line 10 def retrieve_payment_resource(payment_id) call_paypal("/v1/payments/payment/#{payment_id}") return (@status.last=='200') end |
#retrieve_refund_transaction(refund_id) ⇒ json String
Use the refund_id to look up the refund.
10 11 12 13 |
# File 'lib/paypkg/retrieve-refund-transaction.rb', line 10 def retrieve_refund_transaction(refund_id) call_paypal("/v1/payments/refund/#{refund_id}") return (@status.last=='200') && (['pending', 'completed', 'refunded', 'partially_refunded'].index(@hash.last[:state])>0) end |
#retrieve_sale_transaction(sale_id) ⇒ json String
Use the sale_id to look up the sale.
10 11 12 13 |
# File 'lib/paypkg/retrieve-sale-transaction.rb', line 10 def retrieve_sale_transaction(sale_id) call_paypal("/v1/payments/sale/#{sale_id}") return (@status.last=='200') && (['pending', 'completed', 'refunded', 'partially_refunded'].index(@hash.last[:state])>0) end |
#store_credit_card(type, number, expire_month, expire_year, cvv2, first_name, last_name, line1, line2, city, state, postal_code, country_code, payer_id) ⇒ String
Store a credit card on the PalPal servers (in the vault, as the refer to it). A card so stored can be used later to make charges, as long as the expire date has not elapsed. Once the expire date elapses, eventually PayPal will automatically remove the card. The card vault_id will be returned from this call: you must save it in your database.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/paypkg/store-credit-card.rb', line 25 def store_credit_card(type, number, expire_month, expire_year, cvv2, first_name, last_name, line1, line2, city, state, postal_code, country_code, payer_id) json = "{ 'payer_id':'#{payer_id}', 'type':'#{type}', 'number':'#{number}', 'expire_month':'#{expire_month}', 'expire_year':'#{expire_year}', 'cvv2':'#{cvv2}', 'first_name':'#{first_name}', 'last_name':'#{last_name}', 'billing_address':{ 'line1':'#{line1}',\n" json << " 'line2':'#{line2}',\n" if line2 json << " 'city':'#{city}', 'state':'#{state}', 'postal_code':'#{postal_code}', 'country_code':'#{country_code}' } }" call_paypal("/v1/vault/credit-card", json) return (@status.last=='201') && (@hash.last[:state]=='ok') end |
#validate_credit_card(type, number, expire_month, expire_year, cvv2, first_name, last_name, line1, city, state, postal_code, country_code) ⇒ Object
Validate a credit card by charging $0.01, then voiding the authorization. The reason for doing this is to validate that an actual charge can be made to the card. If you just attempt to store the card, and you get a valid response, it just means that the card data had no syntactical errors, not that you could ACTUALLY charge the card.
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/paypkg/validate-credit-card.rb', line 23 def validate_credit_card(type, number, expire_month, expire_year, cvv2, \ first_name, last_name, line1, city, state, postal_code, country_code) data = "" data << "{ 'intent':'authorize', 'payer':{ 'payment_method':'credit_card', 'funding_instruments':[ { 'credit_card':{ 'number':'#{number}', 'type':'#{type}', 'expire_month':#{expire_month}, 'expire_year':#{expire_year}, 'cvv2':'#{cvv2}', 'first_name':'#{first_name}', 'last_name':'#{last_name}'," if (!line1.empty?) || (!city.empty?) || (!state.empty?) || (!postal_code.empty?) || (!country_code.empty?) data << " 'billing_address':{ 'line1':'#{line1}', 'city':'#{city}', 'state':'#{state}', 'postal_code':'#{postal_code}', 'country_code':'#{country_code}' }" end data << " } } ] }, 'transactions':[ { 'amount':{ 'total':0.01, 'currency':'USD' }, 'description':'This is a validation transaction.' } ] }" call_paypal("/v1/payments/payment", data) if (@status.last=='201') && (@hash.last[:state]=='approved') link = @hash.last[:transactions][0][:related_resources][0][:authorization][:links].select{|link| link[:rel]=='void'} endpoint = link[0][:href][@uri_base.length..-1] # remove the uri_base from the beginning of the link call_paypal(endpoint, nil, :method => :post, :reset => :no) return true if (@status.last=='200') && (@hash.last[:state]=='voided') end return false end |