详解Java商城项目使用微信支付的平台收付通实现购物车的合并支付和抽成操作

246 阅读4分钟

在Java商城项目中集成微信平台收付通实现购物车合并支付及平台抽成,需基于微信支付的服务商模式或直连模式,通过收付通的合单支付分账接口完成。以下是关键步骤及代码实现逻辑:


一、系统架构与前置条件

  1. 资质准备

    • 平台主体需具备ICP许可证或EDI许可证(主体与微信商户号一致)。
    • 开通微信支付服务商或直连商户号,并在微信商户后台启用**“平台收付通”** 功能。
  2. 二级商户入驻

    • 平台通过API将商家入驻为微信二级商户(子商户),获取其sub_mchid
      // 示例:调用二级商户入驻API
      Map<String, String> params = new HashMap<>();
      params.put("business_code", "BUSINESS_CODE"); // 平台自定义业务号
      params.put("subject_info", "{...}"); // 商户主体信息(营业执照等)
      String result = WxPayApi.call("https://api.mch.weixin.qq.com/v3/ecommerce/applyments/", params);
      
      返回结果包含子商户号sub_mchid,用于后续支付分账。
  3. 绑定支付场景

    • 在微信支付后台绑定商城的APPID(公众号/小程序),确保与ICP主体一致。

二、购物车合并支付实现流程

步骤1:生成合单订单

用户购物车包含多商户商品时,平台生成合单支付订单(最多50个子订单):

// 构建合单支付请求
Map<String, Object> combineOrder = new HashMap<>();
combineOrder.put("combine_appid", "PLATFORM_APPID"); // 平台APPID
combineOrder.put("combine_out_trade_no", "COMBINE_ORDER_123"); // 平台合单号
combineOrder.put("sub_orders", Arrays.asList(
    new SubOrder("SUB_MCHID_A", 1000, "订单A描述"), // 子商户A订单
    new SubOrder("SUB_MCHID_B", 2000, "订单B描述")  // 子商户B订单
));
combineOrder.put("notify_url", "https://yourdomain.com/pay/notify"); // 支付回调地址

步骤2:调用合单支付API

使用微信支付SDK发起合单支付请求:

import com.github.wxpay.sdk.WXPay;

// 初始化微信支付配置
WXPayConfig config = new MyWxPayConfig(); // 实现WXPayConfig接口
WXPay wxpay = new WXPay(config);

// 调用合单支付接口
Map<String, String> response = wxpay.unifiedOrder(combineOrder);
if ("SUCCESS".equals(response.get("return_code"))) {
    String prepayId = response.get("prepay_id"); // 获取预支付ID
    // 返回前端支付参数(如JSAPI调起支付)
    return buildJsapiParams(prepayId); 
}

步骤3:处理支付结果回调

微信异步通知支付结果,平台需验证签名并更新订单状态:

@PostMapping("/pay/notify")
public String payNotify(HttpServletRequest request) {
    Map<String, String> notifyData = parseRequest(request); // 解析回调数据
    if (wxpay.isPayResultNotifySignatureValid(notifyData)) {
        String combineOrderId = notifyData.get("combine_out_trade_no");
        // 更新主订单状态为已支付,子订单资金进入冻结状态(默认冻结180天)
        orderService.updateOrderStatus(combineOrderId, PAID);
        return "<xml><return_code>SUCCESS</return_code></xml>";
    }
}

三、平台抽成与分账实现

步骤1:解冻资金并分账

用户确认收货后(或满足平台规则),平台发起分账:

  1. 解冻子商户资金:通过分账接口解冻冻结资金。
  2. 平台抽佣:分账时平台抽取佣金(≤订单金额30%)。
// 构建分账请求(单笔订单)
Map<String, String> profitSharingReq = new HashMap<>();
profitSharingReq.put("transaction_id", "P20250626123456"); // 微信支付单号
profitSharingReq.put("out_order_no", "SHARE_ORDER_001"); // 分账单号
profitSharingReq.put("receivers", JSON.toJSONString(Arrays.asList(
    new Receiver("SUB_MCHID_A", 700, "MERCHANT_ID"), // 子商户A分得70%
    new Receiver("PLATFORM_MCHID", 300, "MERCHANT_ID") // 平台抽佣30%
)));
// 调用分账API
Map<String, String> shareResponse = wxpay.invokeProfitSharing(profitSharingReq);

⚠️ 关键限制

  • 分账比例总和≤30%(平台抽佣上限)。
  • 多次分账需确保总分账额不超限。

步骤2:分账结果异步通知

处理微信分账结果回调,更新平台和子商户账务:

@PostMapping("/profit/notify")
public String profitNotify(HttpServletRequest request) {
    // 验证回调签名
    if (wxpay.isValidSignature(request)) {
        String status = request.getParameter("status"); // SUCCESS/FAIL
        if ("SUCCESS".equals(status)) {
            // 更新分账状态,解冻资金转入商户账户
            accountService.unfreezeSubMerchantFunds();
        }
    }
}

四、异常处理与优化

  1. 交易退款

    • 需按子订单发起退款,退款金额≤子订单未分账金额。
    • 若已分账,需先调用分账回退接口
  2. 账期控制优化

    • 冻结期默认180天,但可通过分账接口提前解冻(如用户确认收货后7天):
      setAutoUnfreezeTime("7d"); // 设置自动解冻时间
      
  3. 手续费处理

    • 交易费率固定0.6%,可选择由平台或子商户承担。
    • 发票开给实际承担方。

五、注意事项

  1. 合规性

    • 禁止平台与子商户同主体(自营业务需用不同主体)。
    • 分账资金必须流向真实业务参与方(避免二清风险)。
  2. 技术细节

    • 合单支付仅支持:JSAPI/APP/小程序支付,不支持H5
    • 分账接收方需提前通过API添加(平台/供应商等)。
  3. 调试工具

    • 日志记录所有分账操作,确保可追溯性。

总结:通过收付通的合单支付+分账能力,Java商城可实现多商户购物车合并支付及平台抽佣。核心在于合理设计资金冻结/解冻时机,遵守分账比例限制,并严格处理异步通知。完整API文档参考:微信支付平台收付通文档