自定义付款表单 - 在不将 PaymentIsCompleted 设置为 true 的情况下无法将订单状态设置为 Authorized
Custom payment form - unable to set order status to Authorized without setting PaymentIsCompleted to true
我们正在尝试使用 Kentico 中的结帐流程来授权信用卡付款而不是收费。为此,一旦用户完成结帐过程,我们希望订单的状态类似于 'Payment authorized',并且其 OrderIsPaid
属性 设置为 false
。
在付款表格中,在我对 ProcessPayment()
的覆盖中,我没有将 base.PaymentResult.PaymentIsCompleted
设置为 true
,因为我只是想授权付款,而不是实际收费卡片。 (同样,这是我们希望的结帐过程结果:信用卡授权;实际上并未对卡收费。)在调用此函数后的某个时刻,订单状态设置为支付失败(在商店配置 -> 支付网关中指定) .
我希望的结果是将订单状态设置为授权(我在商店配置中指定)并将订单的 OrderIsPaid
字段设置为 false
.
根据观察到的行为,我假设付款过程的成功取决于将 PaymentIsCompleted
设置为 true
。我还假设 属性 与 OrderInfo.OrderIsPaid
相同。
有谁知道我怎样才能达到想要的状态?
----------------更新:基于 Trevor 回答的解决方案--------
我在支付过程中没有设置OrderCustomData。相反,我决定覆盖状态基于当前状态,是否 PaymentStatusValue=='complete',以及我们之前是否覆盖了此特定 PaymentTransactionID 的状态。
void UpdateAfter(object sender, ObjectEventArgs e)
{
try
{
if (e.Object.TypeInfo.ObjectClassName.ToLower().Equals("ecommerce.order"))
{
/*
* The standard payment process behavior will not allow us to set 'IsPaid' to false without forcing the order status to the failed state.
* (As specified in the Store Configuration app under payment methods -> edit payment method -> [Order status if payment fails:])
* The workaround is to configure the payment methods failure status to be 'Authorization Failed' (internal name 'PaymentFailed'),
* to set IsPaid=false in the payment code, and to use this event handler to override the status failed status based on .
*/
OrderInfo order = (OrderInfo)e.Object;
if (order == null)
throw new ArgumentNullException("Order object of ecommerce.order event is null.");
// If a payment hasn't been made, then there's nothing to override.
if (order.OrderPaymentResult == null)
return;
// We will log the payment's transaction ID in ordercustomdata so next time we don't override
// order status unless the payment transaction ID has changed.
string successfulPaymentTransactionId = null;
try
{
successfulPaymentTransactionId = (string)order.OrderCustomData.GetValue("SuccessfulPaymentTransactionID");
}
catch
{ }
// Do not override status on an order that has the same payment transaction ID as when we last overrode it.
if (successfulPaymentTransactionId != null && successfulPaymentTransactionId == order.OrderPaymentResult.PaymentTransactionID)
return;
PaymentOptionInfo paymentOption = PaymentOptionInfoProvider.GetPaymentOptionInfo(order.OrderPaymentOptionID);
if (paymentOption == null)
throw new ArgumentNullException(String.Format("Payment option for OrderPaymentOptionID '{0}' is null.", order.OrderPaymentOptionID));
// Override status if: status is failed but payment status is 'completed'.
// avoid overriding manually; Only override if we haven't yet overriden status based on the currrent payment transaction ID.
if (order.OrderStatusID == paymentOption.PaymentOptionFailedOrderStatusID
&& order.OrderPaymentResult.PaymentStatusValue == "completed"
&& (successfulPaymentTransactionId == null || successfulPaymentTransactionId != order.OrderPaymentResult.PaymentTransactionID))
{
order.OrderStatusID = paymentOption.PaymentOptionSucceededOrderStatusID;
order.OrderCustomData["SuccessfulPaymentTransactionID"] = order.OrderPaymentResult.PaymentTransactionID;
order.Update();
}
}
}
catch (Exception ex)
{
EventLogProvider.LogException("EcommerceOrderInfoModule", "UpdateAfter", ex, 0, null, null);
}
}
您说得对 "PaymentIsComplete" 将触发付费或未付费状态。在 Kentico 中,虽然对于您的付款,您可以设置 "Order Status" 应用于付款失败和付款成功。
商店配置 -> 付款方式 ->(编辑您的)-> 将 "Order status if payment fails" 设置为 "Payment Authorized"(可能需要创建它)
现在承认,这可能不是理想的,因为这里确实有 3 种状态的项目,完全失败、成功但未支付和已支付。因此,您可能需要使用自定义数据更新订单,然后使用事件挂钩来捕获订单状态更改并检查此值。
// If authorized, then set this to true, set paymentiscomplete to false regardless
Order.OrderCustomData.SetValue("Authorized", true);
PaymentResult.PaymentIsCompleted = false;
并且在 InitializationModule
protected override void OnInit()
{
base.OnInit();
CMS.DataEngine.ObjectEvents.Update.After += Update_After;
}
void Update_After(object sender, ObjectEventArgs e)
{
try {
switch (e.Object.TypeInfo.ObjectClassName.ToLower())
{
case "ecommerce.order":
OrderInfo theOrderObj = (OrderInfo)e.Object;
bool hasAuthorizedStatus = CMS.Helpers.ValidationHelper.GetBoolean(theOrderObj.OrderCustomData.GetValue("Authorized"), false);
if (hasAuthorizedStatus && theOrderObj.OrderStatusID == OrderStatusInfoProvider.GetOrderStatusInfo("ThePaymentFailureStatus", SiteContext.CurrentSiteName).StatusID)
{
theOrderObj.OrderStatusID = OrderStatusInfoProvider.GetOrderStatusInfo("PaymentAuthorized", SiteContext.CurrentSiteName).StatusID;
theOrderObj.Update();
}
break;
}
}
catch (Exception ex)
{
CMS.EventLog.EventLogProvider.LogException("CustomInitializationModule", "UpdateAfterError", ex);
}
}
我们正在尝试使用 Kentico 中的结帐流程来授权信用卡付款而不是收费。为此,一旦用户完成结帐过程,我们希望订单的状态类似于 'Payment authorized',并且其 OrderIsPaid
属性 设置为 false
。
在付款表格中,在我对 ProcessPayment()
的覆盖中,我没有将 base.PaymentResult.PaymentIsCompleted
设置为 true
,因为我只是想授权付款,而不是实际收费卡片。 (同样,这是我们希望的结帐过程结果:信用卡授权;实际上并未对卡收费。)在调用此函数后的某个时刻,订单状态设置为支付失败(在商店配置 -> 支付网关中指定) .
我希望的结果是将订单状态设置为授权(我在商店配置中指定)并将订单的 OrderIsPaid
字段设置为 false
.
根据观察到的行为,我假设付款过程的成功取决于将 PaymentIsCompleted
设置为 true
。我还假设 属性 与 OrderInfo.OrderIsPaid
相同。
有谁知道我怎样才能达到想要的状态?
----------------更新:基于 Trevor 回答的解决方案--------
我在支付过程中没有设置OrderCustomData。相反,我决定覆盖状态基于当前状态,是否 PaymentStatusValue=='complete',以及我们之前是否覆盖了此特定 PaymentTransactionID 的状态。
void UpdateAfter(object sender, ObjectEventArgs e)
{
try
{
if (e.Object.TypeInfo.ObjectClassName.ToLower().Equals("ecommerce.order"))
{
/*
* The standard payment process behavior will not allow us to set 'IsPaid' to false without forcing the order status to the failed state.
* (As specified in the Store Configuration app under payment methods -> edit payment method -> [Order status if payment fails:])
* The workaround is to configure the payment methods failure status to be 'Authorization Failed' (internal name 'PaymentFailed'),
* to set IsPaid=false in the payment code, and to use this event handler to override the status failed status based on .
*/
OrderInfo order = (OrderInfo)e.Object;
if (order == null)
throw new ArgumentNullException("Order object of ecommerce.order event is null.");
// If a payment hasn't been made, then there's nothing to override.
if (order.OrderPaymentResult == null)
return;
// We will log the payment's transaction ID in ordercustomdata so next time we don't override
// order status unless the payment transaction ID has changed.
string successfulPaymentTransactionId = null;
try
{
successfulPaymentTransactionId = (string)order.OrderCustomData.GetValue("SuccessfulPaymentTransactionID");
}
catch
{ }
// Do not override status on an order that has the same payment transaction ID as when we last overrode it.
if (successfulPaymentTransactionId != null && successfulPaymentTransactionId == order.OrderPaymentResult.PaymentTransactionID)
return;
PaymentOptionInfo paymentOption = PaymentOptionInfoProvider.GetPaymentOptionInfo(order.OrderPaymentOptionID);
if (paymentOption == null)
throw new ArgumentNullException(String.Format("Payment option for OrderPaymentOptionID '{0}' is null.", order.OrderPaymentOptionID));
// Override status if: status is failed but payment status is 'completed'.
// avoid overriding manually; Only override if we haven't yet overriden status based on the currrent payment transaction ID.
if (order.OrderStatusID == paymentOption.PaymentOptionFailedOrderStatusID
&& order.OrderPaymentResult.PaymentStatusValue == "completed"
&& (successfulPaymentTransactionId == null || successfulPaymentTransactionId != order.OrderPaymentResult.PaymentTransactionID))
{
order.OrderStatusID = paymentOption.PaymentOptionSucceededOrderStatusID;
order.OrderCustomData["SuccessfulPaymentTransactionID"] = order.OrderPaymentResult.PaymentTransactionID;
order.Update();
}
}
}
catch (Exception ex)
{
EventLogProvider.LogException("EcommerceOrderInfoModule", "UpdateAfter", ex, 0, null, null);
}
}
您说得对 "PaymentIsComplete" 将触发付费或未付费状态。在 Kentico 中,虽然对于您的付款,您可以设置 "Order Status" 应用于付款失败和付款成功。
商店配置 -> 付款方式 ->(编辑您的)-> 将 "Order status if payment fails" 设置为 "Payment Authorized"(可能需要创建它)
现在承认,这可能不是理想的,因为这里确实有 3 种状态的项目,完全失败、成功但未支付和已支付。因此,您可能需要使用自定义数据更新订单,然后使用事件挂钩来捕获订单状态更改并检查此值。
// If authorized, then set this to true, set paymentiscomplete to false regardless
Order.OrderCustomData.SetValue("Authorized", true);
PaymentResult.PaymentIsCompleted = false;
并且在 InitializationModule
protected override void OnInit()
{
base.OnInit();
CMS.DataEngine.ObjectEvents.Update.After += Update_After;
}
void Update_After(object sender, ObjectEventArgs e)
{
try {
switch (e.Object.TypeInfo.ObjectClassName.ToLower())
{
case "ecommerce.order":
OrderInfo theOrderObj = (OrderInfo)e.Object;
bool hasAuthorizedStatus = CMS.Helpers.ValidationHelper.GetBoolean(theOrderObj.OrderCustomData.GetValue("Authorized"), false);
if (hasAuthorizedStatus && theOrderObj.OrderStatusID == OrderStatusInfoProvider.GetOrderStatusInfo("ThePaymentFailureStatus", SiteContext.CurrentSiteName).StatusID)
{
theOrderObj.OrderStatusID = OrderStatusInfoProvider.GetOrderStatusInfo("PaymentAuthorized", SiteContext.CurrentSiteName).StatusID;
theOrderObj.Update();
}
break;
}
}
catch (Exception ex)
{
CMS.EventLog.EventLogProvider.LogException("CustomInitializationModule", "UpdateAfterError", ex);
}
}