0

我是 Rails 新手,也是活跃商家的新手,只想知道以下代码是否足以使用活跃商家进行支付处理。

如您所见,我使用的是授权和捕获而不是购买方法。我主要关心的是代码中的“brought_quantity”减法(当支付处理失败时,它是对应的部分),我不太确定在竞争条件或支付网关错误的情况下如何处理它。

请注意,变量 transactions 是模型/表的实例变量,我在其中存储支付网关响应的信息。

def purchase(item)
  price = price_in_cents(item.value)
  if !item.can_purchase
    errors[:base] << "We are sorry, all items are sold out at the moment."
    return false
  else
    response = GATEWAY.authorize(price, credit_card, purchase_options)
    transactions.create!(:action => "authorize", :value => price, :params => response)
    #p response
    if response.success?
      item.brought_quantity = item.brought_quantity + 1
      if item.save!
        response = GATEWAY.capture(price, response.authorization)
        transactions.create!(:action => "capture", :value => price, :params => response)
        if !response.success?
          errors[:base] << "There were some problem processing your payment, please either try again or contact us at support@foo.com with this error id: 111"
          @rd = RunningDeal.find_by_id(@item.id)
          @rd.brought_quantity = @rd.brought_quantity - 1
          @rd.save!
          return false
        end
      else
        errors[:base] << "We are sorry, all items are sold out at the moment."
        return false
      end
    else
      # problem process their payment, put out error
      errors[:base] << "There were some problem processing your payment, please either try again or contact us at support@foo.com with this error id: 111"
      return false
    end
  end
  return true
end

编辑 好的,做了一些重构,这里是更新的代码,欢迎任何意见和建议。我删除了!在 transaction.create 上,因为这不是一个足够重要的操作来引发异常。

这是基于反馈的更新代码。

#from running_deal.rb
def decrement_deal_quantity
  self.brought_quantity = self.brought_quantity + 1
  return self.save!
end


def purchase(running_deal)
  price = price_in_cents(running_deal.value)
  if !running_deal.can_purchase
    errors[:base] << "We are sorry, all items are sold out at the moment."
    return false
  else
    auth_resp = GATEWAY.authorize(price, credit_card, purchase_options)
    transactions.create(:action => "authorize", :value => price, :success => auth_resp.success?, :message => auth_resp.message, :authorization => auth_resp.authorization, :params => auth_resp)
    if auth_resp.success?
      begin
        running_deal.decrement_deal_quantity
        cap_resp = GATEWAY.capture(price, auth_resp.authorization)
        transactions.create(:action => "capture", :value => price, :success => cap_resp.success?, :message => cap_resp.message, :authorization => cap_resp.authorization, :params => cap_resp)
      rescue
        GATEWAY.void(auth_resp.authorization, purchase_options) if auth_resp.success?
        errors[:base] << "There were some problem processing your payment, please either try again or contact us at support@foo.com"
        return false
      end
    else
      # problem process their payment, put out error
      errors[:base] << "There were some problem processing your payment, please either try again or contact us at support@foo.com"
      return false
    end
  end
  return true

结尾

4

1 回答 1

3

处理交易很棘手。

几个想法:

  • 如果授权成功,则在 99.9% 的情况下捕获将成功。你真的不需要那么担心这个案子。
  • 如果在 authorize() 成功后代码中出现故障(例如写入数据库的异常),您希望调用 void() 到网关以删除授权。否则资金将被冻结 7 天。
  • 此代码需要移动到模型方法中:

      @rd = RunningDeal.find_by_id(@item.id)
      @rd.brought_quantity = @rd.brought_quantity - 1
      @rd.save!
    
  • 您需要在方法的底部添加子句以捕获异常,因为您调用的是 create!() 而不是 create() (如果保存则返回 true)

    rescue Exception => e # 错误处理结束

  • 尚不清楚为什么如果 item.save!失败您的错误消息表明该项目已售罄?那是完全模糊的。

总的来说,你想做这样的事情:

  • 检查是否有足够的库存
  • 执行 AUTH
  • 启动数据库事务
  • 保存/更新所有数据库对象
  • 提交事务
  • 执行捕获
  • 捕获异常,如果 AUTH 成功 - 执行 VOID

希望这可以帮助。

于 2011-05-19T20:18:47.983 回答