1
This commit is contained in:
422
business/partner/purchase/jx/localjx/tonglianpay_gun.go
Normal file
422
business/partner/purchase/jx/localjx/tonglianpay_gun.go
Normal file
@@ -0,0 +1,422 @@
|
||||
package localjx
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"git.rosy.net.cn/baseapi/platformapi/tonglianpayapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"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"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
TransactionStatus = map[string]string{
|
||||
"0000": "交易成功",
|
||||
"1001": "交易不存在",
|
||||
"2008": "交易处理中,请查询交易,如果是实时交易(例如刷卡支付,交易撤销,退货),建议每隔一段时间(10秒)查询交易",
|
||||
"2000": "交易处理中,请查询交易,如果是实时交易(例如刷卡支付,交易撤销,退货),建议每隔一段时间(10秒)查询交易",
|
||||
"3888": "流水号重复",
|
||||
"3099": "渠道商户错误",
|
||||
"3014": "交易金额小于应收手续费",
|
||||
"3031": "校验实名信息失败",
|
||||
"3088": "交易未支付",
|
||||
"3089": "撤销异常,如已影响资金24小时内会做差错退款处理",
|
||||
"3050": "交易已被撤销",
|
||||
"3999": "1",
|
||||
"3889": "1",
|
||||
"3045": "1",
|
||||
}
|
||||
)
|
||||
|
||||
// BarCodeScannerPay 面对面扫码支付(扫码枪)
|
||||
func BarCodeScannerPay(vendorOrderId string, userPaymentLabel string) (payCode 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("此订单不是京西订单,无法使用该功能")
|
||||
}
|
||||
storeDetail, err := dao.GetStoreDetail(db, goodsOrder.JxStoreID, 0, "")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
param := &tonglianpayapi.OnlinePayParam{
|
||||
Trxamt: utils.Int64ToStr(goodsOrder.ActualPayPrice),
|
||||
Reqsn: goodsOrder.VendorOrderID,
|
||||
Body: storeDetail.Name,
|
||||
Authcode: userPaymentLabel, // 支付授权码
|
||||
Chnlstoreid: utils.Int2Str(goodsOrder.JxStoreID),
|
||||
NotifyUrl: tonglianpayapi.OnlinePayCallbackUrl,
|
||||
Signtype: tonglianpayapi.EncryptionRsa,
|
||||
}
|
||||
terminfo := &tonglianpayapi.TerminfoBase{
|
||||
Termno: fmt.Sprintf("%d_1", goodsOrder.JxStoreID),
|
||||
Devicetype: "10",
|
||||
Termsn: fmt.Sprintf("%d_1", goodsOrder.JxStoreID),
|
||||
Longitude: fmt.Sprintf("+%s", utils.Float64ToStr(jxutils.IntCoordinate2Standard(storeDetail.Lng))),
|
||||
Latitude: fmt.Sprintf("+%s", utils.Float64ToStr(jxutils.IntCoordinate2Standard(storeDetail.Lat))),
|
||||
}
|
||||
terminfoBByte, _ := json.Marshal(terminfo)
|
||||
param.Terminfo = string(terminfoBByte)
|
||||
|
||||
vendorCode, trxId, remake, err := api.TLpayAPI.CreateOnlineBankOrder(param)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if vendorCode == tonglianpayapi.TrxStatusSuccess {
|
||||
goodsOrder.Status = model.OrderStatusFinished
|
||||
} else if vendorCode == tonglianpayapi.TrxStatusTransaction || vendorCode == tonglianpayapi.TrxStatusTransaction2 {
|
||||
goodsOrder.Status = model.OrderStatusWaitPay
|
||||
} else {
|
||||
goodsOrder.Status = model.OrderStatusPayFail
|
||||
}
|
||||
goodsOrder.VendorStatus = vendorCode
|
||||
goodsOrder.VendorOrderID2 = trxId
|
||||
dao.UpdateEntity(db, goodsOrder, "Status", "VendorStatus", "VendorOrderID2")
|
||||
partner.CurOrderManager.OnOrderMsg(goodsOrder, vendorCode, fmt.Sprintf(vendorCode+":"+TransactionStatus[vendorCode]+":%s", remake))
|
||||
if vendorCode == "3045" || vendorCode == "3999" || vendorCode == "3889" {
|
||||
return remake, nil
|
||||
}
|
||||
return TransactionStatus[vendorCode], nil
|
||||
}
|
||||
|
||||
// OnTLOnlinePayCallback 通联扫码枪扫码支付回调
|
||||
func OnTLOnlinePayCallback(call *tonglianpayapi.CallBackResultOnlinePay) (err error) {
|
||||
switch call.TrxCode {
|
||||
case tonglianpayapi.MsgTypePay, tonglianpayapi.MsgTypePayZFB:
|
||||
err = onTLOnlinePayFinished(call)
|
||||
case tonglianpayapi.MsgTypeRefund, tonglianpayapi.MsgTypeRefundZFB:
|
||||
err = onTLOnlinePayRefund(call)
|
||||
default:
|
||||
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func onTLOnlinePayFinished(call *tonglianpayapi.CallBackResultOnlinePay) (err error) {
|
||||
db := dao.GetDB()
|
||||
if order, err := partner.CurOrderManager.LoadOrder(call.CusorderID, model.VendorIDJX); err == nil {
|
||||
if call.TrxStatus == tonglianpayapi.TrxStatusSuccess {
|
||||
loc, _ := time.LoadLocation("Local")
|
||||
t1, _ := time.ParseInLocation("20060102150405", call.PayTime, loc)
|
||||
order.OrderFinishedAt = t1
|
||||
order.Status = model.OrderStatusFinished
|
||||
} else if call.TrxStatus == tonglianpayapi.TrxStatusTransaction || call.TrxStatus == tonglianpayapi.TrxStatusTransaction2 {
|
||||
order.Status = model.OrderStatusWaitPay
|
||||
} else {
|
||||
order.Status = model.OrderStatusPayFail
|
||||
}
|
||||
order.VendorStatus = call.TrxStatus
|
||||
dao.UpdateEntity(db, order, "Status", "OrderFinishedAt", "VendorStatus")
|
||||
partner.CurOrderManager.OnOrderMsg(order, call.TrxStatus, fmt.Sprintf(call.TrxStatus+":"+TransactionStatus[call.TrxStatus]+":支付结果回调成功"))
|
||||
|
||||
//if call.TrxStatus == tonglianpayapi.TrxStatusSuccess {
|
||||
// err = OnPayFinished(orderPay)
|
||||
//}
|
||||
} else {
|
||||
globals.SugarLogger.Debugf("onTLpayFinished msg:%s, err:%v", utils.Format4Output(call, true), err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func onTLOnlinePayRefund(call *tonglianpayapi.CallBackResultOnlinePay) (err error) {
|
||||
db := dao.GetDB()
|
||||
afsOrder, err := partner.CurOrderManager.LoadAfsOrder(call.CusorderID, model.VendorIDJX)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if afsOrder == nil {
|
||||
return fmt.Errorf("CusorderID 错误")
|
||||
}
|
||||
goodsOrder, err := partner.CurOrderManager.LoadOrder(afsOrder.VendorOrderID, model.VendorIDJX)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//partner.CurOrderManager.OnOrderMsg(goodsOrder, call.TrxStatus, fmt.Sprintf(call.TrxStatus+":"+TransactionStatus[call.TrxStatus]+":支付结果回调成功"))
|
||||
// 退款成功
|
||||
if call.TrxStatus == tonglianpayapi.TrxStatusSuccess {
|
||||
afsOrder.VendorStatus = call.TrxStatus
|
||||
afsOrder.Status = model.AfsOrderStatusFinished
|
||||
afsOrder.AfsFinishedAt = time.Now()
|
||||
dao.UpdateEntity(db, afsOrder, "VendorStatus", "Status", "AfsFinishedAt")
|
||||
}
|
||||
|
||||
// 是否全退取消订单
|
||||
orderSkuCount := 0
|
||||
for _, v := range goodsOrder.Skus {
|
||||
orderSkuCount += v.Count
|
||||
}
|
||||
|
||||
afsSkus, err := dao.GetStoreAfsOrderSkuList2(db, []string{goodsOrder.VendorOrderID})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
refundSkuCount := 0
|
||||
for _, v := range afsSkus {
|
||||
refundSkuCount += v.Count
|
||||
}
|
||||
|
||||
if orderSkuCount == refundSkuCount {
|
||||
goodsOrder.Status = model.OrderStatusCanceled
|
||||
goodsOrder.VendorStatus = call.TrxStatus
|
||||
dao.UpdateEntity(db, goodsOrder, "Status", "VendorStatus")
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// QueryBarCodeScannerStatus 刷新当前订单的支付状态
|
||||
func QueryBarCodeScannerStatus(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("此订单不是京西订单,无法使用该功能")
|
||||
}
|
||||
|
||||
param := &tonglianpayapi.PayTransactionStatusQuery{
|
||||
Reqsn: goodsOrder.VendorOrderID,
|
||||
Trxid: "",
|
||||
Randomstr: utils.GetUUID(),
|
||||
Signtype: tonglianpayapi.EncryptionRsa,
|
||||
Sign: "",
|
||||
}
|
||||
vendorCode, remake, err := api.TLpayAPI.QueryPayTransaction(param)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if vendorCode == tonglianpayapi.TrxStatusSuccess {
|
||||
goodsOrder.OrderFinishedAt = time.Now()
|
||||
goodsOrder.Status = model.OrderStatusFinished
|
||||
} else if vendorCode == tonglianpayapi.TrxStatusTransaction || vendorCode == tonglianpayapi.TrxStatusTransaction2 {
|
||||
goodsOrder.Status = model.OrderStatusWaitPay
|
||||
} else {
|
||||
goodsOrder.Status = model.OrderStatusPayFail
|
||||
}
|
||||
goodsOrder.VendorStatus = vendorCode
|
||||
dao.UpdateEntity(db, goodsOrder, "Status", "VendorStatus", "OrderFinishedAt")
|
||||
partner.CurOrderManager.OnOrderMsg(goodsOrder, vendorCode, fmt.Sprintf("扫码枪扫码刷新结果:[code:%s,说明:%s,异常原因:%s],本地状态[%d]", vendorCode, TransactionStatus[vendorCode], remake, goodsOrder.Status))
|
||||
|
||||
if vendorCode == "3045" || vendorCode == "3999" || vendorCode == "3889" {
|
||||
return remake, nil
|
||||
}
|
||||
return TransactionStatus[vendorCode], nil
|
||||
}
|
||||
|
||||
// RefundBarCodeScannerOrder 扫码支付订单退单
|
||||
func RefundBarCodeScannerOrder(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
|
||||
}
|
||||
|
||||
// 通知退款,等待回传
|
||||
status, errMsg, err := api.TLpayAPI.OrderRefund(&tonglianpayapi.OnLineOrderRefundParam{
|
||||
Trxamt: utils.Int2Str(refundMoney),
|
||||
Reqsn: afsOrder.AfsOrderID,
|
||||
Oldreqsn: goodsOrder.VendorOrderID,
|
||||
Oldtrxid: "",
|
||||
Remark: reason,
|
||||
Benefitdetail: "",
|
||||
Randomstr: utils.GetUUID(),
|
||||
Signtype: tonglianpayapi.EncryptionRsa,
|
||||
Sign: "",
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch status {
|
||||
case "0000", "1001", "2008", "2000":
|
||||
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
|
||||
}
|
||||
dao.Commit(db, txDB)
|
||||
default:
|
||||
return fmt.Errorf(errMsg)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkJxAfsOrder(db *dao.DaoDB, goodsOrder *model.GoodsOrder, vendorOrderId string, skuIds map[int]int) (bool, int, error) {
|
||||
if goodsOrder.Status != model.OrderStatusFinished {
|
||||
return false, 0, fmt.Errorf("订单未完成支付,无法退款(刷新订单状态/联系管理员)")
|
||||
}
|
||||
|
||||
// 未结束的售后单,不让继续添加售后单了
|
||||
completeAfsOrder, _ := dao.GetAfsOrders(db, model.VendorIDJX, vendorOrderId, "")
|
||||
if len(completeAfsOrder) != model.NO {
|
||||
for _, v := range completeAfsOrder {
|
||||
if v.Status != model.AfsOrderStatusFinished {
|
||||
return false, 0, fmt.Errorf("此订单还有未完成的售后单,请稍后再处理")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
totalCount := 0 // 总的商品个数
|
||||
skuList := make(map[int]*model.OrderSku, 0)
|
||||
for _, v := range goodsOrder.Skus {
|
||||
skuList[v.SkuID] = v
|
||||
totalCount += v.Count
|
||||
}
|
||||
|
||||
// 已经完成商品个数+当次录入商品个数>订单商品个数 不让继续退了
|
||||
afsSkuList, _ := dao.GetStoreAfsOrderSkuList2(db, []string{vendorOrderId}) // 已经退款商品
|
||||
afsCount := 0 // 总的售后个数
|
||||
for _, v := range afsSkuList {
|
||||
if v.Count+skuIds[v.SkuID] > skuList[v.SkuID].Count {
|
||||
return false, 0, fmt.Errorf("商品[%s],记录购买个数为:%d个,退款个数为:%d个,请检查输入", skuList[v.SkuID].SkuName, skuList[v.SkuID].Count, v.Count+skuIds[v.SkuID])
|
||||
}
|
||||
afsCount += v.Count + skuIds[v.SkuID]
|
||||
}
|
||||
|
||||
if afsCount > totalCount {
|
||||
return false, 0, fmt.Errorf("退货商品数计算结果大于订单商品数,请联系管理员")
|
||||
}
|
||||
|
||||
totalRefundMoney := 0 // 总退款金额
|
||||
for skuId, skuCount := range skuIds {
|
||||
if skuList[skuId] != nil && skuList[skuId].Count >= skuCount {
|
||||
totalRefundMoney += int(skuList[skuId].SalePrice) * skuCount
|
||||
}
|
||||
}
|
||||
|
||||
return totalCount == afsCount, totalRefundMoney, nil
|
||||
}
|
||||
|
||||
func addRefundSku(ctx *jxcontext.Context, goodsOrder *model.GoodsOrder, skuIds map[int]int, reason string, refundType bool) (afsOrder *model.AfsOrder, skuFinancial, afsSkuFinancial []*model.OrderSkuFinancial, err error) {
|
||||
refundMoney := 0 // 退款金额
|
||||
afsOrderID := utils.Int64ToStr(jxutils.GenAfsOrderNo()) // 退款Id
|
||||
orderSkuFinancial := make([]*model.OrderSkuFinancial, 0, len(goodsOrder.Skus)) // 所有商品
|
||||
afsOrderSkuFinancial := make([]*model.OrderSkuFinancial, 0, len(skuIds)) // 申请退款商品
|
||||
|
||||
for _, v := range goodsOrder.Skus {
|
||||
orderSku := &model.OrderSkuFinancial{
|
||||
ModelIDCUL: model.ModelIDCUL{
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
LastOperator: ctx.GetUserName(),
|
||||
},
|
||||
VendorID: model.VendorIDJX,
|
||||
VendorOrderID: goodsOrder.VendorOrderID,
|
||||
VendorSubOrderID: "",
|
||||
AfsOrderID: "",
|
||||
IsAfsOrder: 0,
|
||||
VendorStoreID: utils.Int2Str(goodsOrder.JxStoreID),
|
||||
StoreID: goodsOrder.JxStoreID,
|
||||
JxStoreID: goodsOrder.JxStoreID,
|
||||
VendorSkuID: v.VendorSkuID,
|
||||
SkuID: v.SkuID,
|
||||
JxSkuID: v.JxSkuID,
|
||||
PromotionType: 0,
|
||||
Name: v.SkuName,
|
||||
ShopPrice: v.ShopPrice,
|
||||
SalePrice: v.SalePrice,
|
||||
Count: v.Count,
|
||||
SkuBoxMoney: 0,
|
||||
UserMoney: v.SalePrice,
|
||||
PmSubsidyMoney: 0,
|
||||
PmSkuSubsidyMoney: 0,
|
||||
PmDeductionsMoney: 0,
|
||||
ShopMoney: v.SalePrice,
|
||||
ShopMoneyByCal: 0,
|
||||
JxSubsidyMoney: 0,
|
||||
JxSkuSubsidyMoney: 0,
|
||||
JxDeductionsMoney: 0,
|
||||
JxShopMoney: v.SalePrice,
|
||||
RefundMoney: 0,
|
||||
RefundMoneyByCal: 0,
|
||||
StoreSubID: 0,
|
||||
StoreSubName: "",
|
||||
}
|
||||
orderSkuFinancial = append(orderSkuFinancial, orderSku)
|
||||
if skuIds[v.SkuID] != 0 && v.Count >= skuIds[v.SkuID] {
|
||||
refundMoney += int(v.SalePrice) * v.Count
|
||||
orderSku.AfsOrderID = afsOrderID
|
||||
orderSku.IsAfsOrder = 1
|
||||
orderSku.Count = skuIds[v.SkuID]
|
||||
orderSku.RefundMoney = v.SalePrice * int64(v.Count)
|
||||
afsOrderSkuFinancial = append(afsOrderSkuFinancial, orderSku)
|
||||
}
|
||||
}
|
||||
|
||||
afsOrder = &model.AfsOrder{
|
||||
ModelIDCUL: model.ModelIDCUL{
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
LastOperator: ctx.GetUserName(),
|
||||
},
|
||||
VendorID: model.VendorIDJX,
|
||||
AfsOrderID: afsOrderID,
|
||||
VendorOrderID: goodsOrder.VendorOrderID,
|
||||
VendorStoreID: utils.Int2Str(goodsOrder.StoreID),
|
||||
StoreID: goodsOrder.StoreID,
|
||||
AfsCreatedAt: time.Now(),
|
||||
VendorAppealType: utils.Int2Str(model.VendorIDJX),
|
||||
AppealType: model.AfsAppealTypeReturnAndRefund,
|
||||
VendorReasonType: "",
|
||||
ReasonType: model.AfsReasonNotOthers,
|
||||
ReasonDesc: utils.LimitUTF8StringLen(reason, 1024),
|
||||
ReasonImgList: "",
|
||||
RefundType: model.AfsTypePartRefund,
|
||||
VendorOrgCode: "0",
|
||||
RefundMoney: int64(refundMoney),
|
||||
Status: model.AfsOrderStatusNew,
|
||||
Flag: 0,
|
||||
AfsTotalShopMoney: goodsOrder.ActualPayPrice - int64(refundMoney),
|
||||
}
|
||||
if refundType {
|
||||
afsOrder.RefundType = model.AfsTypeFullRefund
|
||||
}
|
||||
|
||||
return afsOrder, orderSkuFinancial, afsOrderSkuFinancial, err
|
||||
}
|
||||
Reference in New Issue
Block a user