我在Spare2.2中实现了一个自定义支付网关。这是一个网关,在那里你可以重定向到网关自己的网站来接受付款,然后银行会用一堆get params重定向回给你。
我遇到了一个问题,如果我在代码中放入一个debugger,那么order的payment_state和shipment_state在数据库中会以null结束,尽管它们在order对象本身中不是null。调用order.save似乎没有什么帮助。
我已经实现了一个肮脏的黑客来解决这个问题:
# This is a hack - for some reason the payment_state and shipment_state weren't being persisted
# and where being stored in the database as null. Really the spree checkout process
# should take care of this and we shouldn't have to set them manually.
# We must be doing something wrong...
order.update_attribute :payment_state, 'paid'
order.update_attribute :shipment_state, 'ready'但我真的很想知道真正的问题是什么--为什么这些状态没有被坚持下来?(在调用上面的代码之前,我应该补充一点,order.payment_state和order.shipment_state的值分别是balance_due和pending -但这是另一个问题。如果我能让他们以任何方式保存,这是主要的问题。
你知道我做错了什么吗?
下面是我的控制器和网关的完整代码。
class Spree::CommBankController < Spree::StoreController
def secure_payment
order = current_order
@order_info = 'Espionage Online order ' + order.number
payment_params = {
"Title" => 'Espionage Online',
"vpc_AccessCode" => payment_method.preferred_access_code,
"vpc_Amount" => (order.total * 100).to_i, # convert to cents
"vpc_Desc" => @order_info,
"vpc_MerchTxnRef" => order.number,
"vpc_Merchant" => payment_method.preferred_merchant_id_no,
"vpc_OrderInfo" => @order_info,
"vpc_ReturnURL" => secure_payment_callback_url(payment_method_id: payment_method.id),
}
payment_request = ::CommWeb::PaymentRequest.new(payment_params, payment_method.preferred_secure_secret)
redirect_to payment_request.url
end
def secure_payment_callback
# Next line - see http://stackoverflow.com/questions/4116545/how-do-i-get-only-the-query-string-in-a-rails-route
order = current_order
query_params = params.except(*request.path_parameters.keys)
payment_response = ::CommWeb::PaymentResponse.new(query_params, payment_method.preferred_secure_secret)
if !secure_hash_matches?(payment_response)
flash.notice = 'Error with payment - secure hash did not match. Please try again.'
redirect_to checkout_state_path(order.state)
return
end
payment = order.payments.create!({
:source => Spree::CommbankCheckout.create({
:params_hash => payment_response.params.to_s,
:success => payment_response.success?,
:desc => payment_response.description,
:trx_response_code => payment_response.trx_response_code,
:message => payment_response.message,
}),
:amount => order.total,
:payment_method => payment_method,
:response_code => payment_response.trx_response_code,
})
payment.pend
if payment_response.success?
# Set payment to completed after order.next because
# spree expects at least one incomplete payment to process an order to complete
order.next!
payment.complete
debugger
# This is a hack - for some reason the payment_state and shipment_state weren't being persisted
# and where being stored in the database as null. Really the spree checkout process
# should take care of this and we shouldn't have to set them manually.
# We must be doing something wrong...
order.update_attribute :payment_state, 'paid'
order.update_attribute :shipment_state, 'ready'
else
payment.failure
end
if order.complete?
flash.notice = Spree.t(:order_processed_successfully)
session[:order_id] = nil
redirect_to completion_route(order)
else
flash.notice = 'Error: ' + payment_response.message + '. Please try again.'
redirect_to checkout_state_path(order.state)
end
end
def secure_hash_matches? payment_response
payment_response.secure_hash_matches?
end
def payment_method
@payment_method ||= Spree::PaymentMethod.find(params[:payment_method_id])
end
def completion_route(order)
order_path(order)
end
end入口..。
# Partly inspired from https://github.com/spree-contrib/spree-adyen (the hosted payment page class)
module Spree
class Gateway::CommBank < Gateway
preference :merchant_id_no, :string
preference :access_code, :string
preference :secure_secret, :string
def auto_capture?
true
end
# Spree usually grabs these from a Credit Card object but when using
# Commbank's 3 Party where we wouldn't keep the credit card object
# as that's entered outside of the store forms
def actions
%w{capture}
end
# Indicates whether its possible to void the payment.
def can_void?(payment)
!payment.void?
end
# Indicates whether its possible to capture the payment
def can_capture?(payment)
payment.pending? || payment.checkout?
end
def method_type
'commbank'
end
def capture(*args)
ActiveMerchant::Billing::Response.new(true, "", {}, {})
end
def source_required?
false
end
def provider_class
self.class
end
def provider
self
end
def purchase
# This is normally delegated to the payment, but don't do that. Handle it here.
# This is a hack copied from the Spree Better Paypal Express gem.
Class.new do
def success?; true; end
def authorization; nil; end
end.new
end
end
end发布于 2015-03-11 11:57:39
检查order.state_changes。它们是否显示了两个状态的更改?
我在使用"spree-adyen“的时候遇到了同样的问题。order.state_changes显示payment_state和shipment_state已更改为ready。然而,它并不保持顺序。这是随机发生的,订单的10%。我目前正在对这样的订单手动调用order.update!,但我真的很想知道问题是什么。
此外,我不太确定order.update!是否是一个好的解决方案,因为它执行很多查询,而且可能非常昂贵。
发布于 2015-02-19 22:04:32
嗯。所以很明显order.update!会解决我的问题。哇哦。
尽管如此,调用order.update!并不是我在其他Spree Payment Gateway gem (https://github.com/spree-contrib/better_spree_paypal_express或https://github.com/spree-contrib/spree-adyen)中看到的,所以我有兴趣知道我是不是在做一些非常愚蠢的事情。(我最终在https://github.com/coinbase/coinbase-spree/blob/master/app%2Fcontrollers%2Fspree%2Fcoinbase_controller.rb的代码中注意到了它)
https://stackoverflow.com/questions/28608001
复制相似问题