This commit is contained in:
邹宗楠
2025-06-24 13:50:48 +08:00
parent 7fd163485c
commit b2d23c1587
15 changed files with 3268 additions and 72 deletions

View File

@@ -0,0 +1,146 @@
package lakala
import (
"encoding/json"
"fmt"
"git.rosy.net.cn/baseapi/platformapi/lakala"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/model"
"git.rosy.net.cn/jx-callback/business/model/dao"
"git.rosy.net.cn/jx-callback/business/partner"
"time"
)
// CreateSeparateShop 商户分账业务回调(创建/修改)
func CreateSeparateShop(callback *lakala.SeparateCallback) error {
var (
db = dao.GetDB()
)
merchantInfo, err := dao.GetStoreInfoByMerchantID(db, callback.MerCupNo, 0, callback.ApplyId, "")
if err != nil {
return err
}
if callback.AuditStatus == utils.Int2Str(model.YES) {
merchantInfo.OperateStatus = model.OperateStatusSuccess
} else {
merchantInfo.OperateStatus = model.OperateStatusFail
}
_, err = dao.UpdateEntity(db, merchantInfo, "OperateStatus")
if err != nil {
return err
}
return nil
}
// BindSeparateBand 绑定/解绑业务
func BindSeparateBand(callback *lakala.SeparateBindCallback) error {
var (
db = dao.GetDB()
)
bindInfo, err := dao.GetStoreInfoByMerchantID(db, callback.MerCupNo, 0, callback.ApplyId, "")
if err != nil {
return err
}
unBind := make(map[string]*model.BindAccountObj, 0)
if err = json.Unmarshal([]byte(bindInfo.BindAccount), &unBind); err != nil {
return err
}
if unBind[callback.ReceiverNo].ApplyId == callback.ApplyId {
unBind[callback.ReceiverNo] = &model.BindAccountObj{
ApplyId: callback.ApplyId,
Status: callback.AuditStatus,
Remark: fmt.Sprintf(callback.AuditStatusText + ":" + callback.Remark),
}
}
byteBind, err := json.Marshal(unBind)
if err != nil {
return err
}
bindInfo.BindAccount = string(byteBind)
if _, err = dao.UpdateEntity(db, bindInfo, "BindAccount"); err != nil {
return err
}
return nil
}
// GetSeparateRecordsCallback 分账结果回调
func GetSeparateRecordsCallback(callback *lakala.SeparateResult) error {
var (
db = dao.GetDB()
)
separateRecord, err := dao.GetSeparateRecords(db, "", callback.SeparateNo, callback.CmdType)
if err != nil {
return err
}
separateRecord.CmdType = callback.CmdType
separateRecord.FinishDate = callback.FinishDate
separateRecord.TotalAmt = callback.TotalAmt
separateRecord.Status = callback.Status
separateRecord.FinalStatus = callback.FinalStatus
separateRecord.UpdatedAt = time.Now()
_, err = dao.UpdateEntity(db, separateRecord, "CmdType", "FinishDate", "TotalAmt", "Status1", "Status2", "Status3", "FinalStatus", "UpdatedAt")
return err
}
// EwalletWithdrawD1Callback 结算信息回调
func EwalletWithdrawD1Callback(param *lakala.EwalletWithdrawD1CallBack) error {
var (
db = dao.GetDB()
)
withDraw, err := dao.GetEwalletWithDraw(db, param.MercId, param.DrawJnl)
if err != nil {
return err
}
withDraw.ReqDate = param.ReqDate
withDraw.DrawAmt = param.DrawAmt
withDraw.DrawFee = param.DrawFee
withDraw.BatchAutoSettle = param.BatchAutoSettle
withDraw.AcctNo = param.AcctNo
withDraw.AcctName = param.AcctName
withDraw.DrawState = param.DrawState
withDraw.Memo = param.Memo
withDraw.CreatedTime = utils.Str2Time(param.CreatedTime)
withDraw.CompleteTime = utils.Str2Time(param.CompleteTime)
_, err = dao.UpdateEntity(db, withDraw)
return err
}
// OrderStatusCallback 订单状态回调 todo param.OrderStatus=6 时暂时无法区分全部退款还是部分退款
func OrderStatusCallback(param *lakala.QueryOrderCallBackResp) error {
var (
db = dao.GetDB()
)
order, err := partner.CurOrderManager.LoadOrder(param.OrderCreateTime, model.VendorIDJX)
if err != nil {
return err
}
// 0:待支付 1:支付中 2:支付成功 3:支付失败 4:已过期 5:已取消 6部分退款或者全部退款
switch param.OrderStatus {
case "0", "1":
order.Status = model.OrderStatusWait4Pay
case "2":
if order.DeliveryType == model.OrderDeliveryTypeSelfTake {
order.Status = model.OrderStatusFinished
order.OrderFinishedAt = time.Now()
} else {
order.Status = model.OrderStatusAccepted
}
case "3":
order.Status = model.OrderStatusWait4Pay
case "4", "5":
order.Status = model.OrderStatusCanceled
order.OrderFinishedAt = time.Now()
case "6":
}
order.VendorStatus = param.OrderStatus
_, err = dao.UpdateEntity(db, order, "Status", "VendorStatus", "OrderFinishedAt")
return err
}

View File

@@ -0,0 +1,821 @@
package lakala
import (
"encoding/json"
"fmt"
"git.rosy.net.cn/baseapi/platformapi/lakala"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
"git.rosy.net.cn/jx-callback/business/model"
"git.rosy.net.cn/jx-callback/business/model/dao"
"git.rosy.net.cn/jx-callback/business/partner"
"git.rosy.net.cn/jx-callback/globals/api"
"strings"
"time"
)
//#region 进件相关API
// LaKaLaInComing 商户进件
func LaKaLaInComing(ctx *jxcontext.Context, incoming *lakala.MerchantIncomingReq, storeId int) (string, error) {
merchantNo, status, err := api.LaKaLaApi.MerchantIncoming(incoming)
if err != nil {
return "", err
}
incomingObj := &model.LakalaIncoming{
StoreId: storeId,
MerchantNo: merchantNo,
MerchantStatus: status,
}
dao.WrapAddIDCULDEntity(incomingObj, ctx.GetUserName())
if err = dao.CreateEntity(dao.GetDB(), incoming); err != nil {
return "", err
}
return status, nil
}
// GetMerchantInfo 获取门店商户详情
func GetMerchantInfo(merchantNo string) (*lakala.MerchantObj, error) {
result, err := api.LaKaLaApi.GetMerchantInfo(merchantNo)
if err != nil {
return nil, err
}
db := dao.GetDB()
merchantInfo, err := dao.GetStoreInfoByMerchantID(db, merchantNo, 0, "", "")
if err != nil {
return nil, err
}
if merchantInfo.TermNo == "" {
termNo := make([]string, 0, 0)
for _, v := range result.TerminalInfo {
termNo = append(termNo, v.TermNoList...)
}
if len(termNo) != model.NO {
merchantInfo.TermNo = strings.Join(termNo, ",")
dao.UpdateEntity(db, merchantInfo, "TermNo")
}
}
return result, err
}
// QueryCityCode 获取拉卡拉code列表
func QueryCityCode(parentCode string) ([]*lakala.OrganizationList, error) {
return api.LaKaLaApi.GetOrganizationCode(parentCode)
}
// QueryBankList 获取地方银行列表
func QueryBankList(areaCode, bankName string) ([]*lakala.BankListResult, error) {
if areaCode == "" {
return nil, fmt.Errorf("地区编码不能为空")
}
return api.LaKaLaApi.GetBankList(areaCode, bankName)
}
// GetCustomerCategory 获取门店类别
func GetCustomerCategory(businessScene, parentCode string) ([]*lakala.BusinessResult, error) {
return api.LaKaLaApi.GetMerchantMcc(businessScene, parentCode)
}
// MerchantFeeQuery 商户费率查询
func MerchantFeeQuery(customerNo, productCode string) (*lakala.MerchantFeeResp, error) {
return api.LaKaLaApi.MerchantFeeQuery(customerNo, productCode)
}
// MerchantFeeChange 商户费率信息变更
func MerchantFeeChange(param *lakala.FeeChangeReq, customerNo string) (int, string, error) {
changeId, status, err := api.LaKaLaApi.MerchantFeeChange(param, customerNo)
if err != nil {
return 0, "", err
}
if changeId != model.NO {
db := dao.GetDB()
merchant, err := dao.GetStoreInfoByMerchantID(db, customerNo, 0, "", "")
if err != nil {
return 0, "", err
}
merchant.FeeId = utils.Int2Str(changeId)
merchant.FeeStatus = status
dao.UpdateEntity(db, merchant, "FeeId", "FeeStatus")
}
return changeId, status, err
}
// UpdateSettleInfo 查询/修改结算信息
func UpdateSettleInfo(customerNo string, param *lakala.UpdateSettleInfoReq) (*lakala.UpdateSettleInfoReq, string, error) {
updateResult, queryResult, err := api.LaKaLaApi.UpdateSettleInfo(customerNo, param)
if err != nil {
return nil, "", err
}
if param == nil {
return queryResult, "", err
}
if updateResult.StatusCodeValue != 200 {
return nil, "", fmt.Errorf(updateResult.StatusCode)
} else {
db := dao.GetDB()
merchant, err := dao.GetStoreInfoByMerchantID(db, customerNo, 0, "", "")
if err != nil {
return nil, "", err
}
merchant.SettleId = utils.Int2Str(updateResult.Body.ReviewRelatedId)
merchant.SettleStatus = updateResult.Body.Message
dao.UpdateEntity(db, merchant, "SettleID", "SettleStatus")
return nil, updateResult.Body.Message, nil
}
}
// MerchantUpdateBaseInfo 基本信息变更
func MerchantUpdateBaseInfo(customerNo string, param *lakala.UpdateBaseInfoReq) (string, error) {
basic, err := api.LaKaLaApi.UpdateBaseInfo(customerNo, param)
if err != nil {
return "", err
}
if basic.StatusCodeValue != 200 {
return "", fmt.Errorf(basic.StatusCode)
}
if basic.Body.ReviewRelatedId != model.NO {
db := dao.GetDB()
merchant, err := dao.GetStoreInfoByMerchantID(db, customerNo, 0, "", "")
if err != nil {
return "", err
}
merchant.BasicId = utils.Int2Str(basic.Body.ReviewRelatedId)
merchant.BasicStatus = basic.Body.Message
dao.UpdateEntity(db, merchant, "BasicId", "BasicStatus")
return merchant.BasicId, nil
}
return "", fmt.Errorf("UpdateBaseInfo 修改异常,联系管理员")
}
// QueryExamine 查询门店变更审核状态
func QueryExamine(merchantId, reviewRelatedId string) (map[string]string, error) {
reviewPass, reviewResult, err := api.LaKaLaApi.QueryMerchantReviewStatus(reviewRelatedId)
if err != nil {
return nil, err
}
db := dao.GetDB()
merchant, err := dao.GetStoreInfoByMerchantID(db, merchantId, 0, "", "")
if err != nil {
return nil, err
}
updateField := make([]string, 0, 0)
switch reviewRelatedId {
case merchant.FeeId:
merchant.FeeStatus = reviewPass
updateField = append(updateField, "FeeStatus")
case merchant.SettleId:
merchant.SettleStatus = reviewPass
updateField = append(updateField, "SettleStatus")
case merchant.BasicId:
merchant.BasicStatus = reviewPass
updateField = append(updateField, "BasicStatus")
case merchant.LicenseId:
merchant.LicenseStatus = reviewPass
updateField = append(updateField, "LicenseStatus")
}
if len(updateField) != 0 {
dao.UpdateEntity(db, merchant, updateField...)
}
return map[string]string{"status": reviewPass, "desc": reviewResult}, err
}
// CheckIsUploadPhoto 查看门店是否需要补充照片
func CheckIsUploadPhoto(customerNo string) (*lakala.OpenCustomerExtImgVo, error) {
return api.LaKaLaApi.CheckImgIsSupplement(customerNo)
}
// ImgSupplement 补充照片
func ImgSupplement(param *lakala.ImgSupplementReq) error {
if param.ExtCustomerNo == "" {
return fmt.Errorf("商户号不能为空")
}
return api.LaKaLaApi.ImgSupplement(param)
}
// GetMerchantReportStatus 查看银联报备状态
func GetMerchantReportStatus(orgCode, agentNo, customerNo string) (*lakala.OpenUnionpayMerchantVo, error) {
return api.LaKaLaApi.GetMerchantReportStatus(orgCode, agentNo, customerNo)
}
// GetMerchantTerminal 获取终端报备信息
func GetMerchantTerminal(orgCode, agentNo, externalCustomerNo, posSn string) (*lakala.OpenUnionpayTermVo, error) {
return api.LaKaLaApi.GetMerchantTerminal(orgCode, agentNo, externalCustomerNo, posSn)
}
// SupplementBusinessLicense 变更营业执照
func SupplementBusinessLicense(param *lakala.BusinessLicenseReq) (string, error) {
licenseId, status, err := api.LaKaLaApi.SupplementBusinessLicense(param)
if err != nil {
return "", err
}
db := dao.GetDB()
merchant, err := dao.GetStoreInfoByMerchantID(db, param.ExternalCustomerNo, 0, "", "")
if err != nil {
return "", err
}
merchant.LicenseId = licenseId
merchant.LicenseStatus = status
if _, err = dao.UpdateEntity(db, merchant, "LicenseId", "LicenseStatus"); err != nil {
return "", err
}
return status, nil
}
// UnionPayMerInfo 联防机制查询(失信人名单)
func UnionPayMerInfo(larName, larIdCard string) (*lakala.DishonestPerson, error) {
return api.LaKaLaApi.UnionPayMerInfo(larName, larIdCard)
}
//#endregion
//#region 分账相关
// CreateSeparate 创建分账门店
func CreateSeparate(req *lakala.CreateSeparateReq) (string, error) {
req.OrderNo = lakala.GetOrderNumber(8)
req.RetUrl = lakala.CallbackLaKaLaShopUrl
applyID, err := api.LaKaLaApi.CreateSeparate(req)
if err != nil {
return "", err
}
db := dao.GetDB()
merchant, err := dao.GetStoreInfoByMerchantID(db, req.MerInnerNo, 0, "", "")
if err != nil {
return "", err
}
merchant.OrderID = req.OrderNo
merchant.ApplyID = applyID
merchant.ThingType = model.ThingTypeSeparate
merchant.Operate = model.OperateTypeCreate
merchant.OperateStatus = model.OperateStatusReview
merchant.Remark = fmt.Sprintf("创建分账:%s", req.OrderNo)
if _, err = dao.UpdateEntity(db, merchant, "OrderID", "ApplyID", "ThingType", "Operate", "OperateStatus", "Remark"); err != nil {
return "", err
}
return applyID, nil
}
// SeparateModify 变更分账门店
func SeparateModify(param *lakala.SeparateModifyReq) (string, error) {
db := dao.GetDB()
merchant, err := dao.GetStoreInfoByMerchantID(db, param.MerInnerNo, 0, "", "")
if err != nil {
return "", err
}
if merchant.OperateStatus == model.OperateStatusReview {
return "", fmt.Errorf("有待审核项目,请审核完成后再变更")
}
param.OrderNo = lakala.GetOrderNumber(8)
param.RetUrl = lakala.CallbackLaKaLaShopUrl
applyID, err := api.LaKaLaApi.SeparateModify(param)
if err != nil {
return "", err
}
merchant.OrderID = param.OrderNo
merchant.ApplyID = applyID
merchant.ThingType = model.ThingTypeSeparate
merchant.Operate = model.OperateTypeUpdate
merchant.OperateStatus = model.OperateStatusReview
merchant.Remark = fmt.Sprintf("修改分账:%s", param.OrderNo)
if _, err = dao.UpdateEntity(db, merchant, "OrderID", "ApplyID", "ThingType", "Operate", "OperateStatus"); err != nil {
return "", err
}
return applyID, nil
}
// SeparateQuery 分账信息查询
func SeparateQuery(merInnerNo, orgCode string) (*lakala.SeparateQueryResp, error) {
param := &lakala.SeparateQueryReq{
Version: lakala.Version2,
OrderNo: lakala.GetOrderNumber(8),
OrgCode: orgCode,
MerInnerNo: merInnerNo,
MerCupNo: "",
}
return api.LaKaLaApi.SeparateQuery(param)
}
// CreateSeparateRecipient 创建分账接收方
func CreateSeparateRecipient(ctx *jxcontext.Context, param *lakala.CreateSeparateRecipientReq) (string, error) {
param.OrderNo = lakala.GetOrderNumber(8)
receiverNo, err := api.LaKaLaApi.CreateSeparateRecipient(param)
if err != nil {
return "", err
}
receiver := &model.LakalaRecipient{}
dao.WrapAddIDCULDEntity(receiver, ctx.GetUserName())
receiver.ReceiverNo = receiverNo
receiver.ReceiverName = param.ReceiverName
receiver.OrgCode = param.OrgCode
receiver.Status = model.ReceiverStatusValid
receiver.Remark = fmt.Sprintf("创建分账接收方:%s", param.OrderNo)
if err = dao.CreateEntity(dao.GetDB(), receiver); err != nil {
return "", err
}
return receiverNo, err
}
// UpdateSeparateRecipient 修改分账接收方
func UpdateSeparateRecipient(param *lakala.UpdateSeparateRecipientReq) (string, error) {
param.OrderNo = lakala.GetOrderNumber(8)
orderNo, err := api.LaKaLaApi.UpdateSeparateRecipient(param)
if err != nil {
return "", err
}
db := dao.GetDB()
recipient, err := dao.GetRecipientByMerchantID(db, param.ReceiverNo)
recipient.ReceiverName = param.ReceiverName
recipient.Status = param.Status
recipient.Remark = fmt.Sprintf("修改分账接收方:%s", param.OrderNo)
_, err = dao.UpdateEntity(db, recipient, "ReceiverName", "Status", "Remark")
if err != nil {
return "", err
}
return orderNo, nil
}
// QuerySeparateRecipient 分账方详细信息查询
func QuerySeparateRecipient(orderNo, receiverNo string) (*lakala.QuerySeparateRecipientResp, error) {
return api.LaKaLaApi.QuerySeparateRecipient(orderNo, receiverNo)
}
// ApplyBind 申请绑定分账关系
func ApplyBind(param *lakala.SeparateApplyBindReq) (*lakala.SeparateApplyBindResp, error) {
param.OrderNo = lakala.GetOrderNumber(8)
param.RetUrl = lakala.CallbackLaKaLaSeparateBindUrl
applyInfo, err := api.LaKaLaApi.ApplyBind(param)
if err != nil {
return nil, err
}
db := dao.GetDB()
merchant, err := dao.GetStoreInfoByMerchantID(db, param.MerInnerNo, 0, "", "")
if err != nil {
return nil, err
}
bind := map[string]*model.BindAccountObj{param.ReceiverNo: &model.BindAccountObj{
ApplyId: utils.Int64ToStr(applyInfo.RespData.ApplyId),
Status: "0",
Remark: "新增绑定",
}}
bodyBind, _ := json.Marshal(bind)
merchant.BindAccount = string(bodyBind)
_, err = dao.UpdateEntity(db, merchant, "BindAccount")
if err != nil {
return nil, err
}
return applyInfo, nil
}
// SeparateUnBind 申请解除绑定
func SeparateUnBind(param *lakala.SeparateUnBindReq) error {
param.OrderNo = lakala.GetOrderNumber(8)
param.RetUrl = lakala.CallbackLaKaLaSeparateBindUrl
applyId, err := api.LaKaLaApi.SeparateUnBind(param)
if err != nil {
return err
}
db := dao.GetDB()
merchant, err := dao.GetStoreInfoByMerchantID(db, param.MerInnerNo, 0, "", "")
if err != nil {
return err
}
unBind := make(map[string]*model.BindAccountObj, 0)
if err = json.Unmarshal([]byte(merchant.BindAccount), &unBind); err != nil {
return err
}
unBind[param.ReceiverNo] = &model.BindAccountObj{
ApplyId: applyId,
Status: "0",
Remark: "解除绑定",
}
bodyBind, _ := json.Marshal(unBind)
merchant.BindAccount = string(bodyBind)
if _, err = dao.UpdateEntity(db, merchant, "BindAccount"); err != nil {
return err
}
return nil
}
// SeparateQueryAmt 可分账金额查询
func SeparateQueryAmt(merchantNo, logNo, logDate string) (*lakala.SeparateQueryAmtResp, error) {
logNo = lakala.GetOrderNumber(8)
logDate = utils.Time2TimeStrByFormat(time.Now(), "20060102")
result, err := api.LaKaLaApi.SeparateQueryAmt(merchantNo, logNo, logDate)
if err != nil {
return nil, err
}
db := dao.GetDB()
merchant, err := dao.GetStoreInfoByMerchantID(db, merchantNo, 0, "", "")
if err != nil {
return nil, err
}
merchant.TotalAmt = result.TotalSeparateAmt
merchant.CanAmt = result.CanSeparateAmt
if _, err = dao.UpdateEntity(db, merchant, "TotalAmt", "CanAmt"); err != nil {
return nil, err
}
return result, err
}
// Separate 分账
func Separate(ctx *jxcontext.Context, param *lakala.OrderSeparateReq) (string, string, error) {
param.LogNo = lakala.GetOrderNumber(8)
param.LogDate = utils.Time2TimeStrByFormat(time.Now(), "20060102")
param.OutSeparateNo = lakala.GetOrderNumber(10)
param.NotifyUrl = lakala.CallbackLaKaLaSeparateUrl
status, separateNo, err := api.LaKaLaApi.Separate(param)
if err != nil {
return "", "", err
}
recv, _ := json.Marshal(param.RecvDatas)
separateData := &model.LakalaSeparateAmt{
MerchantNo: param.MerchantNo,
OutSeparateNo: param.OutSeparateNo, // 商户分账指令流水号
SeparateNo: separateNo,
CalType: param.CalType,
FinishDate: "",
TotalAmt: param.TotalAmt,
Status: status,
DetailData: string(recv),
Remark: "分账",
}
t, err := time.Parse("20060102", param.LogDate)
if err != nil {
t = time.Now()
}
separateData.LogDate = t
dao.WrapAddIDCULDEntity(separateData, ctx.GetUserName())
if err = dao.CreateEntity(dao.GetDB(), separateData); err != nil {
return "", "", err
}
return status, separateNo, nil
}
// SeparateResultQuery 分账结果查询
func SeparateResultQuery(merchantNo, separateNo string) (*lakala.SeparateResultQueryResp, error) {
result, err := api.LaKaLaApi.SeparateResultQuery(merchantNo, separateNo)
if err != nil {
return nil, err
}
db := dao.GetDB()
recordsObj, err := dao.GetSeparateRecords(db, merchantNo, separateNo, result.CmdType)
if err != nil {
return nil, err
}
recordsObj.UpdatedAt = time.Now()
recordsObj.TotalAmt = result.TotalAmt
recordsObj.ActualSeparateAmt = result.ActualSeparateAmt
recordsObj.TotalFeeAmt = result.TotalFeeAmt
recordsObj.Status = result.Status
if len(result.DetailDatas) != 0 {
detail, _ := json.Marshal(result.DetailDatas)
recordsObj.DetailData = string(detail)
}
if _, err = dao.UpdateEntity(db, recordsObj); err != nil {
return nil, err
}
return result, nil
}
// SeparateCancel 订单分账撤销
func SeparateCancel(merchantNo, separateNo string) (*lakala.SeparateCancelResp, error) {
db := dao.GetDB()
separateAmt, err := dao.GetSeparateRecords(db, merchantNo, separateNo, "")
if err != nil {
return nil, err
}
result, err := api.LaKaLaApi.SeparateCancel(&lakala.SeparateCancelReq{
MerchantNo: merchantNo,
OriginSeparateNo: separateNo,
OriginOutSeparateNo: "",
OutSeparateNo: lakala.GetOrderNumber(8),
TotalAmt: separateAmt.TotalAmt,
})
if err != nil {
return nil, err
}
separateAmt.Status = result.RespData.Status
separateAmt.SeparateNo = result.RespData.SeparateNo
separateAmt.Remark += ",分账撤销"
if _, err = dao.UpdateEntity(db, separateAmt, "SeparateNo2", "Status2", "Remark"); err != nil {
return nil, err
}
return result, err
}
// SeparateFallBack 分账退回
func SeparateFallBack(merchantNo, separateNo, reason string) (*lakala.SeparateFallResp, error) {
db := dao.GetDB()
separateAmt, err := dao.GetSeparateRecords(db, merchantNo, separateNo, "")
if err != nil {
return nil, err
}
recv := make([]*lakala.RecvDatasParam, 0, 0)
if err = json.Unmarshal([]byte(separateAmt.DetailData), &recv); err != nil {
return nil, err
}
if len(recv) == 0 {
return nil, fmt.Errorf("数据异常[%s],未获取到分账详细", separateNo)
}
param := &lakala.SeparateFallReq{
MerchantNo: merchantNo,
OriginSeparateNo: separateNo,
OutSeparateNo: lakala.GetOrderNumber(8),
FallbackReason: reason,
TotalAmt: separateAmt.TotalAmt,
OriginRecvDatas: nil,
}
originRecvDatas := make([]*lakala.OriginRecvDatas, 0, len(recv))
for _, v := range recv {
originRecvDatas = append(originRecvDatas, &lakala.OriginRecvDatas{
RecvNo: v.RecvNo,
Amt: v.SeparateValue,
})
}
param.OriginRecvDatas = originRecvDatas
result, err := api.LaKaLaApi.SeparateFallBack(param)
if err != nil {
return nil, err
}
separateAmt.Status = result.RespData.Status
separateAmt.SeparateNo = result.RespData.SeparateNo
separateAmt.Remark += ",分账退回"
return result, nil
}
//#endregion
//#region 订单相关
// CreateOrder 创建拉卡拉交易订单
func CreateOrder(vendorOrderID, merchantNo string, vendorId int) (*lakala.CreateOrderResp, error) {
order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, vendorId)
if err != nil {
return nil, err
}
param := &lakala.CreateOrderReq{
OutOrderNo: order.VendorOrderID,
MerchantNo: merchantNo,
TotalAmount: order.ActualPayPrice,
OrderEfficientTime: time.Now().Add(1 * time.Hour).Format("20060102150405"),
OrderInfo: fmt.Sprintf("门店扫码订单:%d", order.OrderSeq),
NotifyUrl: lakala.OrderStatusCallback,
}
result, err := api.LaKaLaApi.CreateOrder(param)
if err != nil {
return nil, err
}
return result, nil
}
// CloseOrder 关闭待支付订单
func CloseOrder(merchantId, vendorOrderId string, vendorId int) (string, error) {
param := &lakala.CloseOrderReq{
MerchantNo: merchantId,
OutOrderNo: vendorOrderId,
PayOrderNo: "",
ChannelId: "",
}
result, err := api.LaKaLaApi.CloseOrder(param)
if err != nil {
return "", err
}
order, err := partner.CurOrderManager.LoadOrder(vendorOrderId, vendorId)
if err != nil {
return "", err
}
switch result {
case lakala.OrderCloseStatusPayFail, lakala.OrderCloseStatusExpire, lakala.OrderCloseStatusCancel, lakala.OrderCloseStatusRefund, lakala.OrderCloseStatusClose:
order.Status = model.OrderStatusCanceled
order.VendorStatus = result
dao.UpdateEntity(dao.GetDB(), order, "Status", "VendorStatus")
}
return result, err
}
// QueryOrder 收银台订单查询
func QueryOrder(vendorOrderId, merchantId string, vendorId int) (*lakala.QueryOrderResp, error) {
result, err := api.LaKaLaApi.QueryOrder(vendorOrderId, merchantId)
if err != nil {
return nil, err
}
order, err := partner.CurOrderManager.LoadOrder(vendorOrderId, vendorId)
if err != nil {
return nil, err
}
switch result.OrderStatus {
case lakala.OrderCloseStatusPayFail, lakala.OrderCloseStatusExpire, lakala.OrderCloseStatusCancel, lakala.OrderCloseStatusRefund, lakala.OrderCloseStatusClose:
order.Status = model.OrderStatusCanceled
order.VendorStatus = result.OrderStatus
case lakala.OrderCloseStatusPaySuccess:
order.Status = model.OrderStatusFinished
order.VendorStatus = result.OrderStatus
order.OrderFinishedAt = time.Now()
}
dao.UpdateEntity(dao.GetDB(), order, "Status", "VendorStatus", "OrderFinishedAt")
return result, nil
}
//#endregion
//#region 账户相关
// QueryBillBalance 查询账户余额
func QueryBillBalance(orgNo, merchantNo, payType string) (*lakala.QueryBillBalanceResp, error) {
result, err := api.LaKaLaApi.QueryBillBalance(&lakala.QueryBillBalanceReq{
OrgNo: orgNo,
MerchantNo: merchantNo,
PayType: payType,
})
return result, err
}
// EwalletWithdrawD1 申请提现
func EwalletWithdrawD1(ctx *jxcontext.Context, orgNo, merchantNo, payType, drawAmt string) error {
param := &lakala.EwalletWithdrawD1Req{
OrgNo: orgNo,
MerchantNo: merchantNo,
DrawAmt: drawAmt,
NotifyUrl: lakala.BillProdCallbackUrl,
MerOrderNo: lakala.GetOrderNumber(8),
PayNo: "",
PayType: payType,
Remark: "",
Summary: "",
BankId: "",
}
drawJnl, _, err := api.LaKaLaApi.EwalletWithdrawD1(param)
if err != nil {
return err
}
withdrawal := &model.LakalaWithdrawal{
CreatedTime: time.Now(),
MercId: merchantNo,
DrawJnl: drawJnl,
ReqDate: "",
DrawAmt: drawAmt,
DrawFee: "",
BatchAutoSettle: "01",
DrawState: "DRAW.ACCEPTED",
DrawMode: "",
Memo: "",
}
dao.WrapAddIDCULDEntity(withdrawal, ctx.GetUserName())
if err = dao.CreateEntity(dao.GetDB(), withdrawal); err != nil {
return err
}
return nil
}
// EwalletWithdrawQuery 提现结果查询
func EwalletWithdrawQuery(ctx *jxcontext.Context, orgNo, merchantNo, drawJnl string) (*lakala.EwalletWithdrawQueryResp, error) {
resp, err := api.LaKaLaApi.EwalletWithdrawQuery(&lakala.EwalletWithdrawQueryReq{
OrgNo: orgNo,
MerchantNo: merchantNo,
DrawJnl: drawJnl,
})
if err != nil {
return nil, err
}
db := dao.GetDB()
withDraw, err := dao.GetEwalletWithDraw(db, merchantNo, drawJnl)
if err != nil {
return nil, err
}
withDraw.UpdatedAt = time.Now()
withDraw.LastOperator = ctx.GetUserName()
withDraw.CreatedTime = utils.Str2Time(resp.CreatedTime)
withDraw.CompleteTime = utils.Str2Time(resp.CompleteTime)
withDraw.ReqDate = resp.ReqDate
withDraw.DrawFee = resp.DrawFee
withDraw.DrawAmt = resp.DrawAmt
withDraw.BatchAutoSettle = resp.BatchAutoSettle
withDraw.DrawState = resp.DrawState
withDraw.DrawMode = resp.DrawMode
withDraw.Memo = resp.Memo
if _, err = dao.UpdateEntity(db, withDraw); err != nil {
return nil, err
}
return resp, nil
}
// SettleDrawPattern 提款模式设置
func SettleDrawPattern(param *lakala.SettleDrawPatternReq) error {
param.NotifyUrl = lakala.BillProdCallbackUrl
return api.LaKaLaApi.SettleDrawPattern(param)
}
// EwalletSettleQuery 提款模式查询
func EwalletSettleQuery(orgCode, merchantId string) (*lakala.EwalletSettleQueryResp, error) {
return api.LaKaLaApi.EwalletSettleQuery(orgCode, merchantId)
}
//#endregion
//#region 图片上传
func UploadImg(filePath, imgType, sourcechnl, isOcr string) (*lakala.UploadImgResp, error) {
return api.LaKaLaApi.FileUpload(filePath, imgType, sourcechnl, isOcr)
}
//#endregion
//#region 京西数据查询
// GetIncomingList 进件查询
func GetIncomingList(merchantNo string, storeId, pageSize, offset int) (*model.PagedInfo, error) {
return dao.GetIncoming(storeId, merchantNo, offset, pageSize)
}
// GetRecipientList 获取分账商户
func GetRecipientList(orgCode, receiverNo, receiverName string, offset, pageSize int) (pagedInfo *model.PagedInfo, err error) {
return dao.GetRecipientList(orgCode, receiverNo, receiverName, offset, pageSize)
}
// GetSeparateAmt 分账流水查询
func GetSeparateAmt(merchantNo, cmdType, status, separateNo, separateTimeStart, separateTimeEnd string, offset, pageSize int) (pagedInfo *model.PagedInfo, err error) {
var (
start time.Time
end time.Time
)
if separateTimeStart != "" {
start = utils.Str2Time(separateTimeStart)
}
if separateTimeEnd != "" {
end = utils.Str2Time(separateTimeEnd)
}
return dao.GetSeparateAmt(merchantNo, cmdType, status, separateNo, start, end, offset, pageSize)
}
// WithdrawalList 提现流水查询
func WithdrawalList(merchantNo, drawJnl, acctName, startTime, endTime string, pageSize, offset int) (pagedInfo *model.PagedInfo, err error) {
var (
start time.Time
end time.Time
)
if startTime != "" {
start = utils.Str2Time(startTime)
}
if endTime != "" {
end = utils.Str2Time(endTime)
}
return dao.WithdrawalList(merchantNo, drawJnl, acctName, start, end, pageSize, offset)
}
//#enregion

