Last active
September 12, 2017 20:32
-
-
Save jbmyid/16c70067ea3f5cea7d2b to your computer and use it in GitHub Desktop.
This file contains 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
module PayPal::SDK | |
module REST | |
module DataTypes | |
Payer.class_eval do | |
object_of :merchant_id, String | |
end | |
class ChargeModel < Base | |
object_of :id, String | |
object_of :type, String | |
object_of :amount, Currency | |
end | |
class PaymentDefination < Base | |
object_of :name, String | |
object_of :type, String #UNLIMITED or FIXED | |
object_of :frequency_interval, String | |
object_of :frequency, String # DAY, WEEK, MONTH or YEAR. | |
object_of :cycles, Integer | |
object_of :amount, Currency | |
object_of :id, String | |
array_of :charge_models, ChargeModel | |
end | |
class MerchantPreference < Base | |
object_of :id, String | |
object_of :cancel_url, String | |
object_of :return_url, String | |
object_of :setup_fee, Currency | |
object_of :max_fail_attempts, Integer | |
object_of :auto_bill_amount, Currency | |
object_of :initial_fail_amount_action, Currency | |
object_of :create_time, DateTime | |
object_of :update_time, DateTime | |
end | |
class BillingPlans < Base | |
object_of :total_count, Integer | |
array_of :BillingPlan, Invoice | |
end | |
class BillingPlan < Base | |
# { | |
# name: "Plan Name", type: "INFINITE", description: "Any description", | |
# payment_definitions: {name: "Name", type: "REGULAR", frequency_interval: 1, amount: {value: 2.3, currency: "USD"}, frequency: "MONTH"}, | |
# merchant_preferences: {cancel_url: "http://google.com", return_url: "http://google.com", setup_fee: {value: 0, currency: "USD"}} | |
# } | |
object_of :id, String | |
object_of :name, String | |
object_of :description, String | |
object_of :type, String | |
array_of :payment_definitions, DataTypes::PaymentDefination | |
object_of :merchant_preferences, MerchantPreference | |
object_of :state, String | |
array_of :links, DataTypes::Links | |
object_of :payee, DataTypes::Payer | |
object_of :create_time, DateTime | |
object_of :update_time, DateTime | |
def self.load_members | |
object_of :name, String | |
object_of :description, String | |
end | |
# def self.all(options={}) | |
# path = "vi/payments/billing-plans" | |
# BillingPlans.new(api.get(path, options, BillingPlan.new.http_header)) | |
# end | |
include RequestDataType | |
def create | |
path = "v1/payments/billing-plans" | |
response = api.post(path, self.to_hash) | |
self.merge!(response) | |
success? | |
end | |
def self.find(resource_id) | |
raise ArgumentError.new("id required") if resource_id.to_s.strip.empty? | |
path = "v1/payments/billing-plans/#{resource_id}" | |
self.new(api.get(path)) | |
end | |
def update(attrs) | |
path = "v1/payments/billing-plans/#{self.id}" | |
attrs = attrs.blank? ? [{path: "/", value: {state: "ACTIVE"}, op: "replace"}] : attrs | |
response = api.patch(path, attrs) | |
self.merge!(response) | |
success? | |
end | |
def activate! | |
update([{path: "/", value: {state: "ACTIVE"}, op: "replace"}]) | |
end | |
end | |
class AgreementDetails < Base | |
object_of :outstanding_balance, Currency | |
object_of :cycles_remaining, Integer | |
object_of :cycles_completed, Integer | |
object_of :final_payment_date, DateTime | |
object_of :failed_payment_count, Integer | |
end | |
class AgreeMent < Base | |
object_of :id, String | |
object_of :name, String | |
object_of :description, String | |
object_of :start_date, DateTime | |
object_of :payer, Payer | |
object_of :plan, BillingPlan | |
array_of :links, DataTypes::Links | |
object_of :override_merchant_preferences, MerchantPreference | |
object_of :state, String | |
object_of :agreement_details, AgreementDetails | |
include RequestDataType | |
def create | |
path = "v1/payments/billing-agreements" | |
response = api.post(path, self.to_hash) | |
self.merge!(response) | |
success? | |
end | |
def approval_url | |
links.select{|link| link.rel=="approval_url"}[0].try :href | |
end | |
def execute_url | |
links.select{|link| link.rel=="execute"}[0].try :href | |
end | |
def execute!(token) | |
response = api.post("v1/payments/billing-agreements/#{token}/agreement-execute") | |
self.merge!(response) | |
success? | |
end | |
def suspend | |
path = "v1/payments/billing-agreements/#{id}/suspend" | |
response = api.post(path, {note: "Suspending the subscription"}) | |
self.merge!(response) | |
success? | |
end | |
def reactivate | |
path = "v1/payments/billing-agreements/#{id}/re-activate" | |
response = api.post(path, {note: "Reactivating the agreement."}) | |
self.merge!(response) | |
success? | |
end | |
def cancel | |
path = "v1/payments/billing-agreements/#{id}/cancel" | |
response = api.post(path, {note: "Cencelling the agreement."}) | |
self.merge!(response) | |
success? | |
end | |
# def update_plan(plan_id) | |
# path = "v1/payments/billing-agreements/#{id}" | |
# response = api.patch(path, [{op: "replace", path: "/", value: {plan: {id: plan_id}}}]) | |
# self.merge!(response) | |
# success? | |
# end | |
def self.find(resource_id) | |
raise ArgumentError.new("id required") if resource_id.to_s.strip.empty? | |
path = "v1/payments/billing-agreements/#{resource_id}" | |
self.new(api.get(path)) | |
end | |
end | |
end | |
end | |
end | |
# For paypal plan concern | |
module ActAsPaypalPlan | |
extend ActiveSupport::Concern | |
include PayPal::SDK::REST::DataTypes | |
included do | |
after_validation :set_paypal_plan, on: :create | |
end | |
def paypal_plan | |
if paypal_id | |
@paypal_plan ||= BillingPlan.find(paypal_id) | |
else | |
@paypal_plan ||= BillingPlan.new(name: name, type: "INFINITE", description: "Pending", | |
payment_definitions: {name: "PaymentDefinition#{name}", type: "REGULAR", frequency_interval: 1, amount: {value: price, currency: "USD"}, frequency: interval}, | |
merchant_preferences: {cancel_url: "http://google.com", return_url: "http://google.com", setup_fee: {value: 0, currency: "USD"}}) | |
end | |
end | |
def agreement(options={}) | |
@agreement ||= AgreeMent.new(name: "Subscribe #{name}", description: "Subscribe #{name}", start_date: Date.today+1.days, plan: {id: paypal_plan.id}, payer: {payment_method: "paypal"}, override_merchant_preferences: {cancel_url: options[:cancel_url], return_url: options[:return_url]}) | |
end | |
private | |
def set_paypal_plan | |
return if errors.any? | |
billing_plan = paypal_plan | |
if billing_plan.create && billing_plan.activate! | |
self.paypal_id = billing_plan.id | |
# billing_plan.activate! | |
else | |
self.errors[:paypal_id] << billing_plan.error[:details].collect{|e| e[:issue]}.join(",") | |
end | |
end | |
end | |
# for paypal subscription concern | |
module ActAsSubscription | |
TYPES = %w{visa mastercard amex discover maestro} | |
STATES = {cancelled: "CANCELLED", active: "ACTIVE", suspended: "SUSPENDED"} | |
extend ActiveSupport::Concern | |
include PayPal::SDK::REST::DataTypes | |
included do | |
define_callbacks :cancel | |
define_callbacks :reactivate | |
define_callbacks :suspend | |
after_create :active! | |
end | |
STATES.each do |k,v| | |
define_method "#{k}?" do | |
self.state == v | |
end | |
define_method "#{k}!" do | |
update_column(:state, v) | |
end | |
end | |
# def credit_card | |
# @credit_card ||= CreditCard.new | |
# end | |
# def credit_card=(card) | |
# @credit_card = card | |
# end | |
# def payer | |
# @payer ||= Payer.new(payment_method: "paypal") | |
# end | |
# def credit_card_token | |
# # , last4: credit_card.number[-4..-1], type: credit_card.type, expire_month: credit_card.expire_month, expire_year: credit_card.expire_year | |
# @credit_card_token ||= CreditCardToken.new({credit_card_id: credit_card.id}) | |
# end | |
# def create_agreement | |
# # agreement.create({name: "Subscribe #{plan.name}", description: "Subscribe #{plan.name}", start_date: (Date.today+1.days), plan: {id: plan.paypal_plan.id}, payer: {payment_method: "paypal"}}) | |
# agreement.create | |
# end | |
def agreement | |
@agreement ||= AgreeMent.find(agreement_id) | |
end | |
def cancel | |
return unless agreement_id | |
run_callbacks :cancel do | |
update_column(:state, STATES[:cancelled]) if agreement.cancel | |
end | |
end | |
def suspend | |
return unless agreement_id | |
run_callbacks :suspend do | |
update_column(:state, STATES[:suspended]) if agreement.suspend | |
end | |
end | |
def reactivate | |
return unless agreement_id | |
run_callbacks :reactivate do | |
update_column(:state, STATES[:active]) if agreement.reactivate | |
end | |
end | |
# def update_plan(plan) | |
# agreement.update_plan(plan.paypal_id) | |
# end | |
private | |
module ClassMethods | |
# | |
end | |
end | |
# licence creation or subscribing paypal plan | |
module PaypalLicence | |
extend ActiveSupport::Concern | |
included do | |
before_action :set_user | |
before_action :set_licence, only: [:destroy, :suspend, :reactivate] | |
end | |
def new | |
@licence = @user.licence || @user.build_licence | |
session[:plan_id] = nil | |
authorize @licence if need_to_authorise? | |
@plans = FixedPlan.all | |
end | |
def approve | |
authorize @user.build_licence, :new? if need_to_authorise? | |
@plan = Plan.find_by_id(params[:licence][:plan_id]) | |
if @plan.agreement(cancel_url: paypal_cancel_url, return_url: paypal_return_url).create | |
session[:plan_id] = @plan.id | |
redirect_to @plan.agreement.approval_url | |
else | |
flash[:alert] = t("flash.error.licence_approve_failure") | |
redirect_to new_licence_path | |
end | |
end | |
def execute | |
authorize @user.build_licence, :new? if need_to_authorise? | |
if session[:plan_id] | |
@licence = @user.create_licence_with_payment_token!(token: params[:token], plan_id: session[:plan_id]) | |
session[:plan_id] = nil | |
flash[:notice] = t("flash.success.licence.created") | |
redirect_to after_create_path | |
else | |
redirect_to unauthorized_url | |
end | |
end | |
def create | |
@licence = Licence.new_with_credit_card(licence_params, @user) | |
authorize @licence if need_to_authorise? | |
@plans = FixedPlan.all | |
if @licence.save | |
redirect_to after_create_path | |
else | |
render "new" | |
end | |
end | |
# Suspend Subscription and can be reactivated | |
def suspend | |
authorize @licence if need_to_authorise? | |
@licence.suspend | |
respond_with @licence, location: after_suspension_path | |
end | |
def reactivate | |
authorize @licence if need_to_authorise? | |
@licence.reactivate | |
respond_with @licence, location: after_reactivate_path | |
end | |
# Cancel Subscription | |
def destroy | |
authorize @licence if need_to_authorise? | |
@licence.destroy | |
respond_with @licence, location: after_cancellation_path | |
end | |
private | |
def after_suspension_path | |
raise NotImplementedError | |
end | |
def after_reactivate_path | |
raise NotImplementedError | |
end | |
def after_cancellation_path | |
raise NotImplementedError | |
end | |
def after_create_path | |
raise NotImplementedError | |
end | |
def paypal_cancel_url | |
# new_user_licence_url(@user, state: "cancelled") | |
raise NotImplementedError | |
end | |
def paypal_return_url | |
# execute_user_licence_url(@user, state: "success", ) | |
raise NotImplementedError | |
end | |
def need_to_authorise? | |
true | |
end | |
def new_licence_path | |
# new_user_licence_path(@user) | |
raise NotImplementedError | |
end | |
def unauthorized_url | |
# user_path(@user) | |
raise NotImplementedError | |
end | |
def set_user | |
raise NotImplementedError | |
end | |
def set_licence | |
@licence = @user.licence | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment