Files
baseapi/platformapi/lakala/lakala_separate_accounts.go
2025-11-21 09:09:09 +08:00

642 lines
19 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package lakala
import (
"encoding/json"
"errors"
"fmt"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/globals"
"net/http"
"time"
)
// CreateSeparate 进件成功的门店创建分账
func (a *API) CreateSeparate(param *CreateSeparateReq) (string, error) {
if (param.SplitLaunchMode == SplitLaunchModeAuto || param.SplitLaunchMode == SplitLaunchModePointRule) && param.SplitRuleSource == "" {
return "", fmt.Errorf("当分账发起方式为%s/%s时,分账规则来源不能为空", SplitLaunchModeAuto, SplitLaunchModePointRule)
}
reqParameter := map[string]interface{}{
"reqData": utils.Struct2Map(param, "", false),
"reqId": param.OrderNo,
"version": Version,
"reqTime": utils.Time2TimeStrByFormat(time.Now(), TimeFormat),
}
result, err := a.AccessAPISign(SeparateAccountProdUrl, SeparateAccountApplyAction, http.MethodPost, "", reqParameter)
if err != nil {
return "", err
}
bodyResult, err := json.Marshal(result)
if err != nil {
return "", err
}
resp := &CreateSeparateResp{}
if err = json.Unmarshal(bodyResult, resp); err != nil {
return "", err
}
if resp.RetCode != Success {
return "", fmt.Errorf(resp.RetMsg)
}
return utils.Int64ToStr(resp.RespData.ApplyId), nil
}
// SeparateModify 商户申请变更分账商户
func (a *API) SeparateModify(modify *SeparateModifyReq) (string, error) {
if modify.MerInnerNo == "" && modify.MerCupNo == "" {
return "", fmt.Errorf("k卡拉卡内部账号或银联账号不能同时为空")
}
reqParameter := map[string]interface{}{
"reqData": utils.Struct2Map(modify, "", false),
"reqId": modify.OrderNo,
"version": Version,
"reqTime": utils.Time2TimeStrByFormat(time.Now(), TimeFormat),
}
result, err := a.AccessAPISign(SeparateAccountProdUrl, SeparateAccountModifyAction, http.MethodPost, "", reqParameter)
if err != nil {
return "", err
}
bodyResult, err := json.Marshal(result)
if err != nil {
return "", err
}
resp := &CreateSeparateResp{}
if err = json.Unmarshal(bodyResult, resp); err != nil {
return "", err
}
if resp.RetCode != Success {
return "", fmt.Errorf(resp.RetMsg)
}
return utils.Int64ToStr(resp.RespData.ApplyId), nil
}
// SeparateQuery 商户分账信息查询
func (a *API) SeparateQuery(query *SeparateQueryReq) (*SeparateQueryResp, error) {
if query.MerInnerNo == "" && query.MerCupNo == "" {
return nil, fmt.Errorf("卡卡拉卡内部账号或银联账号不能同时为空")
}
reqParameter := map[string]interface{}{
"reqData": utils.Struct2Map(query, "", false),
"reqId": query.OrderNo,
"version": Version,
"reqTime": utils.Time2TimeStrByFormat(time.Now(), TimeFormat),
}
result, err := a.AccessAPISign(SeparateAccountProdUrl, SeparateAccountQueryAction, http.MethodPost, "", reqParameter)
if err != nil {
return nil, err
}
if result["retCode"].(string) != Success {
return nil, fmt.Errorf(result["retMsg"].(string))
}
bodyResult, err := json.Marshal(result["respData"])
if err != nil {
return nil, err
}
resp := &SeparateQueryResp{}
if err = json.Unmarshal(bodyResult, resp); err != nil {
return nil, err
}
return resp, nil
}
// CreateSeparateRecipient 创建分账接收方
func (a *API) CreateSeparateRecipient(recipient *CreateSeparateRecipientReq) (string, error) {
switch recipient.AcctTypeCode {
case BankTypeEnterprise:
if recipient.AcctNo == "" {
return "", fmt.Errorf("收款账户账户类型为对公,必须上送[营业执照编号]")
}
if recipient.LicenseName == "" {
return "", fmt.Errorf("收款账户账户类型为对公,必须上送[营业执照名称]")
}
if recipient.LegalPersonName == "" {
return "", fmt.Errorf("收款账户账户类型为对公,必须上送[法人姓名]")
}
if recipient.LegalPersonCertificateType == "" {
return "", fmt.Errorf("收款账户账户类型为对公,必须上送[法人证件类型]")
}
if recipient.LegalPersonCertificateNo == "" {
return "", fmt.Errorf("收款账户账户类型为对公,必须上送[法人证件号]")
}
default:
}
reqParameter := map[string]interface{}{
"reqData": utils.Struct2Map(recipient, "", false),
"reqId": recipient.OrderNo,
"version": Version,
"reqTime": utils.Time2TimeStrByFormat(time.Now(), TimeFormat),
}
result, err := a.AccessAPISign(SeparateAccountProdUrl, SeparateReceiverApplyAction, http.MethodPost, "", reqParameter)
if err != nil {
return "", err
}
bodyResult, err := json.Marshal(result)
if err != nil {
return "", err
}
resp := &CreateSeparateRecipientResp{}
if err = json.Unmarshal(bodyResult, resp); err != nil {
return "", err
}
if resp.RetCode != Success {
return "", fmt.Errorf(resp.RetMsg)
}
return resp.RespData.ReceiverNo, nil
}
// UpdateSeparateRecipient 分账接收方变更申请
func (a *API) UpdateSeparateRecipient(param *UpdateSeparateRecipientReq) (string, error) {
if param.ReceiverNo == "" {
return "", fmt.Errorf("分账接收方编号不能为空")
}
reqParameter := map[string]interface{}{
"reqData": utils.Struct2Map(param, "", false),
"reqId": param.OrderNo,
"version": Version,
"reqTime": utils.Time2TimeStrByFormat(time.Now(), TimeFormat),
}
result, err := a.AccessAPISign(SeparateAccountProdUrl, SeparateReceiverModifyAction, http.MethodPost, "", reqParameter)
if err != nil {
return "", err
}
bodyResult, err := json.Marshal(result)
if err != nil {
return "", err
}
resp := &CreateSeparateRecipientResp{}
if err = json.Unmarshal(bodyResult, resp); err != nil {
return "", err
}
if resp.RetCode != Success {
return "", fmt.Errorf(resp.RetMsg)
}
return resp.RespData.OrderNo, nil
}
// QuerySeparateRecipient 分账方详细信息查询
func (a *API) QuerySeparateRecipient(orderNo, receiverNo string) (*QuerySeparateRecipientResp, error) {
reqParameter := map[string]interface{}{
"reqData": map[string]string{
"version": Version,
"orderNo": orderNo,
"orgCode": a.orgCode,
"receiverNo": receiverNo,
},
}
result, err := a.AccessAPISign(SeparateAccountProdUrl, SeparateReceiverQueryAction, http.MethodPost, "", reqParameter)
if err != nil {
return nil, err
}
if result["retCode"] != Success {
return nil, errors.New(result["retMsg"].(string))
}
bodyResult, err := json.Marshal(result["respData"])
if err != nil {
return nil, err
}
resp := &QuerySeparateRecipientResp{}
if err = json.Unmarshal(bodyResult, resp); err != nil {
return nil, err
}
return resp, nil
}
// ApplyBind 申请绑定分账关系
func (a *API) ApplyBind(param *SeparateApplyBindReq) (*SeparateApplyBindResp, error) {
reqParameter := map[string]interface{}{
"reqData": utils.Struct2Map(param, "", false),
"reqId": param.OrderNo,
"version": Version,
"reqTime": utils.Time2TimeStrByFormat(time.Now(), TimeFormat),
}
result, err := a.AccessAPISign(SeparateAccountProdUrl, SeparateBindAction, http.MethodPost, "", reqParameter)
if err != nil {
return nil, err
}
bodyResult, err := json.Marshal(result)
if err != nil {
return nil, err
}
resp := &SeparateApplyBindResp{}
if err = json.Unmarshal(bodyResult, resp); err != nil {
return nil, err
}
if resp.RetCode != Success {
return nil, fmt.Errorf(resp.RetMsg)
}
return resp, nil
}
// SeparateUnBind 申请解除绑定
func (a *API) SeparateUnBind(param *SeparateUnBindReq) (string, error) {
reqParameter := map[string]interface{}{
"reqData": utils.Struct2Map(param, "", false),
"reqId": param.OrderNo,
"version": Version,
"reqTime": utils.Time2TimeStrByFormat(time.Now(), TimeFormat),
}
result, err := a.AccessAPISign(SeparateAccountProdUrl, SeparateUnBindAction, http.MethodPost, "", reqParameter)
if err != nil {
return "", err
}
bodyResult, err := json.Marshal(result)
if err != nil {
return "", err
}
resp := &SeparateApplyBindResp{}
if err = json.Unmarshal(bodyResult, resp); err != nil {
return "", err
}
if resp.RetCode != Success {
return "", fmt.Errorf(resp.RetMsg)
}
return utils.Int64ToStr(resp.RespData.ApplyId), nil
}
// Separate 分账
func (a *API) Separate(param *OrderSeparateReq) (*OrderSeparateResp, error) {
reqParameter := map[string]interface{}{
"req_data": utils.Struct2Map(param, "", false),
"version": Version,
"req_time": utils.Time2TimeStrByFormat(time.Now(), TimeFormat),
}
result, err := a.AccessAPISign(SeparateProd, SeparateOrder, http.MethodPost, "", reqParameter)
if err != nil {
return nil, err
}
bodyResult, err := json.Marshal(result)
if err != nil {
return nil, err
}
resp := &OrderSeparateResp{}
if err = json.Unmarshal(bodyResult, resp); err != nil {
return nil, err
}
if resp.Code != SeparateSuccess {
return nil, fmt.Errorf(resp.Msg)
}
return resp, nil
}
// SeparateCancel 订单分账撤销
func (a *API) SeparateCancel(param *SeparateCancelReq) (*SeparateCancelResp, error) {
reqParameter := map[string]interface{}{
"req_data": utils.Struct2Map(param, "", false),
"version": Version,
"req_time": utils.Time2TimeStrByFormat(time.Now(), TimeFormat),
}
result, err := a.AccessAPISign(SeparateProd, SeparateCancel, http.MethodPost, "", reqParameter)
if err != nil {
return nil, err
}
bodyResult, err := json.Marshal(result)
if err != nil {
return nil, err
}
resp := &SeparateCancelResp{}
if err = json.Unmarshal(bodyResult, resp); err != nil {
return nil, err
}
if resp.Code != SeparateSuccess {
return nil, fmt.Errorf(resp.Msg)
}
return resp, err
}
// SeparateFallBack 分账退回
func (a *API) SeparateFallBack(param *SeparateFallReq) (*SeparateFallResp, error) {
reqParameter := map[string]interface{}{
"req_data": utils.Struct2Map(param, "", false),
"version": Version,
"req_time": utils.Time2TimeStrByFormat(time.Now(), TimeFormat),
}
globals.SugarLogger.Debugf("------SeparateFallBack param := %s", utils.Format4Output(param, false))
result, err := a.AccessAPISign(SeparateProd, SeparateFallBack, http.MethodPost, "", reqParameter)
globals.SugarLogger.Debugf("------SeparateFallBack result := %s", utils.Format4Output(result, false))
globals.SugarLogger.Debugf("------SeparateFallBack err := %v", err)
if err != nil {
return nil, err
}
bodyResult, err := json.Marshal(result)
if err != nil {
return nil, err
}
resp := &SeparateFallResp{}
if err = json.Unmarshal(bodyResult, resp); err != nil {
return nil, err
}
if resp.Code != SeparateSuccess {
return nil, fmt.Errorf(resp.Msg)
}
return resp, err
}
// SeparateResultQuery 分账结果查询
func (a *API) SeparateResultQuery(merchantNo, separateNo string) (*SeparateResultQueryResp, error) {
reqData := map[string]string{
"merchant_no": merchantNo,
"separate_no": separateNo,
}
reqParameter := map[string]interface{}{
"req_data": reqData,
"version": Version,
"req_time": utils.Time2TimeStrByFormat(time.Now(), TimeFormat),
}
result, err := a.AccessAPISign(SeparateProd, SeparateQuery, http.MethodPost, "", reqParameter)
if err != nil {
return nil, err
}
if result["code"].(string) != SeparateSuccess {
return nil, fmt.Errorf(result["msg"].(string))
}
bodyResult, err := json.Marshal(result["resp_data"])
if err != nil {
return nil, err
}
resp := &SeparateResultQueryResp{}
if err = json.Unmarshal(bodyResult, resp); err != nil {
return nil, err
}
return resp, err
}
// SeparateQueryAmt 可分账金额查询
func (a *API) SeparateQueryAmt(merchantNo, logNo, logDate string) (*SeparateQueryAmtResp, error) {
reqData := map[string]string{
"merchant_no": merchantNo,
"log_no": logNo,
"log_date": logDate,
}
reqParameter := map[string]interface{}{
"req_data": reqData,
"version": Version,
"req_time": utils.Time2TimeStrByFormat(time.Now(), TimeFormat),
}
result, err := a.AccessAPISign(SeparateProd, SeparateQueryAmt, http.MethodPost, "", reqParameter)
if err != nil {
return nil, err
}
if result["code"].(string) != SeparateSuccess {
return nil, fmt.Errorf(result["msg"].(string))
}
bodyResult, err := json.Marshal(result["resp_data"])
if err != nil {
return nil, err
}
resp := &SeparateQueryAmtResp{}
if err = json.Unmarshal(bodyResult, resp); err != nil {
return nil, err
}
return resp, err
}
// QueryCarBin 卡BIN查询
func (a *API) QueryCarBin(orderNo, orgCode, cardNo string) (*BinInfo, error) {
reqData := map[string]string{
"version": "1.0",
"orderNo": orderNo,
"orgCode": orgCode,
"cardNo": cardNo,
}
reqParameter := map[string]interface{}{
"reqData": reqData,
"ver": Version,
"timestamp": utils.Int64ToStr(time.Now().Unix()),
"reqId": utils.GetUUID(),
}
result, err := a.AccessAPISign(SeparateAccountProdUrl, SeparateCardBinAction, http.MethodPost, "", reqParameter)
if err != nil {
return nil, err
}
if result["retCode"].(string) != Success {
return nil, fmt.Errorf(result["retMsg"].(string))
}
bodyResult, err := json.Marshal(result["respData"])
if err != nil {
return nil, err
}
resp := &BinInfo{}
if err = json.Unmarshal(bodyResult, resp); err != nil {
return nil, err
}
return resp, err
}
// SaveAuthentication 微信支付宝认证
func (a *API) SaveAuthentication(param *AuthenticationInfo, authType string) error {
reqData := utils.Struct2Map(param, "", false)
activityUrl := WeChatAuthentication
if authType == AuthenticationType {
reqData["realNameType"] = AuthenticationType
activityUrl = AlibabaAuthentication
}
reqParameter := map[string]interface{}{
"reqData": reqData,
"ver": Version,
"timestamp": utils.Int64ToStr(time.Now().Unix()),
"reqId": utils.GetUUID(),
}
result, err := a.AccessAPISign(SeparateAccountProdUrl, activityUrl, http.MethodPost, "", reqParameter)
if err != nil {
return err
}
if result["retCode"].(string) != Success {
return errors.New(result["retMsg"].(string))
}
return nil
}
// UpdateAuthentication 实名认证修改
// https://o.lakala.com/#/home/document/detail?id=183
func (a *API) UpdateAuthentication(param *UpdateAuthentication, authType string) error {
reqData := utils.Struct2Map(param, "", false)
activityUrl := WeChatUpdateAuthentication
if authType == AuthenticationType {
activityUrl = AlibabaUpdateAuthentication
}
reqParameter := map[string]interface{}{
"reqData": reqData,
"ver": Version,
"timestamp": utils.Int64ToStr(time.Now().Unix()),
"reqId": utils.GetUUID(),
}
result, err := a.AccessAPISign(SeparateAccountProdUrl, activityUrl, http.MethodPost, "", reqParameter)
if err != nil {
return err
}
if result["retCode"].(string) != Success {
return errors.New(result["retMsg"].(string))
}
return nil
}
// QueryAuthentication 实名认证查询
// https://o.lakala.com/#/home/document/detail?id=181
func (a *API) QueryAuthentication(param *QueryAuthentication, authType string) (*QueryAuthenticationResp, error) {
reqData := utils.Struct2Map(param, "", false)
activityUrl := WeChatQueryAuthentication
if authType == AuthenticationType {
reqData["realNameType"] = AuthenticationType
activityUrl = AlibabaQueryAuthentication
}
reqParameter := map[string]interface{}{
"reqData": reqData,
"ver": Version,
"timestamp": utils.Int64ToStr(time.Now().Unix()),
"reqId": utils.GetUUID(),
}
result, err := a.AccessAPISign(SeparateAccountProdUrl, activityUrl, http.MethodPost, "", reqParameter)
if err != nil {
return nil, err
}
if result["retCode"].(string) != Success {
return nil, errors.New(result["retMsg"].(string))
}
body, err := json.Marshal(result["respData"])
if err != nil {
return nil, err
}
resp := &QueryAuthenticationResp{}
if err = json.Unmarshal(body, resp); err != nil {
return nil, err
}
return resp, nil
}
// AccountStatusQuery 开户状态查询
// https://o.lakala.com/#/home/document/detail?id=528
func (a *API) AccountStatusQuery(tradeMode, subMerchantId, merchantNo string) (map[string]interface{}, error) {
reqParameter := map[string]interface{}{
"reqData": map[string]interface{}{"tradeMode": tradeMode, "subMerchantId": subMerchantId, "merchantNo": merchantNo},
"ver": Version,
"timestamp": utils.Int64ToStr(time.Now().Unix()),
"reqId": utils.GetUUID(),
}
result, err := a.AccessAPISign(PayAccountProdUrl, WeChatAccountStatusQuery, http.MethodPost, "", reqParameter)
if err != nil {
return nil, err
}
if result["retCode"].(string) != Success {
return nil, errors.New(result["retMsg"].(string))
}
return result["respData"].(map[string]interface{}), nil
}
// SubMerchantInfoQuery 报备查询
// https://o.lakala.com/#/home/document/detail?id=326
func (a *API) SubMerchantInfoQuery(param *SubMerchantInfoQueryReq) ([]*SubMerchantInfoQueryResp, error) {
reqParameter := map[string]interface{}{
"reqData": utils.Struct2Map(param, "", false),
}
result, err := a.AccessAPISign(SeparateAccountProdUrl, SubMerchantQuery, http.MethodPost, "", reqParameter)
if err != nil {
return nil, err
}
if result["retCode"].(string) != Success {
return nil, errors.New(result["retMsg"].(string))
}
if result["respData"] != nil && result["respData"].(map[string]interface{}) != nil {
list := make([]*SubMerchantInfoQueryResp, 0, 0)
data, err := json.Marshal(result["respData"].(map[string]interface{})["list"])
if err != nil {
return nil, err
}
if err = json.Unmarshal(data, &list); err != nil {
return nil, err
}
return list, nil
}
return nil, errors.New("返回值为空")
}
// SubMerchantInfoQueryReq 报备查询
type SubMerchantInfoQueryReq struct {
Version string `json:"version"` // 必传 String 8 接口版本号 1.0
OrderNo string `json:"orderNo"` // 必传 String 32 订单编号,保证唯一(便于后续跟踪排查问题及核对报文) 14位年月日时24小时制分秒+8位的随机数不重复2021020112000012345678
OrgCode string `json:"orgCode"` // 必传 String 32 机构代码 (合作方在拉卡拉的标识,请联系业务员) 1
MerInnerNo string `json:"merInnerNo"` // 可传 String 32 拉卡拉内部商户号和银联商户号必须传一个,都送以内部商户号为准。 5002022050550024285
MerCupNo string `json:"merCupNo"` // 可传 String 32 拉卡拉内部商户号和银联商户号必须传一个,都送以内部商户号为准。 8222900581207ET
RegisterChannel string `json:"registerChannel"` // 可选 String 8 报备渠道 UNIONPAY
RegisterType string `json:"registerType"` // 可选 String 64 报备类型 WXZF
RegisterStatus string `json:"registerStatus"` // 可选 String 64 报备状态 SUCCESS成功FAIL失败 SUCCESS
SubMchId string `json:"subMchId"` // 可选 String 64 子商户号
}
// SubMerchantInfoQueryResp 报备查询返回值
type SubMerchantInfoQueryResp struct {
MerInnerNo string `json:"merInnerNo"` // 内部商户号
SubMchId string `json:"subMchId"` // 子商户号
SubMchIdBank string `json:"subMchIdBank"` // 交易子商户号
DcWalletId string `json:"dcWalletId"` // 数币钱包ID
RegisterType string `json:"registerType"` // 报备类型
RegisterTypeText string `json:"registerTypeText"`
RegisterChannel string `json:"registerChannel"` // 报备渠道
RegisterChannelText string `json:"registerChannelText"`
ChannelId string `json:"channelId"` // 渠道号
ReceOrgNo string `json:"receOrgNo"` // 从业机构号
RegisterTm string `json:"registerTm"` // 报备时间
RegisterStatus string `json:"registerStatus"` // 报备状态
ResultCode string `json:"resultCode"` // 结果返回码
ResultMessage string `json:"resultMessage"` // 结果描述
}