View File

@@ -0,0 +1,286 @@
package dao
import (
"git.rosy.net.cn/jx-callback/business/model"
"time"
)
// GetStoreInfoByMerchantID 门店进件/分账商户
func GetStoreInfoByMerchantID(db *DaoDB, merchantNo string, storeId int, applyId, OrderID string) (*model.LakalaIncoming, error) {
merchantObj := &model.LakalaIncoming{}
param := []interface{}{}
sql := ` SELECT * FROM lakala_incoming WHERE 1=1 `
if merchantNo != "" {
sql += ` AND merchant_no = ?`
param = append(param, merchantNo)
}
if storeId != model.NO {
sql += ` AND store_id = ?`
param = append(param, storeId)
}
if applyId != "" {
sql += ` AND apply_id = ?`
param = append(param, applyId)
}
if OrderID != "" {
sql += ` AND order_id = ?`
param = append(param, OrderID)
}
if err := GetRow(db, merchantObj, sql, param...); err != nil {
return nil, err
}
return merchantObj, nil
}
// GetRecipientByMerchantID 获取门店接受账户详细
func GetRecipientByMerchantID(db *DaoDB, receiverNo string) (*model.LakalaRecipient, error) {
receiverObj := &model.LakalaRecipient{}
sql := ` SELECT * FROM lakala_recipient WHERE receiver_no = ?`
if err := GetRow(db, receiverObj, sql, []interface{}{receiverNo}...); err != nil {
return nil, err
}
return receiverObj, nil
}
// GetSeparateRecords 分账记录
func GetSeparateRecords(db *DaoDB, merchantNo, separateNo, cmsType string) (*model.LakalaSeparateAmt, error) {
records := &model.LakalaSeparateAmt{}
sql := ` SELECT * FROM lakala_separate_amt WHERE 1=1 `
param := []interface{}{}
if merchantNo != "" {
sql += ` AND merchant_no = ?`
param = append(param, merchantNo)
}
switch cmsType {
case model.CmdTypeSeparate:
sql += ` AND separate_no1 = ?`
case model.CmdTypeCancel:
sql += ` AND separate_no2 = ?`
case model.CmdTypeFallBack:
sql += ` AND separate_no3 = ?`
default:
sql += ` AND separate_no1 = ?`
}
param = append(param, separateNo)
if err := GetRow(db, records, sql, param...); err != nil {
return nil, err
}
return records, nil
}
// GetEwalletWithDraw 提现记录
func GetEwalletWithDraw(db *DaoDB, mercId, drawJnl string) (*model.LakalaWithdrawal, error) {
receiverObj := &model.LakalaWithdrawal{}
parama := []interface{}{}
sql := ` SELECT * FROM lakala_withdrawal WHERE 1=1 `
if mercId != "" {
sql += ` AND merc_id = ?`
parama = append(parama, mercId)
}
if drawJnl != "" {
sql += ` AND draw_jnl = ? `
parama = append(parama, drawJnl)
}
if err := GetRow(db, receiverObj, sql, parama...); err != nil {
return nil, err
}
return receiverObj, nil
}
// GetIncoming 京西管理系统查询进件列表
func GetIncoming(storeID int, merchantNo string, offset, pageSize int) (pagedInfo *model.PagedInfo, err error) {
db := GetDB()
txDB, _ := Begin(db)
defer func() {
if r := recover(); r != nil {
Rollback(db, txDB)
panic(r)
}
}()
var incoming []*model.LakalaIncoming
var param = []interface{}{}
sql := ` SELECT SQL_CALC_FOUND_ROWS s.name,l.* FROM lakala_incoming l
JOIN store s ON l.store_id = s.id
WHERE 1=1 `
if storeID != 0 {
sql += ` AND s.store_id = ? `
param = append(param, storeID)
}
if merchantNo != "" {
sql += ` AND s.merchant_no = ?`
param = append(param, merchantNo)
}
sql += `
ORDER BY l.total_amt desc
LIMIT ? OFFSET ?
`
param = append(param, pageSize, offset)
if err = GetRowsTx(txDB, &incoming, sql, param...); err == nil {
pagedInfo = &model.PagedInfo{
TotalCount: GetLastTotalRowCount2(db, txDB),
Data: incoming,
}
}
return pagedInfo, nil
}
// GetRecipientList 京西管理系统查询分账账户列表
func GetRecipientList(orgCode, receiverNo, receiverName string, offset, pageSize int) (pagedInfo *model.PagedInfo, err error) {
db := GetDB()
txDB, _ := Begin(db)
defer func() {
if r := recover(); r != nil {
Rollback(db, txDB)
panic(r)
}
}()
var recipient []*model.LakalaRecipient
var param = []interface{}{}
sql := ` SELECT SQL_CALC_FOUND_ROWS r.* FROM lakala_recipient r WHERE 1=1 `
if orgCode != "" {
sql += ` AND r.org_code = ? `
param = append(param, orgCode)
}
if receiverNo != "" {
sql += ` AND r.receiver_no = ?`
param = append(param, receiverNo)
}
if receiverName != "" {
sql += ` AND r.receiver_name like ?`
param = append(param, "%"+receiverNo+"%")
}
sql += `
ORDER BY r.id desc
LIMIT ? OFFSET ?
`
param = append(param, pageSize, offset)
if err = GetRowsTx(txDB, &recipient, sql, param...); err == nil {
pagedInfo = &model.PagedInfo{
TotalCount: GetLastTotalRowCount2(db, txDB),
Data: recipient,
}
}
return pagedInfo, nil
}
// GetSeparateAmt 交易流水查询
func GetSeparateAmt(merchantNo, cmdType, status, separateNo string, separateTimeStart, separateTimeEnd time.Time, offset, pageSize int) (pagedInfo *model.PagedInfo, err error) {
db := GetDB()
txDB, _ := Begin(db)
defer func() {
if r := recover(); r != nil {
Rollback(db, txDB)
panic(r)
}
}()
var recipient []*model.LakalaSeparateAmt
var param = []interface{}{}
sql := ` SELECT SQL_CALC_FOUND_ROWS r.* FROM Lakala_separate_amt r WHERE 1=1 `
if merchantNo != "" {
sql += ` AND r.merchant_no = ? `
param = append(param, merchantNo)
}
if cmdType != "" {
sql += ` AND r.cmd_type = ?`
param = append(param, cmdType)
}
if status != "" {
sql += ` AND r.status = ?`
param = append(param, status)
}
if separateNo != "" {
sql += ` AND r.separate_no = ?`
param = append(param, separateNo)
}
if !separateTimeStart.IsZero() {
sql += ` AND r.log_date >= ?`
param = append(param, separateTimeStart)
}
if !separateTimeEnd.IsZero() {
sql += ` AND r.log_date <= ?`
param = append(param, separateTimeEnd)
}
sql += `
ORDER BY r.id desc
LIMIT ? OFFSET ?
`
param = append(param, pageSize, offset)
if err = GetRowsTx(txDB, &recipient, sql, param...); err == nil {
pagedInfo = &model.PagedInfo{
TotalCount: GetLastTotalRowCount2(db, txDB),
Data: recipient,
}
}
return pagedInfo, nil
}
// WithdrawalList 提现记录
func WithdrawalList(merchantNo, drawJnl, acctName string, startTime, endTime time.Time, pageSize, offset int) (pagedInfo *model.PagedInfo, err error) {
db := GetDB()
txDB, _ := Begin(db)
defer func() {
if r := recover(); r != nil {
Rollback(db, txDB)
panic(r)
}
}()
var recipient []*model.LakalaWithdrawal
var param = []interface{}{}
sql := ` SELECT SQL_CALC_FOUND_ROWS r.* FROM lakala_withdrawal r WHERE 1=1 `
if merchantNo != "" {
sql += ` AND r.merchant_no = ? `
param = append(param, merchantNo)
}
if drawJnl != "" {
sql += ` AND r.draw_jnl = ?`
param = append(param, drawJnl)
}
if acctName != "" {
sql += ` AND r.acct_name like ?`
param = append(param, "%"+acctName+"%")
}
if !startTime.IsZero() {
sql += ` AND r.created_time >= ?`
param = append(param, startTime)
}
if !endTime.IsZero() {
sql += ` AND r.created_time <= ?`
param = append(param, endTime)
}
sql += `
ORDER BY r.id desc
LIMIT ? OFFSET ?
`
param = append(param, pageSize, offset)
if err = GetRowsTx(txDB, &recipient, sql, param...); err == nil {
pagedInfo = &model.PagedInfo{
TotalCount: GetLastTotalRowCount2(db, txDB),
Data: recipient,
}
}
return pagedInfo, nil
}

