Quickbooks Online API - 提供发票 ID 后付款 'Unapplied'

Quickbooks Online API - Payment 'Unapplied' when Invoice ID provided

我已经成功地使用 C# .NET SDK 创建了付款,但是当我签入 QBO 时它一直显示为 'unapplied'。

我正在提供发票 ID 并尝试遵循他们的开发人员 API 文档,但我已经做了这么长时间,也许我遗漏了什么?

以下代码创建付款但不'receive'发票付款,是否有我遗漏或需要做的事情才能将两者链接在一起?

Payment payment = new Payment
{
    ProcessPayment = false,
    CustomerRef = new ReferenceType { name = customer.DisplayName, Value = customer.Id },
    CurrencyRef = new ReferenceType { type = "Currency", Value = "CAD" },
    TotalAmt = amount,
    TotalAmtSpecified = true
};

if (method == PaymentTypes.Cash)
{
    var paymentType = paymentMethods.FirstOrDefault(o => o.Id == "1");
    if (paymentType != null)
    {
        payment.PaymentMethodRef = new ReferenceType()
            {name = paymentType.Name, Value = paymentType.Id};
    }
}

if (method == PaymentTypes.DebitCard)
{
    var paymentType = paymentMethods.FirstOrDefault(o => o.Id == "9");
    if (paymentType != null)
    {
        payment.PaymentMethodRef = new ReferenceType()
            { name = paymentType.Name, Value = paymentType.Id };
    }
}

if (method == PaymentTypes.CreditCard)
{
    var paymentType = paymentMethods.FirstOrDefault(o => o.Id == "8");
    if (paymentType != null)
    {
        payment.PaymentMethodRef = new ReferenceType()
            { name = paymentType.Name, Value = paymentType.Id };
    }
}

List<LinkedTxn> linkedTxns = new List<LinkedTxn>
{
    new LinkedTxn()
    {
        TxnId = invoice.Id,
        TxnType = TxnTypeEnum.Invoice.ToString()
    },
};

foreach (Line line in invoice.Line)
{
    //line.Amount = amount;
    //line.AmountSpecified = true;
    line.Received = amount;
    line.ReceivedSpecified = true;
    line.DetailType = LineDetailTypeEnum.PaymentLineDetail;
    line.DetailTypeSpecified = true;
    line.LinkedTxn = linkedTxns.ToArray();
}

payment.DepositToAccountRef = new ReferenceType() { Value = "5" };
payment.Line = invoice.Line;
payment.PaymentRefNum = reference;

DataService dataService = new DataService(serviceContext);
dataService.Add<Payment>(payment);

这是不是的答案。但是,要添加到评论中的内容太多了。我希望这将是一个有用的起点(如果没有,我稍后会删除它)。

首先,我建议重构您的代码并参数化您的变量。这样做您应该能够单独执行可重复的测试。

当您执行 dataService.Add<Payment>(payment) 时,存储响应对象,因为它可能提供有关如何处理请求的线索。或者,如果这是抑制错误消息,您可能想尝试使用 Postman 发送 HTTP 请求。这可能有助于确定哪些参数丢失/不正确。

避免创建部分分配的对象,这样可以更轻松地阅读 7 找出需要分配的属性。

此外,如果您查看 完整更新付款 部分 https://developer.intuit.com/app/developer/qbo/docs/api/accounting/all-entities/payment json 有效载荷有一个额外的 Line,属性 TxnType 设置为 CreditMemo.我假设您需要添加类似 ReceivePaymentCreditCardPayment?

的内容

要重构您的代码,请考虑:

// TODO - Set variables for testing purposes. 
// This can be added as params to a method.
decimal amount = 100;
string reference = "";
string invoiceId = ""; // invoice.Id
string customerDisplayName = ""; //customer.DisplayName
string customerId = ""; //customer.Id
string paymentName = "Cash"; // paymentType.Name
string paymentId = "1"; // paymentType.Id
List<Line> lines = new List<Line>(); // invoice.Line

                        
if(lines.Count() == 0)
{
    // TODO: You might want to check there are lines?
    throw new ArgumentException("No invoice.");
}

Line[] invoiceLines = lines.Select(m => new Line()
{
    AnyIntuitObject = m.AnyIntuitObject,
    Amount = m.Amount,
    AmountSpecified = m.AmountSpecified,
    CustomField = m.CustomField,
    Id = m.Id,
    LineNum = m.LineNum,
    Description = m.Description,
    DetailType = LineDetailTypeEnum.PaymentLineDetail, //m.DetailType,
    DetailTypeSpecified = true, //m.DetailTypeSpecified,
    LinkedTxn = new List<LinkedTxn>
    {
        new LinkedTxn()
        {
            TxnId = invoiceId,
            TxnType = TxnTypeEnum.Invoice.ToString() // TODO: Should this be ReceivePayment?
        },
    }.ToArray(), //m.LinkedTxn,
    LineEx = m.LineEx,
    Received = amount, //m.Received,    
    ReceivedSpecified = true // m.ReceivedSpecified
}).ToArray();            

Payment payment = new Payment
{
    ProcessPayment = false,
    CustomerRef = new ReferenceType { name = customerDisplayName, Value = customerId },
    CurrencyRef = new ReferenceType { type = "Currency", Value = "CAD" },
    TotalAmt = amount,
    TotalAmtSpecified = true,
    DepositToAccountRef = new ReferenceType() { Value = "5" },
    Line = invoiceLines, // Variable is for debugging purposes - it should be inline or call a method. 
    PaymentRefNum = reference,
    PaymentMethodRef = new ReferenceType()
    {
        name = paymentName,
        Value = paymentId,
    }
};

DataService dataService = new DataService(serviceContext);
Payment results = dataService.Add<Payment>(payment);

var json = JsonConvert.SerializeObject(results);
Console.Write(json); // TODO - Use break point/ or write response somewhere for clues.