proc/worker/client.go
func (w *Worker) ClientEndpointCreate(job *data.Job) error {
	logger := w.logger.Add("method", "ClientEndpointCreate",
		"job", job)

	ch, err := w.relatedChannel(logger, job,
		data.JobClientEndpointRestore)
	if err != nil {
		return err
	}

	var jdata data.JobEndpointCreateData
	if err := w.unmarshalDataTo(logger, job.Data, &jdata); err != nil {
		return err
	}

	msg, err := w.extractEndpointMessage(logger, ch, jdata.EndpointSealed)
	if err != nil {
		return err
	}

	offer, err := w.offering(logger, ch.Offering)
	if err != nil {
		return err
	}

	url := strings.Replace(w.countryConfig.URLTemplate,
		"{{ip}}", msg.ServiceEndpointAddress, 1)

	var countryStatus string

	c, err := country.GetCountry(w.countryConfig.Timeout, url,
		w.countryConfig.Field)
	if err != nil || len(c) != 2 {
		countryStatus = data.CountryStatusUnknown
	} else if c == offer.Country {
		countryStatus = data.CountryStatusValid
	} else {
		countryStatus = data.CountryStatusInvalid
	}

	params, _ := json.Marshal(msg.AdditionalParams)

	return w.db.InTransaction(func(tx *reform.TX) error {
		raddr := pointer.ToString(msg.PaymentReceiverAddress)
		saddr := pointer.ToString(msg.ServiceEndpointAddress)
		endp := data.Endpoint{
			ID:                     util.NewUUID(),
			Template:               offer.Template,
			Channel:                ch.ID,
			Hash:                   msg.TemplateHash,
			RawMsg:                 data.FromBytes(jdata.EndpointSealed),
			PaymentReceiverAddress: raddr,
			ServiceEndpointAddress: saddr,
			Username:               pointer.ToString(msg.Username),
			Password:               pointer.ToString(msg.Password),
			AdditionalParams:       params,
			CountryStatus:          pointer.ToString(countryStatus),
		}
		if err = w.db.Insert(&endp); err != nil {
			logger.Add("endpoint", endp).Error(err.Error())
			return ErrInternal
		}

		ch.ServiceStatus = data.ServiceSuspended
		changedTime := time.Now()
		ch.ServiceChangedTime = &changedTime
		// TODO: Review flow with service_changed_time.
		ch.PreparedAt = changedTime
		err = w.saveRecord(logger, w.db.Querier, ch)
		if err != nil {
			logger.Error(err.Error())
			return ErrInternal
		}

		return nil
	})
}
func (w *Worker) ClientEndpointCreate(job *data.Job) error {
	logger := w.logger.Add("method", "ClientEndpointCreate",
		"job", job)

	ch, err := w.relatedChannel(logger, job,
		data.JobClientEndpointRestore)
	if err != nil {
		return err
	}

	var jdata data.JobEndpointCreateData
	if err := w.unmarshalDataTo(logger, job.Data, &jdata); err != nil {
		return err
	}

	msg, err := w.extractEndpointMessage(logger, ch, jdata.EndpointSealed)
	if err != nil {
		return err
	}

	offer, err := w.offering(logger, ch.Offering)
	if err != nil {
		return err
	}

	url := strings.Replace(w.countryConfig.URLTemplate,
		"{{ip}}", msg.ServiceEndpointAddress, 1)

	var countryStatus string

	c, err := country.GetCountry(w.countryConfig.Timeout, url,
		w.countryConfig.Field)
	if err != nil || len(c) != 2 {
		countryStatus = data.CountryStatusUnknown
	} else if c == offer.Country {
		countryStatus = data.CountryStatusValid
	} else {
		countryStatus = data.CountryStatusInvalid
	}

	params, _ := json.Marshal(msg.AdditionalParams)

	return w.db.InTransaction(func(tx *reform.TX) error {
		raddr := pointer.ToString(msg.PaymentReceiverAddress)
		saddr := pointer.ToString(msg.ServiceEndpointAddress)
		endp := data.Endpoint{
			ID:                     util.NewUUID(),
			Template:               offer.Template,
			Channel:                ch.ID,
			Hash:                   msg.TemplateHash,
			RawMsg:                 data.FromBytes(jdata.EndpointSealed),
			PaymentReceiverAddress: raddr,
			ServiceEndpointAddress: saddr,
			Username:               pointer.ToString(msg.Username),
			Password:               pointer.ToString(msg.Password),
			AdditionalParams:       params,
			CountryStatus:          pointer.ToString(countryStatus),
		}
		if err = w.db.Insert(&endp); err != nil {
			logger.Add("endpoint", endp).Error(err.Error())
			return ErrInternal
		}

		ch.ServiceStatus = data.ServiceSuspended
		changedTime := time.Now()
		ch.ServiceChangedTime = &changedTime
		// TODO: Review flow with service_changed_time.
		ch.PreparedAt = changedTime
		err = w.saveRecord(logger, w.db.Querier, ch)
		if err != nil {
			logger.Error(err.Error())
			return ErrInternal
		}

		return nil
	})
}
// ClientEndpointCreate decodes endpoint message, saves it in the DB and
// triggers product configuration.