169
business/model/lakala.go Normal file
View File

@@ -0,0 +1,169 @@
package model
import "time"
const (
ThingTypeSeparate = 1 // 商户分账
ThingTypeReceive = 2 // 分账接收方
OperateTypeCreate = "create" // 创建
OperateTypeUpdate = "update" // 修改
OperateTypeBind = "bind" // 绑定
OperateTypeUnBind = "unbind" // 解绑
OperateStatusReview = "review" // 审核中
OperateStatusSuccess = "success" // 审核通过
OperateStatusFail = "fail" // 审核失败
ReceiverStatusValid = "VALID" // 有效
ReceiverStatusInValid = "INVALID" // 无效
)
// 分账状态说明
const (
SeparateAmtAccepted = "ACCEPTED" // 已受理
SeparateAmtProcessing = "PROCESSING" // 处理中
SeparateAmtFail = "FAIL" // 失败
SeparateAmtSuccess = "SUCCESS" // 成功
SeparateAmtCanceling = "CANCELING" // 撤销中
SeparateAmtCanceled = "CANCELED" // 撤销成功
SeparateAmtCancelFail = "CANCEL_FAIL" // 撤销失败
SeparateAmtFallBacking = "FALLBACKING" // 回退中
SeparateAmtFallBackEnd = "FALLBACK_END" // 回退失败
)
// 分账指令类型
const (
CmdTypeSeparate = "SEPARATE" // 分账
CmdTypeCancel = "CANCEL" // 分账撤销
CmdTypeFallBack = "FALLBACK" // 分账退回
)
// LakalaIncoming 进件账户状态,分账状态
type LakalaIncoming struct {
ModelIDCUL
StoreId int `orm:"column(store_id);size(16)" json:"storeId"` // 京西门店ID
MerchantNo string `orm:"column(merchant_no);size(20)" json:"merchantNo"` // 拉卡拉进件商户号
TermNo string `orm:"column(term_no);size(256)" json:"termNo"` // 终端号 M String(32) 拉卡拉分配的业务终端号
MerchantStatus string `orm:"column(merchant_status);size(80)" json:"merchantStatus"` // 拉卡拉进件状态
FeeId string `orm:"column(fee_id);size(80)" json:"feeId"` // 拉卡拉费率变更ID
FeeStatus string `orm:"column(fee_status);size(80)" json:"feelStatus"` // 拉卡拉费率变更状态
SettleId string `orm:"column(settle_id);size(80)" json:"settleId"` // 结算变更id
SettleStatus string `orm:"column(settle_status);size(80)" json:"settleStatus"` // 结算变更状态
BasicId string `orm:"column(basic_id);size(80)" json:"basicId"` // 基本信息变更ID
BasicStatus string `orm:"column(basic_status);size(80)" json:"basicStatus"` // 基本信息变更状态
LicenseId string `orm:"column(license_id);size(80)" json:"licenseId"` // 营业执照变更ID
LicenseStatus string `orm:"column(license_status);size(80)" json:"licenseStatus"` // 营业执照变更状态
// 分账
OrderID string `orm:"column(order_id);size(32)" json:"orderId"` // 当前事件ID
ApplyID string `orm:"column(apply_id);size(32)" json:"applyId"` // 申请id
ThingType int `orm:"column(thong_type);size(2)" json:"thingType"` // 事件类型[1-分账门店/2-分账接收方]
Operate string `orm:"column(operate);size(2)" json:"operate"` // 操作类型[创建/修改/绑定/解绑]
OperateStatus string `orm:"column(operate_status);size(2)" json:"operateStatus"` // 操作所处状态
TotalAmt string `orm:"column(total_amt);size(10)" json:"totalAmt"` // 总分账金额
CanAmt string `orm:"column(can_amt);size(10)" json:"canAmt"` // 可分账金额
BindAccount string `orm:"column(bind_account);type(text)" json:"bindAccount"` // 绑定的分账账户map["receiverNo"]"1"
Remark string `orm:"column(remark);size(512)" json:"remark"` // 备注说明
}
type BindAccountObj struct {
ApplyId string `json:"applyId"` // 申请编号
Status string `json:"status"` // 审核状态
Remark string `json:"remark"` // 备注说明
}
func (o *LakalaIncoming) TableUnique() [][]string {
return [][]string{
[]string{"StoreID"},
[]string{"MerchantNo"},
}
}
func (o *LakalaIncoming) TableIndex() [][]string {
return [][]string{
[]string{"ApplyID"},
}
}
// LakalaRecipient 拉卡拉接收分账账户
type LakalaRecipient struct {
ModelIDCUL
OrgCode string `orm:"column(org_code);size(20)" json:"orgCode"` // 申请机构代码(回传)
OrgID string `orm:"column(org_id);size(20)" json:"orgId"` // 接收方所属机构
ReceiverNo string `orm:"column(receiver_no);size(20)" json:"receiverNo"` // 接收方编号
ReceiverName string `orm:"column(receiver_name);size(20)" json:"receiverName"` // 接收方名称
Status string `orm:"column(status);size(16)" json:"status"` // 分账账户状态 有效VALID 无效INVALID
Remark string `orm:"column(remark);size(512)" json:"remark"` // 备注说明
}
func (o *LakalaRecipient) TableUnique() [][]string {
return [][]string{
[]string{"ReceiverNo"},
}
}
func (o *LakalaRecipient) TableIndex() [][]string {
return [][]string{
[]string{"CreatedAt"},
}
}
// LakalaSeparateAmt 分账记录
type LakalaSeparateAmt struct {
ModelIDCUL
MerchantNo string `orm:"column(merchant_no);size(20)" json:"merchantNo"` // 分账发起商户
CmdType string `orm:"column(cmd_type);size(32)" json:"cmdType"` // SEPARATE分账 CANCEL分账撤销FALLBACK分账回退
SeparateNo string `orm:"column(separate_no);size(32)" json:"separateNo"` // 分账系统生成唯一流水
Status string `orm:"column(status);size(32)" json:"status1"` // 分账状态
//SeparateNo2 string `orm:"column(separate_no2);size(32)" json:"separateNo2"` // 分账撤销系统生成唯一流水
//Status2 string `orm:"column(status2);size(32)" json:"status2"` // 分账撤销状态
//SeparateNo3 string `orm:"column(separate_no3);size(32)" json:"separateNo3"` // 分账回退系统生成唯一流水
//Status3 string `orm:"column(status3);size(32)" json:"status3"` // 分账回退状态
OutSeparateNo string `orm:"column(out_separate_no);size(32)" json:"outSeparateNo"` // 商户分账指令流水号
LogDate time.Time `orm:"column(log_date);type(datetime)" json:"logDate"` // 交易日期
CalType string `orm:"column(cal_type);size(2)" json:"calType"` // 分账计算类型
FinishDate string `orm:"column(finish_date);size(20)" json:"finishDate"` // 完成日期 yyyyMMdd
TotalAmt string `orm:"column(total_amt);size(15)" json:"totalAmt"` // 发生总金额
ActualSeparateAmt string `orm:"column(actual_separate_amt);size(15)" json:"actualSeparateAmt"` // 实分金额
TotalFeeAmt string `orm:"column(total_fee_amt);size(15)" json:"totalFeeAmt"` // 手续费金额
FinalStatus string `orm:"column(final_status);size(32)" json:"finalStatus"` // 处理状态
DetailData string `orm:"column(detail_data);type(text)" json:"detailData"` // 细节数据
Remark string `orm:"column(remark);size(256)" json:"remark"` // 备注说明记录订单流程变化
}
func (o *LakalaSeparateAmt) TableUnique() [][]string {
return [][]string{
[]string{"MerchantNo"},
}
}
func (o *LakalaSeparateAmt) TableIndex() [][]string {
return [][]string{
[]string{"CreatedAt"},
}
}
// LakalaWithdrawal 拉卡拉提现记录
type LakalaWithdrawal struct {
ModelIDCUL
CreatedTime time.Time `orm:"column(created_time);type(datetime)" json:"createdTime"` // 创建时间
CompleteTime time.Time `orm:"column(complete_time);type(datetime)" json:"completeTime"` // 完成时间
MercId string `orm:"column(merc_id);size(32)" json:"mercId"` // 商户号
DrawJnl string `orm:"column(draw_jnl);size(32)" json:"drawJnl"` // 提款流水号
ReqDate string `orm:"column(req_date);size(32)" json:"reqDate"` // 请求日期
AcctName string `orm:"column(acct_name);size(32)" json:"acctName"` // 结算账户名
AcctNo string `orm:"column(acct_no);size(32)" json:"acctNo"` // 结算账户号
DrawAmt string `orm:"column(draw_amt);size(32)" json:"drawAmt"` // 提款金额(元):含手续费
DrawFee string `orm:"column(draw_fee);size(32)" json:"drawFee"` // 手续费(元)
BatchAutoSettle string `orm:"column(batch_auto_settle);size(2)" json:"batchAutoSettle"` // 结算模式01主动提款 02余额自动结算 03 交易自动结算)
DrawState string `orm:"column(draw_state);size(16)" json:"drawState"` // 提款状态 DRAW.ACCEPTED 提款已受理 DRAW.FREEZE 提款冻结DRAW.PROCESSING 提款处理中DRAW.SUCCESS 提款成功DRAW.FAILED 提款失败
DrawMode string `orm:"column(draw_mode);size(4)" json:"drawMode"` // 提款模式(D0/D1)
Memo string `orm:"column(memo);size(256)" json:"memo"` // 结果信息
}
func (o *LakalaWithdrawal) TableUnique() [][]string {
return [][]string{
[]string{"MercId"},
[]string{"DrawJnl"},
}
}
func (o *LakalaWithdrawal) TableIndex() [][]string {
return [][]string{
[]string{"CreatedTime"},
}
}

