Acumatica SOAP API 释放付款时状态无效错误
结论
Balanced 是付款释放前的正常状态,无需先改成 Open。在 Acumatica 中,Status 通常由系统根据 Hold、Released、Voided 等字段计算,创建付款时不应手动赋值。
出现 Document Status is invalid for processing,表示服务器实际加载的付款不符合释放条件。需要检查付款是否仍处于 Hold 状态、是否已经释放或作废,以及调用 Release 时使用的单据键是否正确。
修改创建付款的代码
删除这一行:
Status = new StringValue { Value = "Open" },
还要确认 CashAccount 填写的是现金账户 ID,而不是付款方式 ID。原代码中的两个字段都使用了 store.AcumaticaPaymentMethod,很可能是赋值错误。应改为:
PaymentMethod = new StringValue
{
Value = store.AcumaticaPaymentMethod
},
CashAccount = new StringValue
{
Value = store.AcumaticaCashAccount
},
完整的创建代码可以写成:
Payment paymentToBeCreated = new Payment
{
Type = new StringValue
{
Value = "Prepayment"
},
PaymentMethod = new StringValue
{
Value = store.AcumaticaPaymentMethod
},
CashAccount = new StringValue
{
Value = store.AcumaticaCashAccount
},
PaymentAmount = new DecimalValue
{
Value = Convert.ToDecimal(wooOrder.order.total)
},
CustomerID = newOrder.CustomerID,
PaymentRef = new StringValue
{
Value = wooPaymentRef
},
Hold = new BooleanValue
{
Value = false
},
OrdersToApply = new[]
{
new PaymentOrder
{
OrderType = new StringValue
{
Value = "SO"
},
OrderNbr = newOrder.OrderNbr,
AppliedToOrder = newOrder.OrderTotal
}
}
};
Payment newPayment =
(Payment)await client.PutAsync(paymentToBeCreated);
使用明确的单据键执行 Release
执行释放动作时,只需提供能够唯一定位付款的字段。与其把查询返回的完整对象传给 InvokeAsync,不如使用只包含 Type 和 ReferenceNbr 的实体,代码会更清楚:
Payment paymentToRelease = new Payment
{
Type = new StringValue
{
Value = newPayment.Type.Value
},
ReferenceNbr = new StringValue
{
Value = newPayment.ReferenceNbr.Value
}
};
InvokeResult invokeResult = await client.InvokeAsync(
paymentToRelease,
new ReleasePayment()
);
ProcessResult processResult =
await LongProcessRunner.GetProcessResult(client, invokeResult);
不同版本生成的契约类可能要求键字段使用 StringValue 或 StringSearch,也可能要求传入由 GetAsync 返回的实体。如果上面的写法与当前代理类不兼容,可以继续使用查询结果,但要确认查询返回的确实是刚创建的付款。
释放前需要确认的状态
Balanced 状态可以释放,但付款还必须满足这些条件:
Hold为false。Released为false。- 单据没有被作废。
Type和ReferenceNbr能唯一定位正确的付款。- 付款使用的 Cash Account、Payment Method 和 Financial Period 有效。
- 如果付款方式启用了信用卡处理流程,相关授权或捕获步骤已经按照该付款方式的配置完成。
- 订单应用金额没有超过付款金额或订单的可应用余额。
释放前可以读取并记录相关字段:
Payment paymentToBeFound = new Payment
{
Type = new StringSearch
{
Value = newPayment.Type.Value
},
ReferenceNbr = new StringSearch
{
Value = newPayment.ReferenceNbr.Value
}
};
Payment currentPayment =
(Payment)await client.GetAsync(paymentToBeFound);
Console.WriteLine($"Type: {currentPayment.Type?.Value}");
Console.WriteLine($"ReferenceNbr: {currentPayment.ReferenceNbr?.Value}");
Console.WriteLine($"Status: {currentPayment.Status?.Value}");
Console.WriteLine($"Hold: {currentPayment.Hold?.Value}");
Console.WriteLine($"Released: {currentPayment.Released?.Value}");
如果契约中没有 Released 字段,需要将它加入 Web Service Endpoint,或者直接在 Acumatica 界面中检查。
仍然报错时如何定位
先在 Acumatica 界面中打开同一笔付款,手动执行 Release:
- 如果界面中也无法释放,说明问题出在单据数据或业务配置上。检查 Hold、付款方式、现金账户、财务期间和订单应用明细。
- 如果界面能够释放,但 SOAP API 无法释放,应检查 Endpoint 中的
ReleasePaymentAction 映射,并确认传给InvokeAsync的Type和ReferenceNbr与数据库中的付款完全一致。
不要强制把 Balanced 改成其他状态。应让 Acumatica 根据单据字段计算状态,再找出服务器将这笔付款判定为不可释放的具体原因。
备注:内容仅供参考。
