PAYATHON 2026

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 中的 ReleasePayment Action 映射,并确认传给 InvokeAsync 的 Type 和 ReferenceNbr 与数据库中的付款完全一致。

不要强制把 Balanced 改成其他状态。应让 Acumatica 根据单据字段计算状态,再找出服务器将这笔付款判定为不可释放的具体原因。

备注:内容仅供参考。