View File

@@ -18,10 +18,11 @@ const (
PayTypeTL = 2 // 通联宝支付
PayTypeTicTok = 3 // 抖音支付
PayTypeKuaiShou = 4 // 快手支付
PayTypeLaKaLa = 5 // 拉卡拉
PayTypeTL_DiscountCard = 3 // 通联宝支付(会员折扣卡)
PayTypeTL_StoreAcctPay = 4 // 通联宝支付(门店账户充值)
PayTypeTL_BrandBillCharge = 5 //品牌账户充值pc扫码支付
PayTypeTL_BrandBillCharge = 5 // 品牌账户充值pc扫码支付
PayStatusNo = 0
PayStatusYes = 1
@@ -138,7 +139,7 @@ type GoodsOrder struct {
ExpectedDeliveredTime time.Time `orm:"type(datetime)" json:"expectedDeliveredTime"` // 预期送达时间
CancelApplyReason string `orm:"size(255)" json:"-"` // ""表示没有申请不为null表示用户正在取消申请
DeliveryType string `orm:"size(32)" json:"deliveryType"` // 订单配送方式,缺省是平台配送
CreateDeliveryType int `orm:"default(0)" json:"createDeliveryType"` //默认0系统发单1为门店发单
CreateDeliveryType int `orm:"default(0)" json:"createDeliveryType"` // 默认0系统发单1为门店发单
VendorWaybillID string `orm:"column(vendor_waybill_id);size(48)" json:"vendorWaybillID"` // 运单id
WaybillVendorID int `orm:"column(waybill_vendor_id)" json:"waybillVendorID"` // 表示当前承运商,-1表示还没有安排
AdjustCount int8 `json:"adjustCount"` // 调整单(次数)

View File

@@ -0,0 +1,254 @@
package localjx
import (
"fmt"
"git.rosy.net.cn/baseapi/platformapi/lakala"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
"git.rosy.net.cn/jx-callback/business/model"
"git.rosy.net.cn/jx-callback/business/model/dao"
"git.rosy.net.cn/jx-callback/business/partner"
"git.rosy.net.cn/jx-callback/globals/api"
"strings"
"time"
)
// RefundBarCodeScannerOrderByLaKaLa 拉卡拉扫码枪退款
func RefundBarCodeScannerOrderByLaKaLa(ctx *jxcontext.Context, vendorOrderId string, skuIds map[int]int, reason string) (err error) {
db := dao.GetDB()
txDB, _ := dao.Begin(db)
defer func() {
if r := recover(); r != nil || err != nil {
dao.Rollback(db, txDB)
if r != nil {
panic(r)
}
}
}()
goodsOrder, err := partner.CurOrderManager.LoadOrder(vendorOrderId, model.VendorIDJX)
if err != nil {
dao.Rollback(db, txDB)
return err
}
// 检查订单售后
refundType, refundMoney, err := checkJxAfsOrder(db, goodsOrder, vendorOrderId, skuIds)
if err != nil {
dao.Rollback(db, txDB)
return err
}
// 本地添加售后数据
afsOrder, orderSkuFinancial, afsOrderSkuFinancial, err := addRefundSku(ctx, goodsOrder, skuIds, reason, refundType)
if err != nil {
dao.Rollback(db, txDB)
return err
}
// 通知退款,等待回传
incoming, err := dao.GetStoreInfoByMerchantID(db, "", goodsOrder.JxStoreID, "", "")
if err != nil {
return err
}
param := &lakala.RefundOrderReq{
MerchantNo: incoming.MerchantNo,
TermNo: incoming.TermNo,
OutTradeNo: afsOrder.AfsOrderID,
RefundAmount: utils.Int2Str(refundMoney),
OriginBizType: "3",
OriginTradeDate: goodsOrder.OrderCreatedAt.Format("20060102"),
OriginLogNo: "",
OriginTradeNo: "",
OriginCardNo: "",
LocationInfo: nil,
RefundType: "",
}
_, err = api.LaKaLaApi.RefundOrder(param)
if err != nil {
return err
}
if err = dao.CreateEntity(db, afsOrder); err != nil {
dao.Rollback(db, txDB)
return err
}
if err = dao.CreateMultiEntities(db, orderSkuFinancial); err != nil {
dao.Rollback(db, txDB)
return err
}
if err = dao.CreateMultiEntities(db, afsOrderSkuFinancial); err != nil {
dao.Rollback(db, txDB)
return err
}
goodsOrder.TotalShopMoney -= int64(refundMoney)
dao.UpdateEntity(db, goodsOrder, "TotalShopMoney")
dao.Commit(db, txDB)
return nil
}
// QueryBarCodeRefundStatus 退款订单状态查询
func QueryBarCodeRefundStatus(afsOrderID string) (resp []*lakala.RefundOrderQueryResp, err error) {
db := dao.GetDB()
txDB, _ := dao.Begin(db)
defer func() {
if r := recover(); r != nil || err != nil {
dao.Rollback(db, txDB)
if r != nil {
panic(r)
}
}
}()
afsOrder, err := partner.CurOrderManager.LoadAfsOrder(afsOrderID, model.VendorIDJX)
if err != nil {
return nil, err
}
goodsOrder, err := partner.CurOrderManager.LoadOrder(afsOrder.VendorOrderID, model.VendorIDJX)
if err != nil {
dao.Rollback(db, txDB)
return nil, err
}
// 通知退款,等待回传
incoming, err := dao.GetStoreInfoByMerchantID(db, "", goodsOrder.JxStoreID, "", "")
if err != nil {
return nil, err
}
param := &lakala.RefundOrderQueryReq{
MerchantNo: incoming.MerchantNo,
TermNo: incoming.TermNo,
OutTradeNo: lakala.GetOrderNumber(8),
OriginTradeDate: afsOrder.AfsCreatedAt.Format("20060102"),
OriginBizType: "3",
OriginTradeNo: "",
OriginTradeRefNo: "",
OriginOutTradeNo: afsOrderID,
}
result, err := api.LaKaLaApi.RefundOrderQuery(param)
if err != nil {
return nil, err
}
for _, v := range result {
if v.OutTradeNo == afsOrderID && v.TradeState == "SUCCESS" {
afsOrder.Status = model.AfsOrderStatusFinished
afsOrder.VendorStatus = v.TradeState
afsOrder.AfsFinishedAt = time.Now()
dao.UpdateEntity(db, afsOrder, "Status", "VendorStatus", "AfsFinishedAt")
}
}
return result, err
}
// BarCodeScannerPayByLaKaLa 拉卡拉扫码枪扫码
func BarCodeScannerPayByLaKaLa(ctx *jxcontext.Context, vendorOrderId, userPaymentLabel, ip string) (string, error) {
db := dao.GetDB()
goodsOrder, err := dao.GetSimpleOrder(db, vendorOrderId)
if err != nil {
return "", err
}
if goodsOrder.VendorID != model.VendorIDJX {
return "", fmt.Errorf("此订单不是京西订单,无法使用该功能")
}
merchantObj, err := dao.GetStoreInfoByMerchantID(db, "", goodsOrder.JxStoreID, "", "")
if err != nil {
return "", err
}
parma := &lakala.PayMicroPayReq{
MerchantNo: merchantObj.MerchantNo,
TermNo: merchantObj.TermNo,
OutTradeNo: goodsOrder.VendorOrderID,
AuthCode: userPaymentLabel,
TotalAmount: utils.Int64ToStr(goodsOrder.ActualPayPrice),
LocationInfo: lakala.LocationInfoObj{
RequestIp: ip,
},
NotifyUrl: lakala.PayStatusCallback,
SettleType: "1",
Subject: fmt.Sprintf("感谢您在本店%s消费,欢迎下次再来", goodsOrder.StoreName),
}
code, msg, payOrderId, err := api.LaKaLaApi.ScannerPayMicroPay(parma)
if code == lakala.PaySuccess {
goodsOrder.Status = model.OrderStatusFinished
goodsOrder.VendorStatus = code
goodsOrder.OrderFinishedAt = time.Now()
dao.UpdateEntity(db, goodsOrder, "Status", "VendorStatus", "OrderFinishedAt")
return "支付成功", nil
}
vendorPayType := ""
if strings.Contains(userPaymentLabel, "101112131415") {
vendorPayType = lakala.Wechat
} else {
vendorPayType = lakala.Alipay
}
payInfo := &model.OrderPay{
PayOrderID: payOrderId,
PayType: model.PayTypeLaKaLa,
VendorPayType: vendorPayType,
TransactionID: userPaymentLabel,
VendorOrderID: goodsOrder.VendorOrderID,
VendorID: goodsOrder.VendorID,
Status: 0,
PayCreatedAt: time.Now(),
PrepayID: userPaymentLabel,
CodeURL: "",
TotalFee: int(goodsOrder.ActualPayPrice),
}
dao.WrapAddIDCULDEntity(payInfo, ctx.GetUserName())
dao.CreateEntity(db, payInfo)
return msg, err
}
// LaKaLaBarCodeScannerStatus 刷新当前订单的支付状态
func LaKaLaBarCodeScannerStatus(vendorOrderId string) (vendorStatus string, err error) {
db := dao.GetDB()
goodsOrder, err := dao.GetSimpleOrder(db, vendorOrderId)
if err != nil {
return "", err
}
if goodsOrder.VendorID != model.VendorIDJX {
return "", fmt.Errorf("此订单不是京西订单,无法使用该功能")
}
merchantObj, err := dao.GetStoreInfoByMerchantID(db, "", goodsOrder.JxStoreID, "", "")
if err != nil {
return "", err
}
param := &lakala.PayStatusQueryReq{
MerchantNo: merchantObj.MerchantNo,
TermNo: merchantObj.TermNo,
OutTradeNo: goodsOrder.VendorOrderID,
TradeNo: "",
}
result, err := api.LaKaLaApi.PayStatusQuery(param)
if err != nil {
return "", err
}
switch result.TradeState {
case lakala.PayStatusINIT, lakala.PayStatusCREATE, lakala.PayStatusDEAL:
goodsOrder.Status = model.OrderStatusWaitPay
goodsOrder.VendorStatus = lakala.PayStatusINIT
case lakala.PayStatusSUCCESS, lakala.PayStatusPARTREFUND:
goodsOrder.Status = model.OrderStatusFinished
goodsOrder.VendorStatus = lakala.PayStatusSUCCESS
goodsOrder.OrderFinishedAt = time.Now()
case lakala.PayStatusFAIL, lakala.PayStatusCLOSE, lakala.PayStatusREFUND:
goodsOrder.Status = model.OrderStatusCanceled
goodsOrder.VendorStatus = lakala.PayStatusFAIL
goodsOrder.OrderFinishedAt = time.Now()
case lakala.PayStatusUNKNOWN:
}
dao.UpdateEntity(db, goodsOrder, "Status", "VendorStatus", "OrderFinishedAt")
partner.CurOrderManager.OnOrderMsg(goodsOrder, result.TradeState, fmt.Sprintf("扫码枪扫码刷新结果:[code:%s,说明:%s,异常原因:%s],本地状态[%d]", result.TradeState, result.TradeStateDesc, "", goodsOrder.Status))
return result.TradeStateDesc, err
}

View File

@@ -0,0 +1,214 @@
package localjx
import (
"encoding/json"
"fmt"
"git.rosy.net.cn/baseapi/platformapi/lakala"
"git.rosy.net.cn/jx-callback/business/partner"
"strings"
"time"
"git.rosy.net.cn/jx-callback/globals"
"git.rosy.net.cn/baseapi/platformapi/tonglianpayapi"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/auth2/authprovider/weixin"
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
"git.rosy.net.cn/jx-callback/business/model"
"git.rosy.net.cn/jx-callback/business/model/dao"
"git.rosy.net.cn/jx-callback/globals/api"
"github.com/astaxie/beego/client/orm"
)
func pay4OrderByLaKaLa(ctx *jxcontext.Context, order *model.GoodsOrder, payType int, vendorPayType, subAppID, code, source, ip string) (orderPay *model.OrderPay, err error) {
merchantObj, err := dao.GetStoreInfoByMerchantID(dao.GetDB(), "", order.JxStoreID, "", "")
if err != nil {
return nil, err
}
param := &lakala.AggregatePayReq{
MerchantNo: merchantObj.MerchantNo,
TermNo: merchantObj.TermNo,
OutTradeNo: order.VendorOrderID,
TotalAmount: utils.Int64ToStr(order.ActualPayPrice),
LocationInfo: lakala.LocationInfoObj{
RequestIp: ip,
},
NotifyUrl: lakala.PayStatusCallback,
Subject: fmt.Sprintf("感谢您在本店%s消费,欢迎下次再来", order.StoreName),
SettleType: "1",
AccBusiFields: nil,
}
if vendorPayType == tonglianpayapi.PayTypeWxXcx || vendorPayType == "JSAPI" || vendorPayType == tonglianpayapi.PayTypeWxCode {
accBusiFeilds := &lakala.AccBusiFieldsByWeChat{
TimeoutExpress: "15",
SubAppid: subAppID,
}
if source == "pc" || vendorPayType == "JSAPI" {
accBusiFeilds.DeviceInfo = "WEB"
}
switch vendorPayType {
case "JSAPI":
param.TransType = "51"
case tonglianpayapi.PayTypeWxXcx:
param.TransType = "71"
}
authInfo, err := ctx.GetV2AuthInfo()
// 微信小程序支付
if err == nil && authInfo.GetAuthType() == weixin.AuthTypeMini && authInfo.GetAuthTypeID() == subAppID {
accBusiFeilds.UserId = authInfo.GetAuthID()
}
if code != "" {
appAuth := strings.Split(code, "_")
sessionInfo, err := weixin.GetAPI(appAuth[0]).SNSCode2Session(appAuth[1])
if err != nil {
return nil, err
}
accBusiFeilds.UserId = sessionInfo.OpenID
}
param.AccBusiFields = accBusiFeilds
param.AccountType = lakala.Wechat
}
// 支付宝暂时不关注小程序
//if vendorPayType == tonglianpayapi.PayTypeZfbJS || vendorPayType == tonglianpayapi.PayTypeZfbApp {
// accBusiFeilds := &lakala.AccBusiFieldsByAliPay{
// TimeoutExpress: "15",
// UserId: openId,
// }
// param.AccBusiFields = accBusiFeilds
//}
result, err := api.LaKaLaApi.AggregatePay(param)
if err == nil {
orderPay = &model.OrderPay{
PayOrderID: param.OutTradeNo,
PayType: payType,
VendorPayType: vendorPayType,
TransactionID: result.LogNo,
VendorOrderID: order.VendorOrderID,
VendorID: order.VendorID,
Status: 0,
PayCreatedAt: time.Now(),
PrepayID: result.TradeNo,
CodeURL: "",
TotalFee: int(order.ActualPayPrice),
}
if result.AccRespFields != nil {
fields, _ := json.Marshal(result.AccRespFields)
orderPay.CodeURL = utils.LimitUTF8StringLen(string(fields), 3200)
}
}
return orderPay, err
}
func OnLaKaLaPayCallback(call *lakala.PayStatusCallBack) (err error) {
switch call.TradeStatus {
case lakala.PayStatusSUCCESS, lakala.PayStatusFAIL: // 支付成功 FAIL-交易失败
err = onLaKaLaPayFinished(call)
case lakala.PayStatusCLOSE, lakala.PayStatusREVOKED, lakala.PayStatusREFUND: // CLOSE-订单关闭 REVOKED-订单撤销
err = onLaKaLaOrderCancel(call)
case lakala.PayStatusPARTREFUND: // PART_REFUND-部分退款 REFUND-全部退款
err = onLaKaLaPayRefund(call)
default:
//INIT-初始化 CREATE-下单成功 DEAL-交易处理中 UNKNOWN-未知状态
return nil
}
return err
}
// onLaKaLaPayFinished 订单支付成功或失败
func onLaKaLaPayFinished(call *lakala.PayStatusCallBack) (err error) {
orderPay := &model.OrderPay{
PayOrderID: call.OutTradeNo,
}
orderPay.DeletedAt = utils.DefaultTimeValue
db := dao.GetDB()
if err = dao.GetEntity(db, orderPay, "PayOrderID", "DeletedAt"); err == nil {
if orderPay.Status != 0 {
return err
}
loc, _ := time.LoadLocation("Local")
t1, _ := time.ParseInLocation("20060102150405", call.TradeTime, loc)
orderPay.PayFinishedAt = utils.Time2Pointer(t1)
orderPay.OriginalData = utils.Format4Output(call, true)
if call.TradeStatus == lakala.PayStatusSUCCESS {
orderPay.Status = model.PayStatusYes
} else {
orderPay.Status = model.PayStatusFailed
}
dao.UpdateEntity(db, orderPay)
if call.TradeStatus == lakala.PayStatusSUCCESS {
err = OnPayFinished(orderPay)
}
} else {
globals.SugarLogger.Debugf("onTLpayFinished msg:%s, err:%v", utils.Format4Output(call, true), err)
}
return err
}
// onLaKaLaOrderCancel 订单取消或撤单
func onLaKaLaOrderCancel(call *lakala.PayStatusCallBack) (err error) {
orderPay := &model.OrderPay{
PayOrderID: call.OutTradeNo,
}
orderPay.DeletedAt = utils.DefaultTimeValue
db := dao.GetDB()
if err = dao.GetEntity(db, orderPay, "PayOrderID", "DeletedAt"); err == nil {
orderPay.Status = model.RefundStatusFailed
orderPay.PayFinishedAt = utils.Time2Pointer(time.Now())
dao.UpdateEntity(db, orderPay, "Status", "PayFinishedAt")
order, _ := partner.CurOrderManager.LoadOrder(orderPay.VendorOrderID, orderPay.VendorID)
order.Status = model.OrderStatusCanceled
order.VendorStatus = call.TradeStatus
order.OrderFinishedAt = time.Now()
dao.UpdateEntity(db, order, "Status", "VendorStatus", "OrderFinishedAt")
}
return err
}
func onLaKaLaPayRefund(call *lakala.PayStatusCallBack) (err error) {
orderPayRefund := &model.OrderPayRefund{
RefundID: call.OutTradeNo,
}
db := dao.GetDB()
if err = dao.GetEntity(db, orderPayRefund, "RefundID"); err != nil && err == orm.ErrNoRows {
orderPayRefund = &model.OrderPayRefund{
RefundID: call.OutTradeNo,
VendorRefundID: call.AccTradeNo,
VendorOrderID: call.OutTradeNo,
VendorID: model.VendorIDJX,
TransactionID: call.LogNo,
Status: model.RefundStatusYes,
RefundCreatedAt: time.Now(),
RefundFinishedAt: utils.Time2Pointer(time.Now()),
RefundFee: utils.Str2Int(call.PayerAmount),
OriginalData: "",
}
dao.WrapAddIDCULDEntity(orderPayRefund, "system")
dao.CreateEntity(db, orderPayRefund)
}
order, _ := partner.CurOrderManager.LoadOrder(call.OutTradeNo, model.VendorIDJX)
afsOrder, _ := partner.CurOrderManager.LoadAfsOrder(call.OutTradeNo, model.VendorIDJX)
if call.TradeStatus == lakala.PayStatusREFUND {
order.Status = model.OrderStatusCanceled
orderPayRefund.Status = model.PayStatusRefund
}
order.OrderFinishedAt = time.Now()
order.VendorStatus = call.TradeStatus
afsOrder.Status = model.AfsOrderStatusFinished
afsOrder.AfsFinishedAt = time.Now()
afsOrder.VendorStatus = call.TradeStatus
orderPayRefund.RefundFinishedAt = utils.Time2Pointer(time.Now())
dao.UpdateEntity(db, order, "Status", "VendorStatus", "OrderFinishedAt")
dao.UpdateEntity(db, afsOrder, "Status", "VendorStatus", "AfsFinishedAt")
dao.UpdateEntity(db, orderPayRefund, "Status", "RefundFinishedAt")
return err
}

View File

@@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"math"
"net"
"regexp"
"strings"
"time"
@@ -328,6 +329,12 @@ func Pay4Order(ctx *jxcontext.Context, orderID int64, payType int, vendorPayType
dao.WrapAddIDCULDEntity(orderPay, ctx.GetUserName())
err = dao.CreateEntity(dao.GetDB(), orderPay)
}
case model.PayTypeLaKaLa: //
ip, _, _ := net.SplitHostPort(ctx.GetRequest().RemoteAddr)
if orderPay, err = pay4OrderByLaKaLa(ctx, order, payType, vendorPayType, subAppID, "", "", ip); err == nil && orderPay != nil {
dao.WrapAddIDCULDEntity(orderPay, ctx.GetUserName())
err = dao.CreateEntity(dao.GetDB(), orderPay)
}
case model.PayTypeTicTok:
if orderPay, err = pay4OrderByTT(ctx, order, vendorPayType, subAppID); err == nil && orderPay != nil {
dao.WrapAddIDCULDEntity(orderPay, ctx.GetUserName())
@@ -863,7 +870,7 @@ func generateOrder(ctx *jxcontext.Context, jxOrder *JxOrderInfo, addressID int64
if jxOrder.OrderType != model.OrderTypeMatter || (jxOrder.OrderType == model.OrderTypeMatter && fromStoreID == -1) {
outJxOrder.Skus = append(outJxOrder.Skus, jxSku)
outJxOrder.OrderPrice += int64(jxSku.Count) * jxSku.SalePrice
} else { //以下else为物料订单袋子金额和数量处理
} else { //以下else为物料订单袋子金额和数量处理
if !result.Flag { //只要flag是false就按原价申请是true再按订单量
outJxOrder.Skus = append(outJxOrder.Skus, jxSku)
outJxOrder.OrderPrice += int64(jxSku.Count) * jxSku.SalePrice

View File

@@ -280,6 +280,8 @@ func RefundBarCodeScannerOrder(ctx *jxcontext.Context, vendorOrderId string, sku
dao.Rollback(db, txDB)
return err
}
goodsOrder.TotalShopMoney -= int64(refundMoney)
dao.UpdateEntity(db, goodsOrder, "TotalShopMoney")
dao.Commit(db, txDB)
default:
return fmt.Errorf(errMsg)