一、需求背景

本次分享的业务场景是:境外用户使用境外钱包扫码境内聚合码进行支付。整体设计采用后台模式,由微信支付受境外钱包委托完成商户信息获取及付款信息推送等环节。与境内常规收单业务相比,额外增加了:

  1. 微信支付受境外钱包委托向境内机构获取商户信息;
  2. 微信支付受境外钱包委托推送用户付款信息。

在这里插入图片描述

在这一实际项目中,我积极尝试将 AI 大模型融入日常开发流程,探索其在编码、调试、文档化等方面的应用效果。以下总结了我在项目中的经验与思考。

二、思维导图

在这里插入图片描述

三、AI 在项目中的实际应用

3.1 功能函数快速补全

在定义好函数签名后,通过对话式提示,AI 可以迅速补全函数内部逻辑。例如数据库连接、加解密函数、日志初始化等。这样能大幅减少样板代码的重复编写,提高专注度。

示例:

func loadViperConfig(localConfigFilePath string) (*AppConfig, error) {}
func InitZapLogger() *zap.Logger {}
func doConnect(user, pass, ip, dbName, port string, maxIdleCoon, maxOpenCoon, maxLifeTime int) (*gorm.DB, error) {}

func SendWeComRobotMessage(url, msg string, retries int) error {}
func TwoPhaseCommit(dbList []*gorm.DB, operation func(*gorm.DB) error) (err error) {}

func AES256GCMDecrypt(base64Data, associatedData, key, nonce string) ([]byte, error) {}
func AESCBCDecrypt(base64Data, base64Key, base64IV string) ([]byte, error) {}
func VerifyWithPublicKey(needSignStr, signature string, pubKey *rsa.PublicKey) error {}
func SignWithPrivateKey(needSignStr string, priKey *rsa.PrivateKey) (string, error) {}
func LoadRSAPrivateKey(privateKeyStr string) (*rsa.PrivateKey, error) {}
func LoadRSAPublicKey(publicKeyStr string) (*rsa.PublicKey, error) {}

func GetServerIP() (ipStr string) {}
func ExtractParamValueFromURL(rawURL, paramKey string) (paramValue string) {}
func RandLetters(n int) string {}

AI 会自动给出完整实现,包括错误处理与返回值。

3.2 构建与脚本自动生成

在编写 MakefileDockerfile、一次性 Shell/Python 脚本时,AI 能根据需求直接生成较为规范的脚手架,大大缩短准备时间。

示例:

# copilot begin
.PHONY: all clean

TARGET = td2_callback_processor

all: $(TARGET)

$(TARGET):
	go mod tidy && go build -o $(TARGET) main.go

clean:
	rm -f $(TARGET)
# copilot end

3.3 条件判断与补全

AI 对常见模式的识别能力较强,比如判空、错误检查、切片非空判断等,能够自动续写后续逻辑,减少遗漏。

示例:

func MustGetBusinessRedis(alias string) *redis.Client {
	rdb := global.BusinessRedisMap[alias]
	// copilot begin
	if rdb == nil {
		panic(fmt.Sprintf("redis instance %s not found", alias))
	}
	return rdb
    // copilot end
}
func doConnect(host, pass, master string) (*redis.Client, error) {
	// copilot begin
	// host 值校验
	if host == "" {
		return nil, fmt.Errorf("host can not be empty")
	}
	hosts := strings.Split(host, ",")
	for i := range hosts {
		hosts[i] = strings.TrimSpace(hosts[i])
	}
	if len(hosts) == 0 {
		return nil, fmt.Errorf("hosts can not be empty")
	}
	// copilot end
}
// err == nil 意味着记录存在
// 信息未发生变更时直接返回,注意传入的管控开始时间或管控结束时间可能为 nil。为空时使用数据库存储的开始和结束时间
// copilot begin
if o.ControlStartTime == nil {
    o.ControlStartTime = entityPO.ControlStartTime
}
if o.ControlEndTime == nil {
    o.ControlEndTime = entityPO.ControlEndTime
}
// copilot end

3.4 结构体与常量的联想补全

定义结构体、常量或枚举时,AI 能根据上下文联想出常用字段。

示例:

const (
	AppRuntimeEnvDev  = "dev"
	AppRuntimeEnvTest = "test"
	AppRuntimeEnvPre  = "pre"
	AppRuntimeEnvGray = "gray"
	AppRuntimeEnvProd = "prod"
)

const (
	LogLevelDebug = "debug"
	LogLevelInfo  = "info"
	LogLevelWarn  = "warn"
	LogLevelError = "error"
	LogLevelAll   = "all"
)

const (
	HeaderWechatPayTimestamp           = "Wechatpay-Timestamp"
	HeaderWechatPaySignature           = "Wechatpay-Signature"
	HeaderWechatPaySignatureTestPrefix = "WECHATPAY/SIGNTEST/"
	HeaderWechatPayNonce               = "Wechatpay-Nonce"
	HeaderWechatPaySerial              = "Wechatpay-Serial"
)
// 2. 验证必要签名头是否存在
var wechatSerial string
requiredHeaders := []string{
    constants.HeaderWechatPayTimestamp,
    constants.HeaderWechatPayNonce,
    constants.HeaderWechatPaySerial,
    constants.HeaderWechatPaySignature,
}
for _, header := range requiredHeaders {
    // copilot begin
    if headers.Get(header) == "" {
        tip = "请求头缺失必要验签字段"
        err = fmt.Errorf("missing required header: %s", header)
        return
    }
    if constants.HeaderWechatPaySerial == header {
        wechatSerial = headers.Get(header)
    }
    // copilot end
}

3.5 序列化与反序列化

在处理 JSONYAMLXML 数据时,AI 能自动生成对应的序列化或反序列化代码,尤其适合请求解析和配置文件加载。

示例:

// 5. 解析请求体
var callbackReq request.WechatCallbackRequest
// copilot begin
if err = json.Unmarshal(rawBody, &callbackReq); err != nil {
    tip = "解析请求体失败"
    err = fmt.Errorf("failed to unmarshal request body: %w", err)
    return
}
// copilot end
// 读取 Apollo 服务器配置
var apolloConfig ApolloConfig
if bytes, err := ioutil.ReadFile(apolloConfigFile); err != nil {
    return nil, err
} else {
    // copilot begin
    if err = yaml.Unmarshal(bytes, &apolloConfig); err != nil {
        return nil, err
    }
    // copilot end
}

3.6 日志与调试

AI 可根据上下文选择合适的日志输出,减少思考时间并保持日志风格统一。

示例:

// copilot begin
// 打印配置内容
if configBytes, err := json.MarshalIndent(appConfig, "", "\t"); err != nil {
    return nil, err
} else {
    log.Printf("====< application configuration content are bleow >====\n%s", string(configBytes))
}
// copilot end

3.7 注释转代码

清晰明确的注释内容,尤其是含有步骤顺序的注释内容,能较好地补全代码。

示例:

// 1. 记录所有请求头信息
for key, values := range headers {
    for _, value := range values {
        log.Infof("Header %s: %s", key, value)
    }
}

3.8 相似函数或逻辑联想补全

紧邻的相似函数或逻辑,有着固定的处理步骤,一般能根据上一段直接补全下一短。

示例:

// -- 查询 APIv3 密钥:F_type = 4
// select F_api3_secret_key from t_wx_sign_key_manage where F_org_id = ? and F_type = 4 and F_expire_time > now() order by F_expire_time desc limit 1;
err = db.Table(c.TableName()).
    Where("F_org_id = ? and F_type = 4 and F_expire_time > now()", c.OrgID).
    Order("F_expire_time desc").
    Limit(1).
    Pluck("F_api3_secret_key", &c.Api3SecretKey).Error
if err != nil {
    return
}
resultDTO.ApiV3Secret = c.Api3SecretKey

// copilot begin

// -- 查询微信平台证书公钥:F_type = 2
// select F_certificate_serial_no, F_rsa_public_key from t_wx_sign_key_manage where F_org_id = '1502075691' and F_type = 2 and F_expire_time > now() order by F_expire_time desc limit 1;
err = db.Table(c.TableName()).
    Where("F_org_id = ? and F_type = 2 and F_expire_time > now()", c.OrgID).
    Order("F_expire_time desc").
    Limit(1).
    Pluck("F_certificate_serial_no, F_rsa_public_key", &c).Error
if err != nil {
    return
}
resultDTO.WeChatSerial = c.CertificateSerialNo
resultDTO.WeChatPublicKeyStr = c.RsaPublicKey

// -- 查询商户 API 证书公私钥:F_type = 1
// select F_certificate_serial_no, F_rsa_public_key, F_rsa_private_key from t_wx_sign_key_manage where F_org_id = '1502075691' and F_type = 1 and F_expire_time > now() order by F_expire_time desc limit 1;
err = db.Table(c.TableName()).
    Where("F_org_id = ? and F_type = 1 and F_expire_time > now()", c.OrgID).
    Order("F_expire_time desc").
    Limit(1).
    Pluck("F_certificate_serial_no, F_rsa_public_key, F_rsa_private_key", &c).Error
if err != nil {
    return
}
resultDTO.MerchantSerial = c.CertificateSerialNo
resultDTO.MerchantPublicKeyStr = c.RsaPublicKey
resultDTO.MerchantPrivateKeyStr = c.RsaPrivateKey

