I've been playing with a related method sales_order_invoice.create and ran into the same problem you did. I just found that for whatever reason I had to insert an extra element into the array of arguments passed to the server if I included a comment on the invoice.
I'm running Magento EE ver. 1.11.0.2 using C# and the XML-RPC.Net v2 library (CookComputing.XmlRpcV2.dll) to integrate data with Magento.
I stumbled upon this resolution by noticing the comment on the empty invoices was "0", which was the value I was feeding for the Send invoice on email (optional)
field, and decided to try inserting an empty element before the comment, and the comment showed up but the items were still not getting invoiced. I then moved the empty element before the list of items and everything worked. I checked the code for the API /app/code/core/Mage/Sales/Model/Order/Invoice/Api.php but couldn't find where or why this would be the case. My only guess is that it has something to do with the library that is parsing the XML-RPC request isn't getting something right since this call has an array in the middle of the other arguments.
In trying to diagnose this I've used the XML-RPC logger
logger = new RequestResponseLogger();
logger.Directory = "C:\Temp\";
magentoProxy.AttachLogger(logger);
logger.UnsubscribeFrom(magentoProxy);
Then anytime I want to see what the request responses are on a call I just put these calls before and after the XML-RPC call
logger.SubscribeTo(magentoProxy);
// call to Magento that I want to see the XML for request and responses to
logger.UnsubscribeFrom(magentoProxy);
I didn't see any problems with the XML that was sent to Magento for the API calls. The only other thing I could think of would be to launch magento with a debugger attached and watch what happens when it gets to that create method in the Api.php file or in the stack prior where things are getting messed up, but I didn't have my dev environment setup for active debugging of the Magento code at the time, and didn't want to spend the time digging into that aspect of things right now.
What I did as a work around was to add some code after the call to create the invoice that pulls down the order_info again from Magento and checks to see if all the items on the order have been invoiced, and if not it throws up an ugly error. I figure that way if at some point this "bug" or whatever is causing this to happen gets fixed or changes I'll at least know if it affects the order items getting invoiced from this call.
// Get the order items that need to be invoiced
// this.orderInfo is the XmlRpcStruct returned from a sales_order.info call
XmlRpcStruct[] orderItems = this.orderInfo.Contains("items") ? (XmlRpcStruct[]) this.orderInfo["items"] : new XmlRpcStruct[] { };
XmlRpcStruct orderItemsToInvoice = new XmlRpcStruct();
Int32 orderItemId;
Int32 qtyOrdered;
Int32 qtyInvoiced;
Int32 qtyToInvoice;
foreach (XmlRpcStruct item in orderItems)
{
orderItemId = item.Contains("item_id") ? Convert.ToInt32(item["item_id"]) : 0;
qtyOrdered = item.Contains("qty_ordered") ? Convert.ToInt32(Convert.ToDecimal(item["qty_ordered"])) : 0;
qtyInvoiced = item.Contains("qty_invoiced") ? Convert.ToInt32(Convert.ToDecimal(item["qty_invoiced"])) : 0;
qtyToInvoice = qtyOrdered - qtyInvoiced;
orderItemsToInvoice[Convert.ToString(orderItemId)] = Convert.ToString(qtyToInvoice);
}
// Invoice This Order with a comment
String newInvoiceId = magentoProxy.salesOrderInvoiceCreate(sessionId: sessionId, arguments: new Object[] {
this.MageIncrementId, // Order increment ID
"", // this should not need to be here, but for some reason if I want to include a comment
// on the invoice I have to thave this extra empty element before the array of order items
// if no comment is included on the invoice this extra element is not needed, rather weird, I can not explain it.
orderItemsToInvoice, // array itemsQty Array of orderItemIdQty (quantity of items to invoice)
"Automatically invoiced prior to CounterPoint import." // Invoice Comment (optional)
//"0", // Send invoice on email (optional) defaults to false
//"0" // Include comments in email (optional) defaults to false
});
// Invoice This Order without a comment
String newInvoiceId = magentoProxy.salesOrderInvoiceCreate(sessionId: sessionId, arguments: new Object[] {
this.MageIncrementId, // Order increment ID
orderItemsToInvoice // array itemsQty Array of orderItemIdQty (quantity of items to invoice)
});