- 在 consts/url.go 中新增分账结果查询 URL 常量 - 实现 SplitLedgerService 的 SplitLedgerResultQuery 方法 - 新增 model/splitLedgerResult.go 文件定义相关请求和响应结构体 - 支持通过 separate_no 或 out_separate_no 查询分账结果 - 返回详细的分账状态、金额及明细信息 |
||
|---|---|---|
| .idea | ||
| consts | ||
| lklsdk | ||
| model | ||
| README.md | ||
| go.mod | ||
| go.sum | ||
README.md
拉卡拉SDK
这是一个通用的拉卡拉SDK,提供了分账、交易、账户等功能的API接口封装,方便开发者快速集成拉卡拉支付服务。
目录结构
lklsdk/
├── account.go # 账户相关功能
├── common/ # 通用工具和客户端
│ ├── client.go # 核心客户端
│ ├── json_cleaner.go # JSON清理工具
│ └── structs.go # 通用结构体定义
├── merchant.go # 商户相关功能
├── merchant/ # 商户相关模块
│ └── in_net/ # 网络接口
│ └── ec/ # 电子合同功能
│ ├── apply/ # 电子合同申请
│ │ ├── api.go # API实现
│ │ ├── request.go # 请求结构体
│ │ └── response.go # 响应结构体
│ ├── applymanual/ # 电子合同人工复核申请
│ │ ├── api.go # API实现
│ │ ├── request.go # 请求结构体
│ │ └── response.go # 响应结构体
│ ├── download/ # 电子合同下载
│ │ ├── api.go # API实现
│ │ ├── request.go # 请求结构体
│ │ └── response.go # 响应结构体
│ ├── qmastatus/ # 电子合同人工复核结果查询
│ │ ├── api.go # API实现
│ │ ├── request.go # 请求结构体
│ │ └── response.go # 响应结构体
│ └── querystatus/ # 电子合同签署状态查询
│ ├── api.go # API实现
│ ├── request.go # 请求结构体
│ └── response.go # 响应结构体
├── mergePre.go # 主扫合单交易功能
├── sdk.go # SDK主入口
├── split_ledger.go # 分账基本功能
├── split_ledger_more.go # 分账扩展功能
├── trade.go # 交易相关功能
├── unifiedreturn/ # 统一退款功能
│ ├── mergerefund/ # 合并退款
│ ├── refund/ # 退款
│ ├── refundfee/ # 退款手续费
│ └── refundquery/ # 退款查询
└── uploadFile.go # 文件上传相关功能
安装
# 将SDK引入到您的项目中
go get -u github.com/black1552/lkl_sdk
快速开始
初始化SDK
import (
"github.com/black1552/lkl_sdk/lklsdk"
"github.com/black1552/lkl_sdk/model"
"github.com/black1552/lkl_sdk/consts"
"github.com/gogf/gf/v2/os/gctx"
)
// 创建配置JSON字符串
cfgJson := `{
"public_key": "your_public_key", // 公钥字符串
"private_key": "your_private_key", // 私钥字符串
"app_id": "your_app_id", // lakala应用ID
"serial_no": "your_serial_no", // 序列号
"sub_app_id": "your_sub_app_id", // 子应用ID 微信AppId
"version": "3.0", // lakala版本号
"account_type": "WECHAT", // 账户类型
"trans_type": "71", // 交易类型
"notify_url": "your_notify_url" // 回调地址
}`
// 初始化SDK(使用泛型指定响应类型)
sdk := lklsdk.NewSDK[model.ResponseType](gctx.New(), cfgJson)
功能模块
1. 主扫合单交易
// 初始化特定响应类型的SDK
sdk := lklsdk.NewSDK[model.MergePreorderResponse](gctx.New(), cfgJson)
// 准备拆单信息
outSplitInfo := []*model.OutSplitInfo{
{
OutSubTradeNo: "子交易流水号1",
MerchantNo: config.MerchantNo,
TermNo: config.TermNo,
Amount: "100", // 1元
},
{
OutSubTradeNo: "子交易流水号2",
MerchantNo: config.MerchantNo,
TermNo: config.TermNo,
Amount: "200", // 2元
},
}
// 构建位置信息
locationInfo := &model.LocationInfo{
RequestIp: "127.0.0.1",
}
// 构建请求参数
mergePreorderReq := &model.MergePreorderReqData{
MerchantNo: config.MerchantNo,
TermNo: config.TermNo,
OutTradeNo: "商户交易流水号",
OutSplitInfo: outSplitInfo,
AccountType: "WECHAT",
TransType: "71",
TotalAmount: "300", // 3元
LocationInfo: locationInfo,
Subject: "测试订单",
NotifyUrl: "https://your-notify-url.com",
}
// 调用接口
mergePreorderResp, err := sdk.MergePreOrder(mergePreorderReq)
if err != nil {
log.Printf("主扫合单交易失败: %v\n", err)
}
// 使用SuccessOrFail方法判断请求是否成功
if !mergePreorderResp.SuccessOrFail() {
log.Printf("主扫合单交易失败: %s\n", mergePreorderResp.Msg)
}
2. 商户分账业务开通申请
// 初始化特定响应类型的SDK
sdk := lklsdk.NewSDK[model.ApplyLedgerMerResponse](gctx.New(), cfgJson)
// 构建请求参数
applyLedgerReq := &model.ApplyLedgerMerReqData{
Version: "1.0",
OrderNo: "12345678901234567890123456789012", // 32位订单号
OrgCode: "123456789012", // 机构代码
MerInnerNo: "1234567821", // 拉卡拉内部商户号
MerCupNo: "", // 银联商户号(与内部商户号二选一)
ContactMobile: "13311111111", // 联系手机号
SplitLowestRatio: 3.51, // 最低分账比例
SplitEntrustFileName: "授权委托书.pdf", // 授权委托书文件名
SplitEntrustFilePath: "path", // 授权委托书文件路径
SplitRange: consts.SPLIT_RANGE_ALL, // 分账范围(ALL全部交易分账,MARK标记交易分账)
RetUrl: "notifyUrl.com", // 回调URL
}
// 调用接口
expectResp, err := sdk.ApplyLedgerMer(applyLedgerReq)
if err != nil {
log.Printf("商户分账业务开通申请失败: %v\n", err)
}
// 使用SuccessOrFail方法判断请求是否成功
if !expectResp.SuccessOrFail() {
log.Printf("商户分账业务开通申请失败: %s\n", expectResp.RetMsg)
}
3. 交易查询
// 初始化特定响应类型的SDK
sdk := lklsdk.NewSDK[model.TradeQueryResponse](gctx.New(), cfgJson)
// 构建请求参数
tradeQueryReq := &model.TradeQueryReqData{
MerchantNo: config.MerchantNo,
TermNo: config.TermNo,
OutTradeNo: "商户订单号", // 替换为实际的商户订单号
}
// 调用接口
tradeQueryResp, err := sdk.TradeQuery(tradeQueryReq)
if err != nil {
log.Printf("交易查询失败: %v\n", err)
}
// 使用SuccessOrFail方法判断请求是否成功
if !tradeQueryResp.SuccessOrFail() {
log.Printf("交易查询失败: %s\n", tradeQueryResp.Msg)
}
4. 订单分账
// 初始化特定响应类型的SDK
sdk := lklsdk.NewSDK[model.OrderSplitLedgerResponse](gctx.New(), cfgJson)
// 准备分账接收方数据
var recvDatas []*model.OrderSplitLedgerRecvDatas
// 可以向recvDatas数组中添加分账接收方信息
// 构建请求参数
splitLedgerReq := &model.OrderSplitLedgerReqData{
MerchantNo: config.MerchantNo,
LogDate: "", // 交易日期,格式为yyyyMMdd
LogNo: "", // 拉卡拉对账单流水号
OutSeparateNo: "", // 商户分账指令流水号
TotalAmt: "", // 分账总金额,单位为分
LklOrgNo: "", // 拉卡拉机构编号
CalType: consts.CAL_TYPE_AMOUNT, // 分账计算类型(0-按金额,1-按比例)
NotifyUrl: "", // 回调地址
RecvDatas: recvDatas, // 分账接收方数据
}
// 调用接口
splitLedgerResp, err := sdk.OrderSplitLedger(splitLedgerReq)
if err != nil {
log.Printf("订单分账失败: %v\n", err)
}
// 使用SuccessOrFail方法判断请求是否成功
if !splitLedgerResp.SuccessOrFail() {
log.Printf("订单分账失败: %s\n", splitLedgerResp.Msg)
}
5. 退款
// 初始化特定响应类型的SDK
sdk := lklsdk.NewSDK[model.RefundResponse](gctx.New(), cfgJson)
// 构建请求参数
refundReq := &model.RefundReqData{
MerchantNo: "your_merchant_no", // 商户号
TermNo: "your_term_no", // 终端号
OutTradeNo: "original_out_trade_no", // 原商户交易流水号
OutRefundNo: "your_refund_out_trade_no", // 退款商户流水号
RefundAmount: "100", // 退款金额,单位为分
TotalAmount: "100", // 原交易总金额,单位为分
RefundReason: "退款原因", // 退款原因
NotifyUrl: "https://your-notify-url.com", // 回调地址
}
// 调用接口
refundResp, err := sdk.Refound(refundReq)
if err != nil {
log.Printf("退款失败: %v\n", err)
}
// 使用SuccessOrFail方法判断请求是否成功
if !refundResp.SuccessOrFail() {
log.Printf("退款失败: %s\n", refundResp.Msg)
}
// 处理成功响应
// 可以从refundResp.RespData中获取退款结果数据
6. 账户余额查询
// 初始化特定响应类型的SDK
sdk := lklsdk.NewSDK[model.BalanceQueryResponse](gctx.New(), cfgJson)
// 构建请求参数
balanceQueryReq := &model.BalanceQueryReqData{
MerchantNo: config.MerchantNo,
OrgNo: "", // 机构号
PayNo: "", // 支付单号
PayType: consts.PAY_TYPE_CARD, // 支付类型(CARD-卡支付,COUPON-优惠券支付,DISCOUNT-折扣支付,POINT-积分支付,MIX-混合支付)
MgtFlag: consts.MGT_FLAG_NO, // 管理标志(NO-普通交易,YES-管理交易)
}
// 调用接口
balanceQueryResp, err := sdk.BalanceQuery(balanceQueryReq)
if err != nil {
log.Printf("账户余额查询失败: %v\n", err)
}
// 使用SuccessOrFail方法判断请求是否成功
if !balanceQueryResp.SuccessOrFail() {
log.Printf("账户余额查询失败: %s\n", balanceQueryResp.Msg)
}
错误处理
SDK使用两层错误处理机制,请确保同时检查网络错误和业务响应状态:
// 1. 首先检查网络或SDK层面的错误
resp, err := sdk.SomeFunction(req)
if err != nil {
log.Printf("调用接口失败: %v\n", err)
// 处理网络错误或SDK内部错误
return err
}
// 2. 然后使用SuccessOrFail()方法判断业务响应是否成功
if !resp.SuccessOrFail() {
log.Printf("业务处理失败: %s\n", resp.Msg) // 或resp.RetMsg
// 处理业务失败情况
return errors.New("业务处理失败")
}
// 处理成功响应
// 使用resp获取返回的数据
7. 账户提现
// 初始化特定响应类型的SDK
sdk := lklsdk.NewSDK[model.WithdrawResponse](gctx.New(), cfgJson)
// 构建请求参数
withdrawReq := &model.WithdrawReqData{
MerchantNo: "your_merchant_no", // 商户号
TermNo: "your_term_no", // 终端号
OutTradeNo: "your_withdraw_out_trade_no", // 提现商户流水号
Amount: "10000", // 提现金额,单位为分
Currency: "CNY", // 货币类型
AccountType: "WECHAT", // 账户类型
}
// 调用接口
withdrawResp, err := sdk.Withdraw(withdrawReq)
if err != nil {
log.Printf("账户提现失败: %v\n", err)
}
// 使用SuccessOrFail方法判断请求是否成功
if !withdrawResp.SuccessOrFail() {
log.Printf("账户提现失败: %s\n", withdrawResp.Msg)
}
8. 商户进件
// 初始化特定响应类型的SDK
sdk := lklsdk.NewSDK[model.MerchantApplyResponse](gctx.New(), cfgJson)
// 构建请求参数
merchantApplyReq := &model.MerchantApplyReqData{
// 填写商户进件所需的各项参数
MerchantName: "商户名称",
ContactName: "联系人姓名",
ContactPhone: "联系电话",
// ... 其他必要参数
}
// 调用接口
merchantApplyResp, err := sdk.AddMer(merchantApplyReq)
if err != nil {
log.Printf("商户进件失败: %v\n", err)
}
// 使用SuccessOrFail方法判断请求是否成功
if !merchantApplyResp.SuccessOrFail() {
log.Printf("商户进件失败: %s\n", merchantApplyResp.Msg)
}
9. 商户进件信息查询
// 初始化特定响应类型的SDK
sdk := lklsdk.NewSDK[model.QueryMerResponse](gctx.New(), cfgJson)
// 构建请求参数
queryMerReq := &model.QueryMerRequestData{
MerchantNo: "your_merchant_no", // 商户号
// ... 其他必要参数
}
// 调用接口
queryMerResp, err := sdk.QueryMerchant(queryMerReq)
if err != nil {
log.Printf("商户进件信息查询失败: %v\n", err)
}
// 使用SuccessOrFail方法判断请求是否成功
if !queryMerResp.SuccessOrFail() {
log.Printf("商户进件信息查询失败: %s\n", queryMerResp.Msg)
}
10. 商户进件信息校验
// 初始化特定响应类型的SDK
sdk := lklsdk.NewSDK[model.MerValidateResponse](gctx.New(), cfgJson)
// 构建请求参数
merValidateReq := &model.MerValidateRequestData{
// 填写商户进件校验所需的各项参数
MerchantName: "商户名称",
// ... 其他必要参数
}
// 调用接口
merValidateResp, err := sdk.MerValidate(merValidateReq)
if err != nil {
log.Printf("商户进件信息校验失败: %v\n", err)
}
// 使用SuccessOrFail方法判断请求是否成功
if !merValidateResp.SuccessOrFail() {
log.Printf("商户进件信息校验失败: %s\n", merValidateResp.Msg)
}
11. 商户进件复议提交
// 初始化特定响应类型的SDK
sdk := lklsdk.NewSDK[model.ReConfSubmitResponse](gctx.New(), cfgJson)
// 构建请求参数
reConfSubmitReq := &model.ReConfSubmitRequestData{
// 填写商户进件复议所需的各项参数
MerchantNo: "your_merchant_no",
// ... 其他必要参数
}
// 调用接口
reConfSubmitResp, err := sdk.ReconsiderSubmit(reConfSubmitReq)
if err != nil {
log.Printf("商户进件复议提交失败: %v\n", err)
}
// 使用SuccessOrFail方法判断请求是否成功
if !reConfSubmitResp.SuccessOrFail() {
log.Printf("商户进件复议提交失败: %s\n", reConfSubmitResp.Msg)
}
12. 聚合预下单
// 初始化特定响应类型的SDK
sdk := lklsdk.NewSDK[model.PreorderResponse](gctx.New(), cfgJson)
// 构建请求参数
preOrderReq := &model.PreorderReqData{
MerchantNo: "your_merchant_no", // 商户号
TermNo: "your_term_no", // 终端号
OutTradeNo: "your_out_trade_no", // 商户交易流水号
AccountType: "WECHAT", // 账户类型
TransType: "71", // 交易类型
Amount: "100", // 金额,单位为分
Subject: "测试订单", // 订单标题
NotifyUrl: "https://your-notify-url.com", // 回调地址
}
// 调用接口
preOrderResp, err := sdk.PreOrder(preOrderReq)
if err != nil {
log.Printf("聚合预下单失败: %v\n", err)
}
// 使用SuccessOrFail方法判断请求是否成功
if !preOrderResp.SuccessOrFail() {
log.Printf("聚合预下单失败: %s\n", preOrderResp.Msg)
}
13. 文件上传查询
// 初始化特定响应类型的SDK
sdk := lklsdk.NewSDK[model.UploadFileResponse](gctx.New(), cfgJson)
// 构建请求参数
uploadFileReq := &model.UploadFileReqData{
// 填写文件上传查询所需的各项参数
// ...
}
// 调用接口
uploadFileResp, err := sdk.UploadFileQuery(uploadFileReq)
if err != nil {
log.Printf("文件上传查询失败: %v\n", err)
}
// 使用SuccessOrFail方法判断请求是否成功
if !uploadFileResp.SuccessOrFail() {
log.Printf("文件上传查询失败: %s\n", uploadFileResp.Msg)
}
14. 分账接收方创建申请
// 初始化特定响应类型的SDK
sdk := lklsdk.NewSDK[model.ApplyLedgerReceiverResponse](gctx.New(), cfgJson)
// 构建请求参数
applyLedgerReceiverReq := &model.ApplyLedgerReceiverReqData{
MerchantNo: "your_merchant_no", // 商户号
TermNo: "your_term_no", // 终端号
ReceiverType: "PERSON", // 接收方类型
ReceiverName: "接收方名称", // 接收方名称
ReceiverNo: "接收方编号", // 接收方编号
ReceiverAccNo: "接收方账号", // 接收方账号
// ... 其他必要参数
}
// 调用接口
applyLedgerReceiverResp, err := sdk.ApplyLedgerReceiver(applyLedgerReceiverReq)
if err != nil {
log.Printf("分账接收方创建申请失败: %v\n", err)
}
// 使用SuccessOrFail方法判断请求是否成功
if !applyLedgerReceiverResp.SuccessOrFail() {
log.Printf("分账接收方创建申请失败: %s\n", applyLedgerReceiverResp.Msg)
}
15. 分账关系绑定申请
// 初始化特定响应类型的SDK
sdk := lklsdk.NewSDK[model.ApplyBindResponse](gctx.New(), cfgJson)
// 构建请求参数
applyBindReq := &model.ApplyBindReqData{
MerchantNo: "your_merchant_no", // 商户号
TermNo: "your_term_no", // 终端号
ReceiverType: "PERSON", // 接收方类型
ReceiverNo: "接收方编号", // 接收方编号
BindType: "1", // 绑定类型
// ... 其他必要参数
}
// 调用接口
applyBindResp, err := sdk.ApplyBind(applyBindReq)
if err != nil {
log.Printf("分账关系绑定申请失败: %v\n", err)
}
// 使用SuccessOrFail方法判断请求是否成功
if !applyBindResp.SuccessOrFail() {
log.Printf("分账关系绑定申请失败: %s\n", applyBindResp.Msg)
}
16. 可分账金额查询
// 初始化特定响应类型的SDK
sdk := lklsdk.NewSDK[model.SplitBalanceResponse](gctx.New(), cfgJson)
// 构建请求参数
splitBalanceReq := &model.SplitBalanceReqData{
MerchantNo: "your_merchant_no", // 商户号
TermNo: "your_term_no", // 终端号
// ... 其他必要参数
}
// 调用接口
splitBalanceResp, err := sdk.QuerySplitBalance(splitBalanceReq)
if err != nil {
log.Printf("可分账金额查询失败: %v\n", err)
}
// 使用SuccessOrFail方法判断请求是否成功
if !splitBalanceResp.SuccessOrFail() {
log.Printf("可分账金额查询失败: %s\n", splitBalanceResp.Msg)
}
错误处理
SDK使用两层错误处理机制,请确保同时检查网络错误和业务响应状态:
// 1. 首先检查网络或SDK层面的错误
resp, err := sdk.SomeFunction(req)
if err != nil {
log.Printf("调用接口失败: %v\n", err)
// 处理网络错误或SDK内部错误
return err
}
// 2. 然后使用SuccessOrFail()方法判断业务响应是否成功
if !resp.SuccessOrFail() {
log.Printf("业务处理失败: %s\n", resp.Msg) // 或resp.RetMsg
// 处理业务失败情况
return errors.New("业务处理失败")
}
// 处理成功响应
// 使用resp获取返回的数据
注意事项
- 请妥善保管您的AppID、商户号、密钥等敏感信息
- 确保网络环境稳定,避免请求超时
- 建议添加请求重试机制,处理网络波动
- 请遵循拉卡拉的接口规范,不要频繁调用接口
- 如遇到问题,请参考拉卡拉官方文档或联系技术支持