package lendbox import ( "bytes" "errors" "fmt" "io" "io/ioutil" "mime/multipart" "net/http" "net/textproto" "os" "strings" "time" log "github.com/rs/zerolog/log" //"mime/multipart" "cf-capital/module_server/handlers/auth" connection "cf-capital/module_server/handlers/connection" eloquent "cf-capital/module_server/handlers/eloquent" server_handlers "cf-server/server/handlers" "encoding/base64" "encoding/json" "github.com/go-playground/validator/v10" ) type responseBody struct { Status string `json:"status"` Message string `json:"message"` Token string `json:"token,omitempty"` Data string `json:"data,omitempty"` } type InvestorRegistration struct { Data InvestorRegistrationData Result InvestorRegistrationDataResult Auth auth.AuthUser } type InvestorRegistrationDataResult struct { ID int64 `json:"id"` Success bool `json:"success"` Msg string `json:"msg"` Data dataIr } type dataIr struct { LBUserId int64 `json:"lbUserId"` } type InvestorRegistrationData struct { FirstName string `json:"firstName" validate:"required"` LastName string `json:"lastName" validate:"required"` Email string `json:"email" validate:"required"` Title string `json:"title" validate:"required" binding:"Mr.,Ms."` CountryCode string `json:"countryCode" validate:"required"` Mobile string `json:"mobile" validate:"required"` PAN string `json:"pan" validate:"required"` DOB string `json:"dob" validate:"required"` Street1 string `json:"street1"` Street2 string `json:"street2"` City string `json:"city"` Pin string `json:"pin"` IP string `json:"ip" validate:"required"` UA string `json:"ua" validate:"required"` Timestamp string `json:"timestamp" validate:"required"` } type BankDetails struct { Data BankDetailsData Result BankDetailsDataResult Auth auth.AuthUser } type BankDetailsDataResult struct { ID int64 `json:"id"` Success bool `json:"success"` Msg string `json:"msg"` Data dataIr } type BankDetailsData struct { LBUserId string `json:"lbUserId" validate:"required"` ID int64 `json:"id"` AccountNumber string `json:"accountNumber"` IFSC string `json:"ifsc"` HolderName string `json:"holderName"` AccountType string `json:"accountType"` BankName string `json:"bankName"` BranchName string `json:"branchName"` } type DocsUpload struct { Data UploadDocsData Result UploadDocsDataResult Auth auth.AuthUser } type UploadDocsDataResult struct { ID int64 `json:"id"` Success bool `json:"success"` Msg string `json:"msg"` } type UploadDocsData struct { LBUserId string `json:"lbUserId" validate:"required"` DocName string `json:"docName" validate:"required"` DocFormat string `json:"docFormat" validate:"required"` DocPassword string `json:"docPassword"` DocContent string `json:"docContent" validate:"required"` } type WalletOrder struct { Data []WalletOrderData Result WalletOrderDataResult } type WalletOrderDataResult struct { ID int64 `json:"id"` Success bool `json:"success"` Msg string `json:"msg"` } type WalletOrderData struct { LBUserId int64 Amount float64 TxType string TxId string LoanId int64 InvestmentId int64 InvestmentType string TxTime string ProductType string Note string } func InvestorSignUp() http.HandlerFunc { return func(w http.ResponseWriter, req *http.Request) { w.Header().Set("Content-Type", "application/json") reqBody, _ := ioutil.ReadAll(req.Body) var lend InvestorRegistration lend.Auth.ID = auth.GetAuth(req) log.Print("Auth ID", lend.Auth.ID) err := json.Unmarshal(reqBody, &lend.Data) if err != nil { log.Error().Err(err).Msg(err.Error()) server_handlers.FormatResponse(w, 400) _ = json.NewEncoder(w).Encode(responseBody{Status: "FAIL", Message: "Unable to parse the data"}) return } validate := validator.New() err = validate.Struct(lend.Data) if err != nil { log.Error().Err(err).Msg(err.Error()) server_handlers.FormatResponse(w, 400) _ = json.NewEncoder(w).Encode(responseBody{Status: "FAIL", Message: err.Error()}) return } _, err = lend.RegisterInvestor() if err != nil { log.Print(err.Error()) server_handlers.FormatResponse(w, 400) _ = json.NewEncoder(w).Encode(responseBody{Status: "FAIL", Message: err.Error()}) return } server_handlers.FormatResponse(w, 200) _ = json.NewEncoder(w).Encode(responseBody{Status: "OK", Message: "Investor registered successfully"}) } } func (manager InvestorRegistration) RegisterInvestor() (InvestorRegistrationDataResult, error) { var investorRegistrationDataResult InvestorRegistrationDataResult //reqBodyBytes := new(bytes.Buffer) //json.NewEncoder(reqBodyBytes).Encode(manager.Data) //responseBody := bytes.NewBuffer(reqBodyBytes.Bytes()) payload, err := json.Marshal(manager.Data) if err != nil { log.Print(err) return investorRegistrationDataResult, err } responseBody := strings.NewReader(string(payload)) body, err := callAPI(responseBody, fmt.Sprint(os.Getenv("LENDBOX_HOST"), "v1/partners/investor-signup"), "application/json") if err != nil { log.Print(err.Error()) return investorRegistrationDataResult, err } err = json.Unmarshal([]byte(body), &investorRegistrationDataResult) if err != nil { log.Print(err.Error()) return investorRegistrationDataResult, err } if investorRegistrationDataResult.Success == false { log.Print(investorRegistrationDataResult.Msg) return investorRegistrationDataResult, errors.New(investorRegistrationDataResult.Msg) } investorRegistrationDataResult, err = saveRegistrationDetails(manager, investorRegistrationDataResult) if err != nil { return investorRegistrationDataResult, err } return investorRegistrationDataResult, nil } func callAPI(responseBody *strings.Reader, api string, cType string) (string, error) { //We will add this secret key in env //os.Setenv("LENDBOX_API_KEY", "eT3uqRLmwjQZKnNRouo3fRZ5VT5DH6JxRWU9RGnagB5c4UhF5veqZkmxxaht1Qgi9rPqkZ8z8NPRK6mNzrkb8HaxBXRxaAAi1LpN") //os.Setenv("LENDBOX_API_KEY", "ts68p1myyIu8C6DnryCIi8slejERgI2pn84uxco1bdIhIbFyv7dokbc5z981d0z5ptlFzlRl4oR1qDi3pF1neeIE50xRTqRyAsop") //os.Setenv("LENDBOX_API_CODE", "QSUQiZynjqfaYCE1CnhaPQ==") //os.Setenv("LENDBOX_API_CODE", "OB5jmLKuVuzPFVhGZiSwmA==") client := &http.Client{ Timeout: time.Second * 10, } //readBuf, _ := ioutil.ReadAll(responseBody) log.Print("string(readBuf)") log.Print(api) log.Print(responseBody) req, err := http.NewRequest("POST", api, responseBody) if err != nil { return "", err } req.Header.Add("Content-Type", cType) req.Header.Add("x-api-key", os.Getenv("LENDBOX_API_KEY")) req.Header.Add("x-api-code", os.Getenv("LENDBOX_API_CODE")) response, err := client.Do(req) if err != nil { return "", err } defer response.Body.Close() body, err := ioutil.ReadAll(response.Body) if err != nil { log.Print(err.Error()) return "", err } log.Print(string(body)) return string(body), nil } func saveRegistrationDetails(manager InvestorRegistration, managerResult InvestorRegistrationDataResult) (InvestorRegistrationDataResult, error) { tx, ctx, db := connection.Connect() dt := getDate() var investorRegistrationDataResult InvestorRegistrationDataResult res, err := tx.ExecContext(ctx, "UPDATE users SET lb_user_id = ?, updated_at = ? where id = ?", managerResult.Data.LBUserId, dt.Format("2006-01-02 15:04:05"), manager.Auth.ID) if err != nil { log.Print(err.Error()) tx.Rollback() return investorRegistrationDataResult, errors.New("Failed to execute the query") } lendbox_registration_id, err := res.LastInsertId() if err != nil { return investorRegistrationDataResult, errors.New("Not able to create registration entry in our system") } investorRegistrationDataResult.ID = lendbox_registration_id connection.Close(tx, db) return investorRegistrationDataResult, nil } func UploadDocs() http.HandlerFunc { return func(w http.ResponseWriter, req *http.Request) { w.Header().Set("Content-Type", "application/json") reqBody, _ := ioutil.ReadAll(req.Body) var lend DocsUpload var elo eloquent.DocumentUpload lend.Auth.ID = auth.GetAuth(req) err := json.Unmarshal(reqBody, &lend.Data) log.Print(lend.Data) if err != nil { log.Print(err.Error()) } validate := validator.New() err = validate.Struct(lend.Data) if err != nil { log.Error().Err(err).Msg(err.Error()) server_handlers.FormatResponse(w, 400) _ = json.NewEncoder(w).Encode(responseBody{Status: "FAIL", Message: err.Error()}) return } _, err = elo.UploadDocument() log.Print("UploadDocument called") _, err = lend.ShareWithLendbox() if err != nil { log.Print(err.Error()) server_handlers.FormatResponse(w, 400) _ = json.NewEncoder(w).Encode(responseBody{Status: "FAIL", Message: err.Error()}) return } server_handlers.FormatResponse(w, 200) _ = json.NewEncoder(w).Encode(responseBody{Status: "OK", Message: "User successfully registered"}) } } func createFormFile(w *multipart.Writer, contentType string, fieldName string, fileName string) (io.Writer, error) { h := make(textproto.MIMEHeader) h.Set("Content-Disposition", fmt.Sprintf(`form-data; name="%s"; filename="%s"`, fieldName, fileName)) h.Set("Content-Type", contentType) return w.CreatePart(h) } func (manager DocsUpload) ShareWithLendbox() (UploadDocsDataResult, error) { var uploadDocsDataResult UploadDocsDataResult log.Print("UploadDocument called 1") decodeBytes, err := base64.StdEncoding.DecodeString(manager.Data.DocContent) if err != nil { log.Error().Err(err).Msg(err.Error()) return uploadDocsDataResult, err } payload := &bytes.Buffer{} multipartWriter := multipart.NewWriter(payload) filevarnameStr := "PAN" filenameStr := "PAN" fileWriter, err := createFormFile(multipartWriter, "application/pdf", filevarnameStr, filenameStr) if err != nil { log.Error().Err(err).Msg(err.Error()) return uploadDocsDataResult, err } //_, err = fileWriter.Write() _, err = io.Copy(fileWriter, bytes.NewBuffer(decodeBytes)) if err != nil { log.Error().Err(err).Msg(err.Error()) return uploadDocsDataResult, err } /* f, err := os.Create("document") if err != nil { return uploadDocsDataResult, err } defer f.Close() if _, err := f.Write(dec); err != nil { return uploadDocsDataResult, err } */ /* payload := &bytes.Buffer{} writer := multipart.NewWriter(payload) file, errFile1 := os.Open("/document") defer file.Close() part1, errFile1 := writer.CreateFormFile("PAN",filepath.Base("/document")) _, errFile1 = io.Copy(part1, file) if errFile1 != nil { log.Print(errFile1) return uploadDocsDataResult, errFile1 } err := writer.Close() if err != nil { log.Print(err) return uploadDocsDataResult, err } */ body, err := callAPI(strings.NewReader(payload.String()), fmt.Sprint(os.Getenv("LENDBOX_HOST"), "v1/partners/upload/docs?lbUserId=", manager.Data.LBUserId), "multipart/form-data") if err != nil { log.Print(err.Error()) return uploadDocsDataResult, err } err = json.Unmarshal([]byte(body), &uploadDocsDataResult) if err != nil { log.Print(err.Error()) return uploadDocsDataResult, err } if uploadDocsDataResult.Success == false { return uploadDocsDataResult, errors.New(uploadDocsDataResult.Msg) } return uploadDocsDataResult, nil } /* func UploadDocsOld() http.HandlerFunc { return func(w http.ResponseWriter, req *http.Request) { w.Header().Set("Content-Type", "application/json") var lend DocsUpload lend.Auth.ID = auth.GetAuth(req) lend.Data.LBUserId = req.FormValue("lbUserId") validate := validator.New() err := validate.Struct(lend.Data) if err != nil { log.Print("e") log.Error().Err(err).Msg(err.Error()) server_handlers.FormatResponse(w, 400) _ = json.NewEncoder(w).Encode(responseBody{Status: "FAIL", Message: err.Error()}) return } file, handler, err := req.FormFile("PAN") log.Print("d") buf := new(bytes.Buffer) writer := multipart.NewWriter(buf) part, err := writer.CreateFormFile("PAN", handler.Filename) log.Print("c") if err != nil { log.Error().Err(err).Msg(err.Error()) server_handlers.FormatResponse(w, 400) _ = json.NewEncoder(w).Encode(responseBody{Status: "FAIL", Message: err.Error()}) return } fileBytes, err := ioutil.ReadAll(buf) part.Write(fileBytes) writer.Close() if err != nil { log.Print("Error Retrieving the File") log.Print(err) server_handlers.FormatResponse(w, 400) _ = json.NewEncoder(w).Encode(responseBody{Status: "FAIL", Message: err.Error()}) return } log.Print(handler.Filename) defer file.Close() //fileBytes, err := ioutil.ReadAll(part) if err != nil { log.Print(err) server_handlers.FormatResponse(w, 400) _ = json.NewEncoder(w).Encode(responseBody{Status: "FAIL", Message: err.Error()}) return } var uploadDocsDataResult UploadDocsDataResult body, err := callAPI(bytes.NewBuffer(fileBytes), fmt.Sprint("https://api-dev.lendbox.in/v1/partners/upload/docs?lbUserId=", lend.Data.LBUserId), "multipart/form-data") if err != nil{ log.Print(err.Error()) server_handlers.FormatResponse(w, 400) _ = json.NewEncoder(w).Encode(responseBody{Status: "FAIL", Message: err.Error()}) return } err = json.Unmarshal([]byte(body), &uploadDocsDataResult) if err != nil{ log.Print(err.Error()) server_handlers.FormatResponse(w, 400) _ = json.NewEncoder(w).Encode(responseBody{Status: "FAIL", Message: err.Error()}) return } if uploadDocsDataResult.Success == false { server_handlers.FormatResponse(w, 400) _ = json.NewEncoder(w).Encode(responseBody{Status: "FAIL", Message: uploadDocsDataResult.Msg}) return } server_handlers.FormatResponse(w, 200) _ = json.NewEncoder(w).Encode(responseBody{Status: "OK", Message: "Investor registered successfully"}) } } */ func InvestorBankDetails() http.HandlerFunc { return func(w http.ResponseWriter, req *http.Request) { w.Header().Set("Content-Type", "application/json") reqBody, _ := ioutil.ReadAll(req.Body) var lend BankDetails lend.Auth.ID = auth.GetAuth(req) err := json.Unmarshal(reqBody, &lend.Data) if err != nil { log.Print(err.Error()) } validate := validator.New() err = validate.Struct(lend.Data) if err != nil { log.Error().Err(err).Msg(err.Error()) server_handlers.FormatResponse(w, 400) _ = json.NewEncoder(w).Encode(responseBody{Status: "FAIL", Message: err.Error()}) return } _, err = lend.ShareBankDetails() if err != nil { log.Print(err.Error()) server_handlers.FormatResponse(w, 400) _ = json.NewEncoder(w).Encode(responseBody{Status: "FAIL", Message: err.Error()}) return } server_handlers.FormatResponse(w, 200) _ = json.NewEncoder(w).Encode(responseBody{Status: "OK", Message: "Investor registered successfully"}) } } func InitiateWalletOrder(walletOrder []WalletOrderData) (WalletOrderDataResult, error) { var walletOrderDataResult WalletOrderDataResult payload, err := json.Marshal(walletOrder) if err != nil { log.Print(err) return walletOrderDataResult, err } responseBody := strings.NewReader(string(payload)) body, err := callAPI(responseBody, fmt.Sprint("https://api-dev.lendbox.in/", "v1/partners/wallet/orders"), "application/json") if err != nil { log.Print(err.Error()) return walletOrderDataResult, err } err = json.Unmarshal([]byte(body), &walletOrderDataResult) if err != nil { log.Print(err.Error()) return walletOrderDataResult, err } if walletOrderDataResult.Success == false { log.Print(walletOrderDataResult.Msg) return walletOrderDataResult, errors.New(walletOrderDataResult.Msg) } //investorRegistrationDataResult, err = saveRegistrationDetails(manager, walletOrder.Result) if err != nil { return walletOrderDataResult, err } return walletOrderDataResult, nil } func (manager BankDetails) ShareBankDetails() (BankDetailsDataResult, error) { var bankDetailsDataResult BankDetailsDataResult //reqBodyBytes := new(bytes.Buffer) //json.NewEncoder(reqBodyBytes).Encode(bankDetailsData) //responseBody := bytes.NewBuffer(reqBodyBytes.Bytes()) log.Print(manager) payload, err := json.Marshal(manager.Data) if err != nil { log.Print(err) return bankDetailsDataResult, err } responseBody := strings.NewReader(string(payload)) body, err := callAPI(responseBody, fmt.Sprint(os.Getenv("LENDBOX_HOST"), "v1/partners/user/save-inv-bankdetails?lbUserId=", manager.Data.LBUserId), "application/json") if err != nil { log.Print(err.Error()) return bankDetailsDataResult, err } err = json.Unmarshal([]byte(body), &bankDetailsDataResult) if err != nil { log.Print(err.Error()) return bankDetailsDataResult, err } if bankDetailsDataResult.Success == false { log.Print(bankDetailsDataResult.Msg) return bankDetailsDataResult, errors.New(bankDetailsDataResult.Msg) } // bankDetailsDataResult, err = saveRegistrationDetails(manager, bankDetailsDataResult) // if err != nil { // return bankDetailsDataResult, err // } return bankDetailsDataResult, nil } func getInvestorBankDetails(manager BankDetails) (BankDetailsData, error) { tx, _, db := connection.Connect() var bankDetailsData BankDetailsData row := tx.QueryRow("select accountNumber, ifsc, holderName, accountType, bankName, branchName from bank_details where user_id = ?", manager.Auth.ID) err := row.Scan(&bankDetailsData.ID, &bankDetailsData.AccountNumber, &bankDetailsData.IFSC, &bankDetailsData.HolderName, &bankDetailsData.AccountType, &bankDetailsData.BankName, &bankDetailsData.BranchName) if err != nil { tx.Rollback() return bankDetailsData, errors.New("Not able to fetch the bank details") } if bankDetailsData.ID == 0 { return bankDetailsData, errors.New("Not able to fetch the bank details") } log.Print(bankDetailsData.ID) connection.Close(tx, db) return bankDetailsData, nil } func (manager InvestorRegistration) GetInvestorRegistrationDetails() (InvestorRegistration, error) { tx, _, db := connection.Connect() log.Print("GetInvestorRegistrationDetails: Data") log.Print("Auth: ", manager.Auth.ID) res, err := tx.Query("select users.id, COALESCE(`email`,'') as email, if(gender = 1, 'Mr.', 'Ms.') as title, COALESCE(`first_name`,'') as first_name, COALESCE(`last_name`,'') as last_name, COALESCE(`mobile_number`,'') as mobile_number, COALESCE(`dob`,'') as dob, COALESCE(`address`,'') as address, COALESCE(`city`,'') as city, COALESCE(`pincode`,'') as pincode, REPLACE(JSON_EXTRACT(IF (pvl.response is not null, pvl.response, ''), '$.pan'), '\"', '') as pan_card, COALESCE(`ip_address`, '') as ip_address, if(client is not null, (REPLACE(JSON_EXTRACT(COALESCE(`client`,''), '$.userAgent'), '\"', '')), '') as ua, if(client is not null, if(users.created_at is not null, users.created_at, ''), users.created_at) as created_at, COALESCE(`lb_user_id`,'') as lb_user_id from users left join pan_validation_logs pvl on users.id = pvl.user_id left join digital_sign_details dsd on users.id = dsd.user_id where users.id = ?", manager.Auth.ID) if err != nil { log.Print(err.Error()) tx.Rollback() return manager, err } var ID int64 var lbUserID string manager.Data.CountryCode = "IN" for res.Next() { err = res.Scan(&ID, &manager.Data.Email, &manager.Data.Title, &manager.Data.FirstName, &manager.Data.LastName, &manager.Data.Mobile, &manager.Data.DOB, &manager.Data.Street1, &manager.Data.City, &manager.Data.Pin, &manager.Data.PAN, &manager.Data.IP, &manager.Data.UA, &manager.Data.Timestamp, &lbUserID) if err != nil { tx.Rollback() log.Print(err.Error()) return manager, errors.New("Address already updated") } } if len(lbUserID) > 0 { connection.Close(tx, db) return manager, errors.New("Address already updated") } if len(manager.Data.DOB) > 0 { var dob, err = time.Parse("2006-01-02", manager.Data.DOB) if err != nil { log.Error().Err(err).Msg(err.Error()) } manager.Data.DOB = fmt.Sprint(dob.Unix()) } var timestamp, errCheck = time.Parse(time.RFC3339, strings.ReplaceAll(manager.Data.Timestamp, " ", "T")+"+00:00") if errCheck != nil { log.Print(errCheck) } log.Print(timestamp) manager.Data.Timestamp = fmt.Sprint(timestamp.Unix()) manager.Data.Street2 = manager.Data.City if ID == 0 { connection.Close(tx, db) return manager, errors.New("Couldn't update the address details. Pan Validation is pending") } connection.Close(tx, db) return manager, nil } func (manager BankDetails) GetLendboxBankDetails() (BankDetails, error) { tx, _, db := connection.Connect() log.Print("GetLendboxBankDetails: Data") log.Print("Auth: ", manager.Auth.ID) row := tx.QueryRow("select COALESCE(lb_user_id, '') as lb_user_id, COALESCE(account_number, ''), COALESCE(ifsc_code, ''), COALESCE(account_holder_name, ''), COALESCE(account_type, ''), COALESCE(bank_name, ''), COALESCE(branch_name, '') from users left join bank_details b on users.id = b.user_id where users.id = ?", manager.Auth.ID) err := row.Scan(&manager.Data.LBUserId, &manager.Data.AccountNumber, &manager.Data.IFSC, &manager.Data.HolderName, &manager.Data.AccountType, &manager.Data.BankName, &manager.Data.BranchName) if err != nil { log.Print(err.Error()) tx.Rollback() return manager, errors.New("Investor Id is not created") } if len(manager.Data.LBUserId) == 0 { connection.Close(tx, db) return manager, errors.New("Investor Id is not created") } manager.Data.AccountType = strings.ToUpper(manager.Data.AccountType) log.Print("manager.Data") log.Print(manager.Data) connection.Close(tx, db) return manager, nil } func (manager WalletOrderData) GetTransactionDetails(AccountId int64, ReferenceId string) (WalletOrderData, error) { tx, _, db := connection.Connect() log.Print("GetTransactionDetails: Data") log.Print("ReferenceId: ", ReferenceId) row := tx.QueryRow("select COALESCE(u.lb_user_id, '') as lb_user_id, COALESCE(a.initial_amount, '') as amount, COALESCE(a.account_id, '') as account_id, COALESCE(t.txn_id, '') as txnId, COALESCE(t.txn_date, '') as txn_date, if(s.scheme_type = 'FLEXI', 'CDF_FLEXI', 'CDF_FIXED') as investmentType, if(s.scheme_type = 'FIXED', if(tenure_duration = 6, 'CDF_3M_FIXED', if(tenure_duration = 12, 'CDF_6M_FIXED', if(tenure_duration = 24, 'CDF_12M_FIXED', 'CDF_3M_FIXED'))), 'CDF_3M_FIXED') as productType from creditcapital.transaction t left join creditcapital.account a on t.account_id = a.account_id left join creditcapital.scheme s on s.scheme_id = a.scheme_id left join creditcapital.users u on a.investor_id = u.id where t.txn_type = 'DEPOSIT' and t.status = 'SUCCESS' and t.reference_code = ? and t.account_id = ? and s.status = 'ACTIVE' and a.account_status = 'ACTIVE'", ReferenceId, AccountId) err := row.Scan(&manager.LBUserId, &manager.Amount, &manager.LoanId, &manager.TxId, &manager.TxTime, &manager.InvestmentType, &manager.ProductType) if err != nil { log.Print(err.Error()) tx.Rollback() return manager, errors.New("Transaction is not active") } if manager.LBUserId == 0 { connection.Close(tx, db) return manager, errors.New("Transaction is not active") } connection.Close(tx, db) return manager, nil } func getDate() time.Time { loc, _ := time.LoadLocation("Asia/Kolkata") dt := time.Now().In(loc) return dt }