// copilot end
// 加载微信平台证书公钥
certDTO.WeChatPublicKey, err = security.LoadRSAPublicKey(certDTO.WeChatPublicKeyStr)
if err != nil {
    return err
}

// copilot begin
// 加载商户 API 证书私钥
certDTO.MerchantPrivateKey, err = security.LoadRSAPrivateKey(certDTO.MerchantPrivateKeyStr)
if err != nil {
    return err
}

// 加载商户 API 证书公钥
certDTO.MerchantPublicKey, err = security.LoadRSAPublicKey(certDTO.MerchantPublicKeyStr)
if err != nil {
    return err
}
// copilot end
func combineAlias(node, name string) string {
	return fmt.Sprintf("%s:%s", node, name)
}

func splitAlias(alias string) (string, string) {
	// copilot begin
	parts := strings.SplitN(alias, ":", 2)
	if len(parts) == 2 {
		return parts[0], parts[1]
	}
	return "", ""
	// copilot end
}
lepayUrl := fmt.Sprintf("%s/cgi-bin/lepos_pay_gateway.cgi", global.AppCfg.Lepay.ServerUrl)
// copilot begin
reqObj, err := http.NewRequest("POST", lepayUrl, bytes.NewBuffer(reqBytes))
if err != nil {
    tip = "创建请求失败"
    return
}
reqObj.Header.Set("Content-Type", "application/json")

client := &http.Client{}
respObj, err := client.Do(reqObj)
if err != nil || respObj.StatusCode != http.StatusOK {
    tip = "请求下单失败"
    return
}
defer respObj.Body.Close()

respBody, err := ioutil.ReadAll(respObj.Body)
if err != nil {
    tip = "读取下单响应失败"
    return
}
// copilot end

3.9 数据循环遍历处理

针对切片或是 mapfor-range 循环,能较好地捕获到用户意图。

示例:

func GetLepayDBList() []*gorm.DB {
	var dbList []*gorm.DB
	aliases := []string{
		// copilot begin
		constants.LepayDBNodeLG01,
		constants.LepayDBNodeLG02,
		constants.LepayDBNodeSH01,
		constants.LepayDBNodeSH02,
		// copilot end
	}
	for _, item := range global.AppCfg.DBList {
		alias := combineAlias(item.Node, item.Name)
		// copilot begin
		for _, aliasItem := range aliases {
			if alias == aliasItem {
				dbList = append(dbList, MustGetBusinessDB(alias))
			}
		}
		// copilot end
	}
	return dbList
}

3.10 数据格式转换

JSON 数据或是 SQL 定义语句直接转换为 Go 结构体,并且提供实体方法。

示例:

type FixedQrCode struct {}

type WeChatCertificate struct {}
type WechatCallbackRequest struct {}

type WXOWQrCodeRequest struct {}
type WXOWOrderRequest struct {}
type WXOWQrCodeResponse struct {}
type WXOWOrderResponse struct {}

四、AI 应用的扩展与思考

除了上述实际体验,AI 在编码中的应用还有许多潜在方向:

4.1 代码审查与质量优化

  • 自动检测潜在 BUG(如空指针风险、未关闭的资源等)
  • 指出性能隐患与命名不规范问题

4.2 单元测试与用例生成

  • 自动生成覆盖率较高的单元测试
  • 快速生成边界条件与异常测试用例

4.3 跨语言迁移与代码翻译

  • 将核心逻辑从 Go 自动迁移到 Python/Java
  • 帮助团队降低异构系统之间的迁移成本

4.4 文档与注释自动化

  • 自动生成 Swagger/OpenAPI 接口文档
  • 基于函数签名生成简洁、规范的注释

4.5 DevOps 与自动化

  • 生成 CI/CD Pipeline 脚本(如 GitHub Actions
  • 辅助部署、运维脚本的编写

4.6 知识辅助与新人培养

  • 通过对话形式解释项目中的关键模块,帮助新人快速熟悉系统
  • 自动总结代码调用链,降低上手门槛

五、展望与趋势

  • 人机协作边界AI 擅长快速生成 80% 的基础代码,但最终的 20% 仍需开发者结合业务场景做决策
  • 隐私与合规性:在金融支付等高敏感场景,必须严格控制 AI 的使用边界,避免泄露关键数据
  • 研发流程变革:未来代码评审可能演变为 AI 初审 + 人工把关,大幅提升研发效率
  • 行业趋势IDEAI 的深度结合将使 对话式编程 成为常态,开发体验与生产力将迎来质的飞跃

六、总结

通过本次项目实践,我深切感受到 AI 大模型在编码中的价值:它能够节省时间、减少低级错误、提升代码一致性。同时,它也引发了我们对研发方式、合规边界与未来趋势的思考。期待未来能进一步探索 “AI + 研发” 的深度结合,真正把人从重复性工作中解放出来,把精力集中在业务创新和架构设计上。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