如何通过 GP web services 或 eConnect 处理销售发票付款?
结论
付款网关返回成功,只能说明外部支付已经完成。Dynamics GP 不会自动把对应的 sales invoice 标记为已付款。还需要在 GP 中创建付款,并将其应用到该发票。
处理方式取决于发票当前的状态:
- 发票仍在 Sales Order Processing(SOP)工作表中且尚未过账时,可以通过 eConnect 的
taCreateSopPaymentInsertRecord为 SOP 发票添加付款。 - 发票已经过账到 Receivables Management(RM)时,需要先创建 Receivables cash receipt,再将收款应用到发票。eConnect 通常使用
taRMCashReceiptInsert和taRMApply。 - 如果当前版本的 GP Web Services 提供 cash receipt 和 apply 操作,也可以直接通过 Web Services 完成已过账发票的付款流程。不同 GP 版本、服务策略和安装组件提供的方法可能不同,应以实际 WSDL 和 SDK 文档为准。
不要直接更新 GP 数据库中的付款、应用或发票余额字段。GP 在处理付款时,还会维护客户余额、应用记录、分配、批次以及可能涉及的总账信息。直接写表很容易造成数据不一致。
先确认发票是否已经过账
CreateSalesInvoice 创建的通常是 SOP 单据,但是否自动过账取决于所用的 Web Services policy 和后续业务流程。
可以这样判断:
- 使用创建发票时返回的
SOPNUMBE查询单据。 - 如果该单据仍可在 Sales Transaction Entry 中编辑,通常表示它还是未过账的 SOP 发票。
- 如果单据已经出现在客户的 Receivables open transactions 中,则应使用 RM cash receipt 流程。
必须先确认单据状态。taCreateSopPaymentInsertRecord 不能代替已过账发票的 RM 应用流程,taRMApply 也不能应用到尚未进入 RM 的 SOP 工作单据。
方案一:为尚未过账的 SOP 发票添加付款
对于仍在 SOP 中的发票,可以使用 eConnect 的 taCreateSopPaymentInsertRecord。付款记录必须引用现有发票的 SOPTYPE 和 SOPNUMBE。
下面是一个结构示例。具体字段应以目标 GP 版本安装目录中的 eConnect XSD 为准:
<?xml version="1.0" encoding="utf-8"?>
<eConnect xmlns:dt="urn:schemas-microsoft-com:datatypes">
<SOPTransactionType>
<taCreateSopPaymentInsertRecord>
<SOPTYPE>3</SOPTYPE>
<SOPNUMBE>INV000123</SOPNUMBE>
<CUSTNMBR>CUSTOMER01</CUSTNMBR>
<DOCDATE>2026-08-31</DOCDATE>
<PYMTTYPE>3</PYMTTYPE>
<DOCAMNT>125.00</DOCAMNT>
<CARDNAME>VISA</CARDNAME>
<AUTHCODE>ABC123</AUTHCODE>
</taCreateSopPaymentInsertRecord>
</SOPTransactionType>
</eConnect>
示例值不能直接用于所有环境:
SOPTYPE必须与现有单据类型一致。标准 SOP Invoice 通常使用3,但仍需根据已经创建的单据或当前版本文档确认。PYMTTYPE的含义和允许值应根据当前 eConnect schema 确认。CARDNAME必须是 GP 中已经配置的卡类型,不能直接填写付款网关返回的品牌名称。- 是否需要收据号、支票号、交易描述或其他字段,取决于付款类型和 GP 配置。
- 不建议将完整卡号或敏感验证数据写入 GP。通常只保存网关交易号、授权码和脱敏后的付款说明。
添加付款后,发票仍需按照现有 SOP 流程过账。过账完成后,GP 才会将发票和付款转入相应的应收账款记录。
方案二:为已过账发票创建 cash receipt 并应用
如果 sales invoice 已经过账,需要分两步处理:
- 使用
taRMCashReceiptInsert创建客户收款。 - 使用
taRMApply将该收款应用到目标发票。
概念上的 eConnect 请求如下:
<?xml version="1.0" encoding="utf-8"?>
<eConnect xmlns:dt="urn:schemas-microsoft-com:datatypes">
<RMTransactionType>
<taRMCashReceiptInsert>
<CUSTNMBR>CUSTOMER01</CUSTNMBR>
<DOCNUMBR>PAY-987654</DOCNUMBR>
<RMDTYPAL>9</RMDTYPAL>
<DOCDATE>2026-08-31</DOCDATE>
<ORTRXAMT>125.00</ORTRXAMT>
<TRXDSCRN>Gateway transaction 987654</TRXDSCRN>
<BCHSOURC>RM_CASH</BCHSOURC>
</taRMCashReceiptInsert>
<taRMApply>
<APFRDCNM>PAY-987654</APFRDCNM>
<APFRDCTY>9</APFRDCTY>
<APTODCNM>INV000123</APTODCNM>
<APTODCTY>1</APTODCTY>
<APPTOAMT>125.00</APPTOAMT>
</taRMApply>
</RMTransactionType>
</eConnect>
文档类型常量需要谨慎处理。标准 RM 环境通常以 1 表示销售或发票,以 9 表示付款,但仍应以当前 GP/eConnect 版本的枚举和 XSD 为准,不能只参考这个示例。
实际系统也可以先提交 cash receipt,确认成功后再单独提交 apply 请求。分开提交更便于处理这些情况:
- 收款已经创建,但应用失败。
- 发票已被其他进程付清。
- 实际付款金额与发票剩余金额不一致。
- 一笔付款需要应用到多张发票。
- 本次只支付部分金额。
- 需要保留未应用余额。
如果两个步骤分开执行,必须记录收款单号,并将”付款已记录”和”付款已应用”作为两个独立状态。
通过 GP Web Services 实现
部分 Dynamics GP Web Services 版本和策略提供 Receivables cash receipt 及其应用对象,另一些环境则没有提供完成这一流程所需的操作。因此,存在 CreateSalesInvoice 并不代表一定存在付款接口。
可以检查当前服务的 WSDL 或生成的代理类,搜索以下概念:
CashReceipt
ReceivablesCashReceipt
Apply
ReceivablesApply
CreateCashReceipt
如果存在对应操作,业务流程仍与 eConnect 相同:先创建客户收款,再将收款应用到已过账发票。Web Services 只是调用接口不同,不会改变 GP 的会计处理方式。
如果 WSDL 中没有这些对象,不要尝试通过 UpdateSalesInvoice 直接修改余额或付款状态。此时通常更适合使用 eConnect。
eConnect 调用示意
应用程序可以生成 eConnect XML,然后通过 eConnectMethods.CreateEntity 提交:
using Microsoft.Dynamics.GP.eConnect;
using System;
public static void SubmitToGp(string connectionString, string xml)
{
using var eConnect = new eConnectMethods();
bool created = eConnect.CreateEntity(
connectionString,
xml
);
if (!created)
{
throw new InvalidOperationException(
"eConnect did not create the GP transaction."
);
}
}
不同 eConnect 版本的程序集、命名空间和方法签名可能不同,应使用与 GP 服务端版本匹配的 SDK。生产代码还需要捕获 eConnect 返回的详细异常,不能只处理布尔结果。
推荐的完整处理顺序
购物车付款流程可以按以下顺序设计:
- 在 GP 中创建 sales invoice,并保存
SOPNUMBE、客户编号和金额。 - 调用付款网关,使用购物车订单号或 GP 单据号作为关联标识。
- 网关批准付款后,保存网关交易 ID、授权码、金额和响应状态。
- 查询 GP 单据的当前状态,确认它仍在 SOP 中,还是已经过账到 RM。
- 如果尚未过账,添加 SOP payment;如果已经过账,创建并应用 RM cash receipt。
- 再次查询 GP,确认付款记录和应用金额已经存在。
- 确认 GP 写入成功后,再将本地订单标记为”已同步到 GP”。
最好将”网关已付款”和”GP 已登记付款”设置为两个独立状态。这样即使 GP 暂时不可用,也不会再次向客户扣款。
幂等性与重复付款
写入付款时必须保证幂等性。网络超时并不表示 GP 没有成功创建付款。如果应用程序直接重试,可能会生成两笔收款。
可以使用稳定且唯一的收款单号,例如:
PAY-{GatewayTransactionId}
每次创建前,先查询该单号是否已经存在:
- 如果付款和应用都已存在,直接返回成功。
- 如果付款已存在但尚未应用,只执行 apply。
- 如果付款不存在,再创建付款。
- 如果同一个网关交易号对应的客户或金额不同,应停止处理并交由人工核查。
其他注意事项
- 不要将信用卡原始数据、CVV 或完整账号保存到 GP。
- 处理网关退款时,不能简单删除原付款。应按照 GP 会计流程创建退款、贷项或反向单据。
- 部分付款时,
APPTOAMT应填写本次实际应用金额,而不是发票原始总额。 - 多币种环境还需要处理币种、汇率、功能币金额和舍入差额。
- 如果收款需要进入批次,应确认
BCHSOURC、批次编号和过账方式符合现有财务流程。 - eConnect 创建记录并不等于自动完成所有过账。是否自动过账取决于所调用的节点、GP 配置和应用程序的后续处理。
- 上线前,应在测试公司中验证 SOP 过账、RM 应用、部分付款、重复提交、退款和失败重试等场景。
未过账发票应使用 SOP payment,已过账发票应使用 RM cash receipt 加 apply。如果当前 Web Services 没有提供后一种流程所需的操作,就使用 eConnect,不要直接修改 GP 数据表。
备注:内容仅供参考。
