PAYATHON 2026

WinForm桌面软件注册收款应签约哪种支付宝支付接口?

支付阿杰

明确结论

WinForm 软件在注册时显示支付宝二维码,由用户用手机支付宝扫码付款。这套流程最接近支付宝“当面付”的扫码支付模式,通常使用 alipay.trade.precreate 接口。

能否签约“当面付”,还要看支付宝对商户经营场景、经营类目和资质材料的审核。没有实体门店并不代表一定无法申请,但不能虚构门店,也不能提交与实际业务不符的资料。申请时应如实说明业务流程:公司销售桌面软件或软件授权,PC 客户端显示订单二维码,用户付款后在线获取注册码。

如果商户后台不允许这类经营场景签约“当面付”,可以改用“电脑网站支付”。WinForm 创建订单后,通过系统浏览器打开支付宝收银台,用户在网页中登录或扫码付款。WinForm 是桌面程序,不应按手机 App 申报“App 支付”。

支付宝可能调整产品名称、经营类目和准入要求,最终应以签约页面及支付宝商家客服的审核口径为准。

两种方案如何选择

方案一:当面付扫码支付

典型流程如下:

  1. WinForm 向企业自己的业务服务器提交购买请求。
  2. 服务器生成唯一订单号和待支付订单。
  3. 服务器调用 alipay.trade.precreate。
  4. 支付宝返回 qr_code。
  5. WinForm 将其绘制成二维码。
  6. 用户使用支付宝扫码付款。
  7. 服务器通过异步通知或 alipay.trade.query 确认付款结果。
  8. 服务器生成注册码并返回给 WinForm。

这种方案不需要用户离开桌面软件,操作更直接。不过,纯线上软件授权是否符合“当面付”的签约条件,仍需支付宝审核确认。

方案二:电脑网站支付

如果无法签约“当面付”,可以使用电脑网站支付。WinForm 本身不必是网站,但支付请求需要由服务端创建,再通过默认浏览器打开支付宝收银台。

var paymentUrl = await CreatePaymentOnServerAsync(orderId);

Process.Start(new ProcessStartInfo
{
    FileName = paymentUrl,
    UseShellExecute = true
});

付款后,不能只根据浏览器的跳转结果发放注册码。业务服务器仍需验证支付宝异步通知的签名,或者主动查询订单状态。

推荐的系统结构

不要在 WinForm 中保存支付宝应用私钥并直接调用支付接口。桌面软件安装在客户电脑上,程序集容易被反编译。私钥泄露后,攻击者可能伪造请求或破坏交易流程。

建议采用以下结构:

WinForm 客户端
    │
    │ 创建订单、查询付款结果
    ▼
企业业务服务器
    │
    │ 使用应用私钥签名
    ▼
支付宝开放平台

支付宝异步通知
    │
    ▼
企业业务服务器
    │
    ├── 验签
    ├── 核对订单号、金额、收款方
    ├── 更新订单状态
    └── 生成注册码

如果软件目前完全离线,也没有业务服务器,建议先增加一个最小化的支付与授权服务。客户端轮询支付宝、解析页面或判断二维码是否消失,都不能可靠证明订单已经付款。

当面付接口示例

下面是服务端调用 alipay.trade.precreate 时的核心业务参数。不同版本的支付宝 .NET SDK 可能使用不同的类名和初始化方式,具体写法应以对应版本的官方说明为准。

var bizContent = new
{
    out_trade_no = order.OrderNo,
    total_amount = order.Amount.ToString("0.00"),
    subject = "桌面软件授权",
    timeout_express = "15m"
};

// 服务端调用 alipay.trade.precreate。
// 返回成功后,将 response.qr_code 发送给 WinForm。
// WinForm 负责把 qr_code 内容绘制成二维码。

对应的请求数据大致如下:

{
  "out_trade_no": "SW202609130001",
  "total_amount": "199.00",
  "subject": "桌面软件授权",
  "timeout_express": "15m"
}

out_trade_no 在商户系统内必须唯一。金额应由服务端根据商品或授权方案确定,不能采用客户端上传的金额。

