Class: StraightServer::Order

Inherits:
Sequel::Model
  • Object
show all
Includes:
Straight::OrderModule
Defined in:
lib/straight-server/order.rb

Instance Method Summary collapse

Instance Method Details

#after_createObject

Update Gateway’s order_counters, incrementing the :new counter. All other increments/decrements happen in the the Gateway#order_status_changed callback, but the initial :new increment needs this code because the Gateway#order_status_changed isn’t called in this case.



125
126
127
# File 'lib/straight-server/order.rb', line 125

def after_create
  self.gateway.increment_order_counter!(:new) if StraightServer::Config.count_orders
end

#after_initializeObject



21
22
23
# File 'lib/straight-server/order.rb', line 21

def after_initialize
  @status = self[:status] || 0
end

#before_createObject



109
110
111
112
113
114
115
116
117
118
119
# File 'lib/straight-server/order.rb', line 109

def before_create
  self.payment_id = gateway.sign_with_secret("#{keychain_id}#{amount}#{created_at}#{(Order.max(:id) || 0)+1}")

  # Save info about current exchange rate at the time of purchase
  unless gateway.default_currency == 'BTC'
    self.data = {} unless self.data
    self.data[:exchange_rate] = { price: gateway.current_exchange_rate, currency: gateway.default_currency }
  end

  super
end

#cancelObject



67
68
69
70
71
# File 'lib/straight-server/order.rb', line 67

def cancel
  self.status = Straight::Order::STATUSES.fetch(:canceled)
  save
  StraightServer::Thread.interrupt(label: payment_id)
end

#cancelable?Boolean

Returns:

  • (Boolean)


63
64
65
# File 'lib/straight-server/order.rb', line 63

def cancelable?
  status == Straight::Order::STATUSES.fetch(:new)
end

#check_status_on_schedule(period: 10, iteration_index: 0, duration: 600, time_passed: 0) ⇒ Object



141
142
143
144
145
146
147
148
# File 'lib/straight-server/order.rb', line 141

def check_status_on_schedule(period: 10, iteration_index: 0, duration: 600, time_passed: 0)
  if StraightServer::Thread.interrupted?(thread: ::Thread.current)
    StraightServer.logger.info "Checking status of order #{self.id} interrupted"
    return
  end
  StraightServer.logger.info "Checking status of order #{self.id}"
  super
end

#gatewayObject



25
26
27
# File 'lib/straight-server/order.rb', line 25

def gateway
  @gateway ||= Gateway.find_by_id(gateway_id)
end

#gateway=(g) ⇒ Object



29
30
31
32
# File 'lib/straight-server/order.rb', line 29

def gateway=(g)
  self.gateway_id = g.id
  @gateway        = g
end

#saveObject



73
74
75
76
# File 'lib/straight-server/order.rb', line 73

def save
  super # calling Sequel::Model save
  @status_changed = false
end

#start_periodic_status_checkObject

Reloads the method in Straight engine. We need to take Order#created_at into account now, so that we don’t start checking on an order that is already expired. Or, if it’s not expired yet, we make sure to stop all checks as soon as it expires, but not later.



133
134
135
136
137
138
139
# File 'lib/straight-server/order.rb', line 133

def start_periodic_status_check
  if (t = time_left_before_expiration) > 0
    StraightServer.logger.info "Starting periodic status checks of order #{id} (expires in #{t} seconds)"
    check_status_on_schedule(duration: t)
  end
  self.save if self.status_changed?
end

#status(as_sym: false, reload: false) ⇒ Object

This method is called from the Straight::OrderModule::Prependable using super(). The reason it is reloaded here is because sometimes we want to query the DB first and see if status has changed there.

If it indeed changed in the DB and is > 1, then the original Straight::OrderModule::Prependable#status method will not try to query the blockchain (using adapters) because the status has already been changed to be > 1.

This is mainly useful for debugging. For example, when testing payments, you don’t actually want to pay, you can just run the server console, change order status in the DB and see how your client picks it up, showing you that your order has been paid for.

If you want the feature described above on, set StraightServer::Config.check_order_status_in_db_first to true



50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/straight-server/order.rb', line 50

def status(as_sym: false, reload: false)
  if reload && StraightServer::Config.check_order_status_in_db_first
    @old_status = self.status
    self.refresh
    unless self[:status] == @old_status
      @status         = self[:status]
      @status_changed = true
      self.gateway.order_status_changed(self)
    end
  end
  self[:status] = @status
end

#time_left_before_expirationObject



150
151
152
153
# File 'lib/straight-server/order.rb', line 150

def time_left_before_expiration
  time_passed_after_creation = (Time.now - created_at).to_i
  gateway.orders_expiration_period+(StraightServer::Config.expiration_overtime || 0) - time_passed_after_creation
end

#to_hObject



78
79
80
81
82
83
84
85
86
87
# File 'lib/straight-server/order.rb', line 78

def to_h
  super.merge({
    id: id,
    payment_id: payment_id,
    amount_in_btc: amount_in_btc(as: :string),
    amount_paid_in_btc: amount_in_btc(field: amount_paid,as: :string),
    keychain_id: keychain_id,
    last_keychain_id: (self.gateway.test_mode ? self.gateway.test_last_keychain_id : self.gateway.last_keychain_id)
  })
end

#to_http_paramsObject



105
106
107
# File 'lib/straight-server/order.rb', line 105

def to_http_params
  "order_id=#{id}&amount=#{amount}&amount_in_btc=#{amount_in_btc(as: :string)}&amount_paid_in_btc=#{amount_in_btc(field: amount_paid, as: :string)}&status=#{status}&address=#{address}&tid=#{tid}&keychain_id=#{keychain_id}&last_keychain_id=#{@gateway.last_keychain_id}"
end

#to_jsonObject



89
90
91
# File 'lib/straight-server/order.rb', line 89

def to_json
  to_h.to_json
end

#validateObject



93
94
95
96
97
98
99
100
101
102
103
# File 'lib/straight-server/order.rb', line 93

def validate
  super # calling Sequel::Model validator
  errors.add(:amount,      "is not numeric") if !amount.kind_of?(Numeric)
  errors.add(:amount,      "should be more than 0") if amount && amount <= 0
  errors.add(:amount_paid, "is not numeric") if !amount.kind_of?(Numeric)
  errors.add(:gateway_id,  "is invalid") if !gateway_id.kind_of?(Numeric) || gateway_id <= 0
  errors.add(:description, "should be shorter than 256 characters") if description.kind_of?(String) && description.length > 255
  errors.add(:gateway,     "is inactive, cannot create order for inactive gateway") if !gateway.active && self.new?
  validates_unique :id
  validates_presence [:address, :keychain_id, :gateway_id, :amount]
end