Spree 0.10.2 如何移除配送和支付结账步骤
结论
需要调整 CheckoutsController,但不能把 object_params 留空。
移除 payment 状态后,Spree 0.10.2 原有的 clear_payments_if_in_payment_state 仍会在 state machine 中查找 "payment",因此会报错:
"payment" is an invalid name
可以覆盖该方法,让它不执行任何操作。与此同时,object_params 仍须返回订单参数,并保留账单地址、配送地址等嵌套属性。否则地址不会赋给订单,验证时所有地址字段都会报错。
如果结账流程完全不处理在线支付,也不应在进入 complete 前调用 process_payment。
修改 checkout state machine
可以把流程改为从 address 直接进入 complete:
Checkout.state_machines[:state] =
StateMachine::Machine.new(Checkout, :initial => 'address') do
after_transition :to => 'complete', :do => :complete_order
event :next do
transition :from => 'address', :to => 'complete'
end
end
原来的以下代码应当删除:
before_transition :to => 'complete', :do => :process_payment
process_payment 用于处理支付记录或调用支付网关。如果货到付款没有对应的支付记录,就不应在完成结账前调用它。
如果系统仍需记录“货到付款”这种支付方式,应自动创建相应的 COD payment,而不是调用在线支付处理逻辑。具体实现取决于项目使用的支付扩展。
覆盖控制器方法
在 Spree 0.10.2 使用的 Rails 2 风格扩展中,可以通过 class_eval 覆盖相关方法:
CheckoutsController.class_eval do
private
def clear_payments_if_in_payment_state
# checkout flow 中已不存在 payment 状态,因此不再执行原来的清理逻辑
end
def object_params
order_params = params[:order] || {}
if order_params[:use_billing] == '1' &&
order_params[:bill_address_attributes]
order_params[:ship_address_attributes] =
order_params[:bill_address_attributes].dup
end
[order_params]
end
end
这里需要注意两点。
object_params 不能为空
如果写成:
def object_params
end
该方法会返回 nil。控制器更新订单时便无法取得:
params[:order][:bill_address_attributes]
params[:order][:ship_address_attributes]
地址内容因此没有赋给订单。执行订单验证时,地址对象仍为空,所有必填字段都会报错。
返回值通常需要是数组
Spree 0.10.2 使用的旧版 controller/resource controller 代码通常会按下面的方式调用参数:
@order.update_attributes(*object_params)
所以 object_params 应返回:
[order_params]
而不是:
order_params
如果当前项目修改过 CheckoutsController#update,需要查看它如何调用 object_params。只有在直接调用 update_attributes(object_params) 时,才应返回普通 Hash。
处理“账单地址同时作为配送地址”
即使采用货到付款,订单通常仍需要配送地址。如果页面有“配送地址与账单地址相同”选项,就要在更新订单前复制地址参数:
if order_params[:use_billing] == '1'
order_params[:ship_address_attributes] =
order_params[:bill_address_attributes].dup
end
如果页面只显示一个地址表单,也可以把该地址同时作为账单地址和配送地址提交:
address_params = order_params[:bill_address_attributes]
if address_params
order_params[:ship_address_attributes] = address_params.dup
end
不要通过关闭 Address 模型的必填验证来处理这个问题。这里的验证错误通常并非规则有误,而是控制器没有把嵌套地址参数传给订单。
还需要检查的地方
将流程改为 address -> complete 后,还要确认:
complete_order不会强制要求订单已有支付记录。- 订单完成验证不要求已经生成配送方式或 shipment。
- 地址页面提供了系统实际需要的账单地址和配送地址。
- 页面、路由和控制器不会继续跳转到
checkout_path(:payment)。 - 如果后台订单需要显示货到付款信息,应通过 COD payment method 或订单属性记录,不能简单伪造“已支付”状态。
如果项目还扩展过 Spree 0.10.2 的 checkout controller,方法签名和 object_params 的返回结构可能会有所不同。判断标准是:覆盖后的参数方法必须将完整的 params[:order] 传给 update_attributes,同时不能再引用已经从 state machine 中删除的 payment 或 delivery 状态。
备注:内容仅供参考。