支付结果处理示例

服务器收到异步通知后,应先使用支付宝公钥或支付宝公钥证书验签,再核对订单信息:

public async Task<IActionResult> AlipayNotify()
{
    var parameters = Request.Form
        .ToDictionary(item => item.Key, item => item.Value.ToString());

    if (!VerifyAlipaySignature(parameters))
        return Content("failure");

    string orderNo = parameters["out_trade_no"];
    string tradeStatus = parameters["trade_status"];
    string totalAmount = parameters["total_amount"];
    string sellerId = parameters["seller_id"];

    var order = await orderRepository.GetAsync(orderNo);
    if (order == null)
        return Content("failure");

    if (decimal.Parse(
            totalAmount,
            System.Globalization.CultureInfo.InvariantCulture) != order.Amount)
        return Content("failure");

    if (sellerId != configuredSellerId)
        return Content("failure");

    if (tradeStatus is "TRADE_SUCCESS" or "TRADE_FINISHED")
    {
        // 必须实现幂等处理,重复通知不能重复发放授权。
        await CompleteOrderAndIssueLicenseAsync(order);
    }

    return Content("success");
}

这段代码仅用于说明流程。VerifyAlipaySignature 应使用所选支付宝 SDK 提供的验签功能,不要自行拼接字符串,实现一套不完整的签名算法。

客户端可以定时查询自己的业务服务器,不要直接根据支付宝页面判断支付结果:

private async Task WaitForPaymentAsync(string orderNo)
{
    while (true)
    {
        var result = await QueryOrderFromServerAsync(orderNo);

        if (result.Status == "PAID")
        {
            ShowLicenseCode(result.LicenseCode);
            return;
        }

        if (result.Status is "CLOSED" or "EXPIRED")
        {
            ShowPaymentExpired();
            return;
        }

        await Task.Delay(TimeSpan.FromSeconds(3));
    }
}

如果异步通知延迟或丢失,服务端也可以调用 alipay.trade.query 主动确认交易状态,但查询频率不宜过高。

申请时应准备的材料

申请支付产品时,可以准备能够真实说明经营场景的材料,例如:

  • 营业执照及企业支付宝账户资料;
  • 软件官网、产品介绍页或下载页面;
  • 软件主界面和购买流程截图;
  • WinForm 显示支付二维码或跳转收银台的截图;
  • 软件授权价格、服务内容及用户协议;
  • 售后联系方式、退款规则和隐私政策;
  • 软件著作权、销售授权等能够证明业务真实性的材料。

办公室可以作为经营地址,但不能包装成并不存在的线下门店。如果签约页面强制要求填写门店信息,而实际业务不符合要求,应联系支付宝商家客服,说明完整业务流程,由平台判断适用的经营类目和支付产品。

必须注意的问题

  1. 注册码必须由服务器生成。不要让客户端仅凭“支付成功”字符串计算注册码,否则很容易被绕过。

  2. 支付金额必须由服务器决定。客户端只能提交商品或套餐标识,服务器根据数据库中的价格创建订单。

  3. 异步通知必须验签,同时核对 app_id、seller_id、out_trade_no、total_amount 和交易状态。

  4. 订单处理必须支持幂等。支付宝可能重复发送通知,同一订单只能生成一次有效授权。

  5. 不要在客户端保存应用私钥。支付宝私钥、数据库凭据和注册码生成密钥都应保存在服务器端。

  6. 二维码应设置有效期。订单过期后应关闭或重新创建,不能无限期重复使用同一个二维码。

  7. 申请前应确认数字商品类目的准入规则。软件授权、数字化服务等类目可能需要额外材料,也可能受到限制,具体以实际审核结果为准。

可以先按真实业务申请“当面付”,使用 alipay.trade.precreate 实现 WinForm 展码支付。如果支付宝审核认为该业务不属于当面交易,再改用电脑网站支付,通过浏览器完成收银台流程。无论选择哪种方式,下单、验签和注册码发放都应由企业服务器完成。

备注:内容仅供参考。