gin-example/normal/service/transfer.go
2023-09-14 14:49:47 +08:00

142 lines
3.9 KiB
Go

package service
import (
"dddexample/normal/common"
model2 "dddexample/normal/model"
"encoding/json"
"errors"
"fmt"
"github.com/IBM/sarama"
"io"
"net/http"
)
func TransferOld(sourceUserId int, targetAccountNumber string, targetAmount float64, targetCurrency string) error {
// 1. 从数据库读取数据,忽略所有校验逻辑如账号是否存在等,错误忽略
var targetAccountDO, sourceAccountDO model2.Account
model2.DB.Model(&model2.Account{}).Find(&sourceAccountDO, sourceUserId)
model2.DB.Model(&model2.Account{}).Where(&model2.Account{TelNum: targetAccountNumber}).Find(&targetAccountDO)
// 2. 业务参数校验
if targetAccountDO.Currency != targetCurrency {
return errors.New("收款人货币种类与转账使用货币不同")
}
// 3. 获取外部数据,并且包含一定的业务逻辑 获取汇率
exchangeRate := 1.0
if sourceAccountDO.Currency != targetCurrency {
var err error
res, err := http.Get("http://www.google.com?now=" + sourceAccountDO.Currency + "&targetCurrency=" + targetCurrency)
if err != nil {
return err
}
body, err := io.ReadAll(res.Body)
res.Body.Close()
if err != nil {
return err
}
if res.StatusCode != 200 {
return errors.New(fmt.Sprintf("Response failed with status code: %d and\nbody: %s\n", res.StatusCode, body))
}
var yahuRes common.YaHuRes
err = json.Unmarshal(body, &yahuRes)
if err != nil {
return err
}
exchangeRate = yahuRes.Rate
}
sourceAmount := targetAmount * exchangeRate
// 4. 业务参数校验
if sourceAccountDO.Amount < sourceAmount {
return errors.New("余额不足")
}
if sourceAccountDO.DailyLimit < sourceAmount {
return errors.New("超出限额")
}
// 5. 计算新值,并且更新字段
sourceAccountDO.Amount -= sourceAmount
targetAccountDO.Amount += sourceAmount
// 6. 更新到数据库
model2.DB.Save(sourceAccountDO)
model2.DB.Save(targetAccountDO)
// 7. 发送审计消息String message = sourceUserId + "," + targetAccountNumber + "," + targetAmount + "," + targetCurrency;
//common.SendKafka("kafka", "")
config := sarama.NewConfig()
config.Producer.RequiredAcks = sarama.WaitForAll
config.Producer.Retry.Max = 5
config.Producer.Return.Successes = true
producer, err := sarama.NewSyncProducer([]string{"localhost:9092"}, config)
if err != nil {
fmt.Println("Failed to create producer:", err)
return err
}
defer producer.Close()
message := &sarama.ProducerMessage{
Topic: "my_topic",
Value: sarama.StringEncoder("Hello, Kafka!"),
}
_, _, err = producer.SendMessage(message)
return err
}
func Transfer(sourceUserId int, targetAccountNumber string, targetAmount float64, targetCurrency string) error {
// 1. 从数据库读取数据,忽略所有校验逻辑如账号是否存在等
sourceAccountDO := model2.SelectByUserId(sourceUserId)
targetAccountDO := model2.SelectByAccountNumber(targetAccountNumber)
// 2. 业务参数校验
if targetAccountDO.Currency != targetCurrency {
return errors.New("收款人货币种类与转账使用货币不同")
}
// 3. 获取外部数据,并且包含一定的业务逻辑 获取汇率
exchangeRate := 1.0
if sourceAccountDO.Currency != targetCurrency {
var err error
exchangeRate, err = common.GetExchangeRate(sourceAccountDO.Currency, targetCurrency)
if err != nil {
return err
}
}
sourceAmount := targetAmount * exchangeRate
// 4. 业务参数校验
if sourceAccountDO.Amount < sourceAmount {
return errors.New("余额不足")
}
if sourceAccountDO.DailyLimit < sourceAmount {
return errors.New("超出限额")
}
// 5. 计算新值,并且更新字段
sourceAccountDO.Amount -= sourceAmount
targetAccountDO.Amount += sourceAmount
// 6. 更新到数据库
model2.DB.Save(sourceAccountDO)
model2.DB.Save(targetAccountDO)
// 7. 发送审计消息String message = sourceUserId + "," + targetAccountNumber + "," + targetAmount + "," + targetCurrency;
common.SendKafka("kafka", "")
return nil
}