Last active
August 29, 2015 14:09
-
-
Save lulalala/8263a700846412a080be to your computer and use it in GitHub Desktop.
Payment Notification
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # in OrdersController | |
| def payment_notify | |
| l = PaymentNotification.new | |
| l.order_id = params[:id] | |
| l.payment_method_id = params[:payment_method_id] | |
| l.url = request.fullpath | |
| l.raw_post = request.raw_post | |
| l.data = {remote_ip:request.remote_ip} | |
| begin | |
| l.save! | |
| rescue => e | |
| l.update_attributes(error:e) | |
| if Rails.env.production? | |
| render text:'error', status:500 and return | |
| else | |
| raise | |
| end | |
| end | |
| case PaymentMethod.find(params[:payment_method_id]).class.merchant_name | |
| when :allpay | |
| render text:'1|OK', status:200 and return | |
| when :paypal | |
| render text:'', status:200 and return | |
| end | |
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| create_table "payment_notifications", force: true | |
| t.integer "order_id", limit: 4 | |
| t.integer "payment_method_id", limit: 4 | |
| t.string "url", limit: 255 | |
| t.text "raw_post", limit: 65535 | |
| t.text "notification", limit: 65535 | |
| t.text "data", limit: 65535 | |
| t.text "error", limit: 65535 | |
| t.datetime "created_at" | |
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class PaymentNotification < ActiveRecord::Base | |
| belongs_to :order | |
| belongs_to :payment_method | |
| serialize :data | |
| serialize :notification | |
| serialize :error | |
| validates :raw_post, :order_id, :payment_method_id, :url, presence:true | |
| # Analyze notification | |
| # and if all is well, mark order as paid. | |
| def process | |
| if order.payment_method != payment_method | |
| raise MismatchError, 'payment method mismatch' | |
| end | |
| if !order.processing? && !order.paid_with_error? | |
| raise IgnorableError, 'order already paid' | |
| end | |
| if notification.nil? | |
| update_attributes(notification:get_notification) | |
| end | |
| # Check notification is legit | |
| if notification.respond_to? :acknowledge | |
| if !notification.acknowledge | |
| raise MismatchError, 'acknowledge failed' | |
| end | |
| end | |
| if !notification.complete? | |
| raise IgnorableError, 'notification not complete' | |
| end | |
| if order_id.to_s != notification.item_id | |
| raise MismatchError, 'order id mismatch' | |
| end | |
| if payment.total != notification.gross.amount.to_i | |
| raise MismatchError, 'amount mismatch' | |
| end | |
| order.pay! | |
| rescue => e | |
| if e.is_a? ConsiderPaidError | |
| if order.processing? | |
| order.pay_with_error! | |
| end | |
| end | |
| if e.is_a?(MismatchError) || e.is_a?(ConsiderPaidError) | |
| # Let admin know about this. | |
| end | |
| self.error = {message:e.message, backtrace:e.backtrace} | |
| save! | |
| end | |
| # Notification does not match our data, possible hack. | |
| class MismatchError < StandardError; end | |
| # Notification ignorable e.g. payment failed notification | |
| class IgnorableError < StandardError; end | |
| # Can be consider paid, just need to inform admin to take a look at. | |
| class ConsiderPaidError < StandardError; end | |
| # Obtain notification object from params | |
| def get_notification | |
| # Convert raw_post to utf-8 when necessary | |
| if payment_method.class.merchant_name == :paypal && raw_post.include?('Big5') | |
| utf8_raw_post = raw_post.encode('utf-8', 'big5') | |
| else | |
| utf8_raw_post = raw_post | |
| end | |
| payment_method.class.active_merchant.notification(utf8_raw_post) | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment