block_chain.go 6.4 KB
package service

import (
	"fmt"
	"github.com/linmadan/egglib-go/core/application"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/application/blockChain/command"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/application/blockChain/dto"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/application/blockChain/query"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/application/factory"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/domain"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/infrastructure/blockchain"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/infrastructure/utils"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/log"
	"strconv"
	"time"
)

// 区块链服务
type BlockChainService struct {
}

// 数据上链
func (blockChainService *BlockChainService) UpChain(upChainCommand *command.UpChainCommand) (interface{}, error) {
	if err := upChainCommand.ValidateCommand(); err != nil {
		return nil, application.ThrowError(application.ARG_ERROR, err.Error())
	}
	transactionContext, err := factory.CreateTransactionContext(nil)
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err := transactionContext.StartTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()

	upChain := &domain.UpChain{
		Source:        upChainCommand.Source,
		PrimaryId:     upChainCommand.PrimaryId,
		IssueId:       upChainCommand.IssueId,
		Data:          upChainCommand.Data,
		UpChainStatus: 2,
		CreatedAt:     time.Now(),
	}

	// 1. 查重
	upChainRepository, _, _ := factory.FastPgUpChain(transactionContext, 0)
	// 可溯源数据,可重复上传,可以追溯历史修改记录
	if len(upChain.IssueId) == 0 {
		if item, err := upChainRepository.FindOne(map[string]interface{}{"source": upChain.Source, "primaryId": upChain.PrimaryId}); err == nil && item != nil {
			return nil, fmt.Errorf("duplicate message %v %v", upChain.Source, upChain.PrimaryId)
		}
	}

	// 2.上链
	bc := &blockchain.BSNBlockChain{
		PublicPem:      []byte(blockchain.PubPem),
		Host:           blockchain.Host,
		PublicKey:      blockchain.PubKey,
		PrivatePem:     blockchain.PriK,
		EnableDebugLog: true,
	}
	options := blockchain.NewUpToChainOptions(upChain.Source, upChain.PrimaryId, upChain.Data).WithInnerPrimaryIssueId(upChain.IssueId)
	upToChainResponse, e := bc.UpToChain(options)
	if e != nil || upToChainResponse == nil {
		upChain.UpFail()
		if e != nil {
			log.Logger.Error("up chain err:" + e.Error())
		}
	} else {
		upChain.UpSuccess(string(*upToChainResponse))
	}

	// 3.保存记录
	if upChain, err = upChainRepository.Save(upChain); err != nil {
		return nil, err
	}

	if err := transactionContext.CommitTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	return upChain, nil
}

// 区块链列表
func (blockChainService *BlockChainService) ListBlockChain(listBlockChain *query.ListBlockChainQuery) (interface{}, error) {
	if err := listBlockChain.ValidateQuery(); err != nil {
		return nil, application.ThrowError(application.ARG_ERROR, err.Error())
	}
	transactionContext, err := factory.CreateTransactionContext(nil)
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err := transactionContext.StartTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()

	upChainRepository, _, _ := factory.FastPgUpChain(transactionContext, 0)
	queryOptions := utils.ObjectToMap(listBlockChain)

	_, upChains, err := upChainRepository.Find(queryOptions)
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	response := dto.NewBlockChains(upChains)
	if err := transactionContext.CommitTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	return response, nil
}

func (blockChainService *BlockChainService) GetBlockChainToken(listBlockChain *query.GetBlockChainTokenQuery) (interface{}, error) {
	if err := listBlockChain.ValidateQuery(); err != nil {
		return nil, application.ThrowError(application.ARG_ERROR, err.Error())
	}
	transactionContext, err := factory.CreateTransactionContext(nil)
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err := transactionContext.StartTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()

	upChainRepository, _, _ := factory.FastPgUpChain(transactionContext, 0)

	upChain, err := upChainRepository.FindOne(map[string]interface{}{"upChainId": listBlockChain.UpChainId})
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	var request = blockchain.GetTokenRequest{
		Type:      listBlockChain.Type,
		ShowValue: true,
	}
	bsn := newBSNBlockChain()
	switch listBlockChain.Type {
	case blockchain.QueryByHashId:
		request.TsTxId = upChain.Hash
	case blockchain.QueryByIssueId:
		request.TsTxId = upChain.Hash
		request.IssueId = upChain.IssueId
	default:
		return nil, application.ThrowError(application.ARG_ERROR, "unknown type "+strconv.Itoa(listBlockChain.Type))
	}
	getTokenResponse, err := bsn.GetToken(&request)
	if err != nil {
		log.Logger.Error(err.Error())
		return nil, application.ThrowError(application.BUSINESS_ERROR, "不存在")
	}
	if err := transactionContext.CommitTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	return map[string]interface{}{
		"token":     getTokenResponse.Token,
		"browseUrl": fmt.Sprintf("%v?token=%v", blockchain.BlockBrowserAddress, getTokenResponse.Token),
	}, nil
}

func newBSNBlockChain() *blockchain.BSNBlockChain {
	// 2.上链
	bc := &blockchain.BSNBlockChain{
		PublicPem:      []byte(blockchain.PubPem),
		Host:           blockchain.Host,
		PublicKey:      blockchain.PubKey,
		PrivatePem:     blockchain.PriK,
		EnableDebugLog: true,
	}
	return bc
}

func NewBlockChainService(options map[string]interface{}) *BlockChainService {
	newBlockChainService := &BlockChainService{}
	return newBlockChainService
}