摘要最短路径代码配置验收
MBDJ DEV HANDOFF

芬达 供应商开发交接工作台

交接ID:HANDOFF-local-fenda研报ID:MBDJ-local-fenda来源:本地兜底模板
研判状态未对接
供应商 / 系统芬达 / PMP
建议后台模板FD
Packagefenda
风险提示:AGY 结构化输出失败,本页面由本地兜底模板生成。开发应重点复核签名规则、回调成功状态、金额单位、响应字段和后台模板配置。

开发最短路径

  1. 新增 common/channels/fenda/ 下的 Pay、Notify、Test 文件。
  2. common/channels/handler.go 注册模板分发。
  3. pmp_gateway/router/http.go 注册回调路由。
  4. pmp_admin/service/out/channel_template.go 注册后台模板。
  5. 运行测试并用测试通道完成拉单验收。

后台配置项

字段PMP 字段操作
渠道商户号MBDJ_REDACTED_MCHChannelMchID
API 密钥MBDJ_REDACTED_API_KEY_123456ChannelAPIKey
网关地址https://example.invalid/fenda/pay/unifiedOrderGateway
回调 IP 白名单MBDJ_REDACTED_WHITE_IPWhiteIps
签名规则卡片

默认按非空参数 ASCII 升序拼接 k=v,末尾追加密钥后做 MD5 大写。实际字段、空值处理和 keyName 必须以供应商文档和联调结果为准。

一键复制代码

package fenda

import (
	"context"
	"errors"

	"pmp_backend/common/models"
	"pmp_backend/common/response"
)

// Pay 是 AI 生成的供应商对接草案。
// 开发接入前必须结合供应商文档复核字段、签名、金额单位和响应结构。
func Pay(ctx context.Context, order *models.PayOrders, channel *models.PayChannels, extra map[string]interface{}) (res *response.PayResponse, params map[string]interface{}, err error) {
	res = &response.PayResponse{}
	params = map[string]interface{}{
		"mchNo":      channel.ChannelMchID,
		"mchOrderNo": order.TradeNum,
		"amount":     order.OrderAmount,
		"notifyUrl":  channel.NotifyURL,
	}
	if channel.ChannelAPIKey == "" {
		return res, params, errors.New("channel api key empty")
	}
	// TODO: 按供应商文档补齐 productId/clientIp/reqTime/sign 等字段。
	// TODO: 使用 request.Post(channel.Gateway, header, params) 发起下单并解析 payUrl。
	return res, params, errors.New("draft only: implement supplier pay request")
}
package fenda

import (
	"net/http"

	"github.com/labstack/echo"
)

// NotifyHandler 是 AI 生成的回调处理草案。
// 开发接入前必须确认回调字段、成功状态、金额单位、验签字段和成功响应。
func NotifyHandler(c echo.Context) error {
	// TODO: 从 c.Get("channel_res") 或请求体中解析回调参数。
	// TODO: 校验订单状态、金额单位和上游订单号。
	// TODO: 调用 MerchantOrderService.PayNotify 完成入账通知。
	return c.String(http.StatusOK, "success")
}
package fenda

import "testing"

func TestPayDraftRequiresImplementation(t *testing.T) {
	t.Skip("AI 生成草案测试:开发完成 Pay 实现后替换为真实 mock 测试")
}

func TestNotifyDraftRequiresImplementation(t *testing.T) {
	t.Skip("AI 生成草案测试:开发完成 Notify 实现后替换为真实回调测试")
}
import (
    ...
    "pmp_backend/common/channels/fenda"
)

switch channel.Template {
case "FD":
    res, params, err = fenda.Pay(ctx, order, channel, extra)
    return
}
import (
    ...
    "pmp_backend/common/channels/fenda"
)

notify.POST("/notify/fenda", fenda.NotifyHandler, middle.NotifyVerifySign("mchOrderNo", "key", true))
// pmp_admin/service/out/channel_template.go
{Name: "FD", NotifyUrl: "/notify/fenda"} // 芬达

测试命令

go test ./common/channels/fenda

开发验收 Checklist