123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433 |
- // Copyright 2019 getensh.com. All rights reserved.
- // Use of this source code is governed by getensh.com.
- package company
- import (
- "context"
- "encoding/json"
- "fmt"
- "git.getensh.com/common/gopkgs/database"
- "git.getensh.com/common/gopkgs/logger"
- "go.uber.org/zap"
- "google.golang.org/grpc/status"
- "property-company/errors"
- dbmodel "property-company/model"
- "property-company/parser"
- "property-company/pb"
- pb_v1 "property-company/pb/v1"
- "property-company/utils"
- "strings"
- "time"
- )
- var identityTypeM = map[string]string{
- "IDENTIFICATION_TYPE_IDCARD": "中国大陆居民-身份证",
- "IDENTIFICATION_TYPE_OVERSEA_PASSPORT": "其他国家或地区居民-护照",
- "IDENTIFICATION_TYPE_HONGKONG_PASSPORT": "中国香港居民-来往内地通行证",
- "IDENTIFICATION_TYPE_MACAO_PASSPORT": "中国澳门居民-来往内地通行证",
- "IDENTIFICATION_TYPE_TAIWAN_PASSPORT": "中国台湾居民-来往大陆通行证",
- }
- func checkSubjectLicenseInfo(req *pb_v1.CompanyWxAccountApplyRequest) error {
- license := req.SubjectInfo.BusinessLicenseInfo
- begin := checkDate(license.PeriodBegin)
- end := checkDate(license.PeriodEnd)
- switch {
- case license.LegalPerson == "":
- return status.Error(10003, "主体信息-营业执照:法人不能为空")
- case license.LicenseCopy == "" || license.LicenseCopyUrl == "":
- return status.Error(10003, "主体信息-营业执照:营业执照片不能为空")
- case license.LicenseNumber == "":
- return status.Error(10003, "主体信息-营业执照:统一社会信用码不能为空")
- case license.MerchantName == "":
- return status.Error(10003, "主体信息-营业执照:营业执照商户名不能为空")
- case license.LicenseAddress == "":
- return status.Error(10003, "主体信息-营业执照:营业执照注册地址不能为空")
- case begin == 0:
- return status.Error(10003, "主体信息-营业执照:营业执照开始时间错误")
- case license.PeriodEnd != "长期" && end == 0:
- return status.Error(10003, "主体信息-营业执照:营业执照结束时间错误")
- case license.PeriodEnd != "长期" && end < begin:
- return status.Error(10003, "主体信息-营业执照:营业执照结束时间或开始时间")
- }
- return nil
- }
- func checkSubjectIdentityInfo(req *pb_v1.CompanyWxAccountApplyRequest) error {
- identity := req.SubjectInfo.IdentityInfo
- if identity.IdDocInfo == nil {
- return status.Error(10003, "主体信息-法人信息:法人证件信息不能为空")
- }
- p := identity.IdDocInfo
- begin := checkDate(p.DocPeriodBegin)
- end := checkDate(p.DocPeriodEnd)
- switch {
- case identityTypeM[p.IdDocType] == "":
- return status.Error(10003, "主体信息-法人信息:不支持的证件类型")
- case begin == 0:
- return status.Error(10003, "主体信息-法人信息:证件开始时间错误")
- case p.DocPeriodEnd != "长期" && end == 0:
- return status.Error(10003, "主体信息-法人信息:证件结束时间错误")
- case p.DocPeriodEnd != "长期" && end < begin:
- return status.Error(10003, "主体信息-法人信息:证件结束时间或开始时间错误")
- case p.IdDocCopy == "" || p.IdDocCopyUrl == "":
- return status.Error(10003, "主体信息-法人信息:人像面照片不能为空")
- case (p.IdDocCopyBack == "" || p.IdDocCopyBackUrl == "") && p.IdDocType != "IDENTIFICATION_TYPE_OVERSEA_PASSPORT":
- return status.Error(10003, "主体信息-法人信息:除护照外证件背面不能为空")
- case p.IdDocName == "":
- return status.Error(10003, "主体信息-法人信息:证件姓名不能为空")
- case p.IdDocNumber == "":
- return status.Error(10003, "主体信息-法人信息:证件号不能为空")
- case p.IdDocAddress == "":
- return status.Error(10003, "主体信息-法人信息:证件地址不能为空")
- }
- return nil
- }
- func checkSubjectUboInfo(req *pb_v1.CompanyWxAccountApplyRequest) error {
- array := req.SubjectInfo.UboInfos
- for _, p := range array {
- begin := checkDate(p.DocPeriodBegin)
- end := checkDate(p.DocPeriodEnd)
- switch {
- case identityTypeM[p.IdDocType] == "":
- return status.Error(10003, "主体信息-受益人信息:收益人证件类型错误")
- case p.IdDocCopy == "" || p.IdDocCopyUrl == "":
- return status.Error(10003, "主体信息-受益人信息:证件正面不能为空")
- case (p.IdDocCopyBack == "" || p.IdDocCopyBackUrl == "") && p.IdDocType != "IDENTIFICATION_TYPE_OVERSEA_PASSPORT":
- return status.Error(10003, "主体信息-受益人信息:除护照外,证件背面不能为空")
- case p.IdDocName == "":
- return status.Error(10003, "主体信息-受益人信息:证件姓名不能为空")
- case p.IdDocNumber == "":
- return status.Error(10003, "主体信息-受益人信息:证件号不能为空")
- case p.IdDocAddress == "":
- return status.Error(10003, "主体信息-受益人信息:证件地址不能为空")
- case begin == 0:
- return status.Error(10003, "主体信息-受益人信息:证件开始时间错误")
- case p.DocPeriodEnd != "长期" && end == 0:
- return status.Error(10003, "主体信息-受益人信息:证件结束时间错误")
- case p.DocPeriodEnd != "长期" && end < begin:
- return status.Error(10003, "主体信息-受益人信息:证件开始时间或结束时间错误")
- }
- }
- return nil
- }
- func checkSubjectInfo(req *pb_v1.CompanyWxAccountApplyRequest) error {
- subject := req.SubjectInfo
- switch {
- case subject.SubjectType != "SUBJECT_TYPE_ENTERPRISE":
- return status.Error(10003, "主体类型错误")
- case subject.BusinessLicenseInfo == nil:
- return status.Error(10003, "营业执照信息不能为空")
- case subject.IdentityInfo == nil:
- return status.Error(10003, "法人身份信息不能为空")
- case !subject.IdentityInfo.Owner && len(subject.UboInfos) == 0:
- return status.Error(10003, "法人不是最终受益人需填写受益人资料")
- }
- if err := checkSubjectLicenseInfo(req); err != nil {
- return err
- }
- if err := checkSubjectIdentityInfo(req); err != nil {
- return err
- }
- if err := checkSubjectUboInfo(req); err != nil {
- return err
- }
- return nil
- }
- func checkBusinessInfo(req *pb_v1.CompanyWxAccountApplyRequest) error {
- p := req.BusinessInfo
- switch {
- case p.MerchantShortname == "":
- return status.Error(10003, "经营资料商户简称不能为空")
- case p.ServicePhone == "":
- return status.Error(10003, "经营资料客服电话不能为空")
- }
- return nil
- }
- func checkBankInfo(req *pb_v1.CompanyWxAccountApplyRequest) error {
- p := req.BankAccountInfo
- switch {
- case p.BankAccountType != "BANK_ACCOUNT_TYPE_CORPORATE":
- return status.Error(10003, "银行账户类型错误")
- case p.AccountName == "":
- return status.Error(10003, "开户名称不能为空")
- case p.AccountBank == "":
- return status.Error(10003, "开户银行不能为空")
- case p.AccountNumber == "":
- return status.Error(10003, "银行卡号(账号)不能为空")
- case p.BankAddressCode == "":
- return status.Error(10003, "开户银行省市编码不能为空")
- case p.BankName == "":
- return status.Error(10003, "开户银行全称不能为空")
- }
- return nil
- }
- func checkDate(data string) int64 {
- array := strings.Split(data, "-")
- if len(array) != 3 {
- return 0
- }
- t, err := time.ParseInLocation("2006-01-02", data, time.Local)
- if err != nil {
- return 0
- }
- if t.Format("2006-01-02") != data {
- return 0
- }
- return t.Unix()
- }
- func checkContactInfo(req *pb_v1.CompanyWxAccountApplyRequest) error {
- p := req.ContactInfo
- begin := checkDate(p.ContactPeriodBegin)
- end := checkDate(p.ContactPeriodEnd)
- switch {
- case p.ContactEmail == "":
- return status.Error(10003, "超管员邮箱不能为空")
- case p.MobilePhone == "":
- return status.Error(10003, "超管员手机号不能为空")
- case p.ContactType != "LEGAL" && p.ContactType != "SUPER":
- return status.Error(10003, "超管员类型不能为空")
- case p.ContactType == "SUPER" && identityTypeM[p.ContactIdDocType] == "":
- return status.Error(10003, "超管员为经办人时:证件类型错误")
- case p.ContactType == "SUPER" && (p.ContactIdDocCopy == "" || p.ContactIdDocCopyUrl == ""):
- return status.Error(10003, "超管员为经办人时:超管员证件正面不能为空")
- case p.ContactType == "SUPER" && (p.ContactIdDocCopyBack == "" || p.ContactIdDocCopyBackUrl == "") && p.ContactIdDocType != "IDENTIFICATION_TYPE_OVERSEA_PASSPORT":
- return status.Error(10003, "超管员为经办人时:除护照外,超管员证件背面不能为空")
- case p.ContactType == "SUPER" && p.ContactIdNumber == "":
- return status.Error(10003, "超管员为经办人时:证件号不能为空")
- case p.ContactType == "SUPER" && p.ContactName == "":
- return status.Error(10003, "超管员为经办人时:超管员证件证件姓名不能为空")
- case p.ContactType == "SUPER" && (p.BusinessAuthorizationLetter == "" || p.BusinessAuthorizationLetterUrl == ""):
- return status.Error(10003, "超管员为经办人时:业务办理授权函不能为空")
- case p.ContactType == "SUPER" && (begin == 0):
- return status.Error(10003, "超管员为经办人时:证件开始时间错误")
- case p.ContactType == "SUPER" && p.ContactPeriodEnd != "长期" && end == 0:
- return status.Error(10003, "超管员为经办人时:证件结束时间错误")
- case p.ContactType == "SUPER" && p.ContactPeriodEnd != "长期" && end < begin:
- return status.Error(10003, "超管员为经办人时:证件结束时间或开始时间错误")
- }
- return nil
- }
- func checkCompanyWxAccountApplyParam(req *pb_v1.CompanyWxAccountApplyRequest) error {
- switch {
- case req.Cid == 0:
- return status.Error(10003, "公司不能为空不能为空")
- case req.SubjectInfo == nil:
- return status.Error(10003, "主体资料不能为空")
- case req.BusinessInfo == nil:
- return status.Error(10003, "经营资料不能为空")
- case req.BankAccountInfo == nil:
- return status.Error(10003, "银行资料不能为空")
- case req.ContactInfo == nil:
- return status.Error(10003, "超管员信息不能为空")
- }
- if err := checkContactInfo(req); err != nil {
- return err
- }
- if err := checkSubjectInfo(req); err != nil {
- return err
- }
- if err := checkBusinessInfo(req); err != nil {
- return err
- }
- if err := checkBankInfo(req); err != nil {
- return err
- }
- return nil
- }
- func copyContactInfo(mreq *pb_v1.WxMerchantApplyRequest, req *pb_v1.CompanyWxAccountApplyRequest) {
- mreq.ContactInfo = &pb_v1.WxContactInfo{
- ContactType: req.ContactInfo.ContactType,
- ContactName: req.ContactInfo.ContactName,
- ContactIdDocType: req.ContactInfo.ContactIdDocType,
- ContactIdNumber: req.ContactInfo.ContactIdNumber,
- ContactIdDocCopy: req.ContactInfo.ContactIdDocCopy,
- ContactIdDocCopyBack: req.ContactInfo.ContactIdDocCopyBack,
- ContactPeriodBegin: req.ContactInfo.ContactPeriodBegin,
- ContactPeriodEnd: req.ContactInfo.ContactPeriodEnd,
- BusinessAuthorizationLetter: req.ContactInfo.BusinessAuthorizationLetter,
- MobilePhone: req.ContactInfo.MobilePhone,
- ContactEmail: req.ContactInfo.ContactEmail,
- }
- }
- func copySubjectInfo(mreq *pb_v1.WxMerchantApplyRequest, req *pb_v1.CompanyWxAccountApplyRequest) {
- mreq.SubjectInfo = &pb_v1.WxSubjectInfo{
- SubjectType: req.SubjectInfo.SubjectType,
- }
- mreq.SubjectInfo.UboInfos = make([]*pb_v1.WxUboInfo, len(req.SubjectInfo.UboInfos))
- for i, v := range req.SubjectInfo.UboInfos {
- mreq.SubjectInfo.UboInfos[i] = &pb_v1.WxUboInfo{
- UboIdDocType: v.IdDocType,
- UboIdDocCopy: v.IdDocCopy,
- UboIdDocCopyBack: v.IdDocCopyBack,
- UboIdDocAddress: v.IdDocAddress,
- UboIdDocName: v.IdDocName,
- UboIdDocNumber: v.IdDocNumber,
- UboPeriodBegin: v.DocPeriodBegin,
- UboPeriodEnd: v.DocPeriodEnd,
- }
- }
- mreq.SubjectInfo.BusinessLicenseInfo = &pb_v1.WxBusinessLicenseInfo{
- LicenseCopy: req.SubjectInfo.BusinessLicenseInfo.LicenseCopy,
- LicenseNumber: req.SubjectInfo.BusinessLicenseInfo.LicenseNumber,
- MerchantName: req.SubjectInfo.BusinessLicenseInfo.MerchantName,
- LegalPerson: req.SubjectInfo.BusinessLicenseInfo.LegalPerson,
- LicenseAddress: req.SubjectInfo.BusinessLicenseInfo.LicenseAddress,
- PeriodBegin: req.SubjectInfo.BusinessLicenseInfo.PeriodBegin,
- PeriodEnd: req.SubjectInfo.BusinessLicenseInfo.PeriodEnd,
- }
- mreq.SubjectInfo.IdentityInfo = &pb_v1.WxIdentityInfo{
- IdHolderType: "LEGAL",
- IdDocType: req.SubjectInfo.IdentityInfo.IdDocInfo.IdDocType,
- Owner: req.SubjectInfo.IdentityInfo.Owner,
- }
- if req.SubjectInfo.IdentityInfo.IdDocInfo.IdDocType == "IDENTIFICATION_TYPE_IDCARD" {
- mreq.SubjectInfo.IdentityInfo.IdCardInfo = &pb_v1.WxIdCardInfo{
- IdCardCopy: req.SubjectInfo.IdentityInfo.IdDocInfo.IdDocCopy,
- IdCardNational: req.SubjectInfo.IdentityInfo.IdDocInfo.IdDocCopyBack,
- IdCardNumber: req.SubjectInfo.IdentityInfo.IdDocInfo.IdDocNumber,
- CardPeriodBegin: req.SubjectInfo.IdentityInfo.IdDocInfo.DocPeriodBegin,
- CardPeriodEnd: req.SubjectInfo.IdentityInfo.IdDocInfo.DocPeriodEnd,
- IdCardName: req.SubjectInfo.IdentityInfo.IdDocInfo.IdDocName,
- IdCardAddress: req.SubjectInfo.IdentityInfo.IdDocInfo.IdDocAddress,
- }
- } else {
- mreq.SubjectInfo.IdentityInfo.IdDocInfo = &pb_v1.WxIdDocInfo{
- IdDocCopy: req.SubjectInfo.IdentityInfo.IdDocInfo.IdDocCopy,
- IdDocCopyBack: req.SubjectInfo.IdentityInfo.IdDocInfo.IdDocCopyBack,
- IdDocName: req.SubjectInfo.IdentityInfo.IdDocInfo.IdDocName,
- IdDocNumber: req.SubjectInfo.IdentityInfo.IdDocInfo.IdDocNumber,
- DocPeriodBegin: req.SubjectInfo.IdentityInfo.IdDocInfo.DocPeriodBegin,
- DocPeriodEnd: req.SubjectInfo.IdentityInfo.IdDocInfo.DocPeriodEnd,
- IdDocAddress: req.SubjectInfo.IdentityInfo.IdDocInfo.IdDocAddress,
- }
- }
- }
- func copyBankInfo(mreq *pb_v1.WxMerchantApplyRequest, req *pb_v1.CompanyWxAccountApplyRequest) {
- mreq.BankAccountInfo = &pb_v1.WxBankAccountInfo{
- AccountName: req.BankAccountInfo.AccountName,
- AccountBank: req.BankAccountInfo.AccountBank,
- BankAddressCode: req.BankAccountInfo.BankAddressCode,
- BankBranchId: req.BankAccountInfo.BankBranchId,
- BankName: req.BankAccountInfo.BankName,
- AccountNumber: req.BankAccountInfo.AccountNumber,
- BankAccountType: req.BankAccountInfo.BankAccountType,
- }
- }
- func copyBusinessInfo(mreq *pb_v1.WxMerchantApplyRequest, req *pb_v1.CompanyWxAccountApplyRequest) {
- mreq.BusinessInfo = &pb_v1.WxBusinessInfo{
- MerchantShortname: req.BusinessInfo.MerchantShortname,
- ServicePhone: req.BusinessInfo.ServicePhone,
- }
- }
- //
- func CompanyWxAccountApply(ctx context.Context, req *pb_v1.CompanyWxAccountApplyRequest) (reply *pb_v1.CompanyWxAccountApplyReply, err error) {
- reply = &pb_v1.CompanyWxAccountApplyReply{}
- // 捕获各个task中的异常并返回给调用者
- defer func() {
- if r := recover(); r != nil {
- err = fmt.Errorf("%+v", r)
- e := &status.Status{}
- if er := json.Unmarshal([]byte(err.Error()), e); er != nil {
- logger.Error("err",
- zap.String("system_err", err.Error()),
- zap.Stack("stacktrace"))
- }
- }
- }()
- err = checkCompanyWxAccountApplyParam(req)
- if err != nil {
- return nil, err
- }
- businessCode := fmt.Sprintf("%s_%d_%d_%s",
- parser.Conf.ThirdParty.Wx.AppletMchId, req.Cid, time.Now().Unix(), utils.GenerateRandomStr(16, "mix"))
- // 先插入记录
- db := database.DB().Begin()
- p := dbmodel.TWxMerchantInfo{}
- p.Cid = req.Cid
- p.BusinessCode = businessCode
- p.CreatedAt = time.Now()
- p.UpdatedAt = time.Now()
- bytes, _ := json.Marshal(req.SubjectInfo)
- p.SubjectInfo = string(bytes)
- bytes, _ = json.Marshal(req.BusinessInfo)
- p.BusinessInfo = string(bytes)
- bytes, _ = json.Marshal(req.BankAccountInfo)
- p.BankAccountInfo = string(bytes)
- bytes, _ = json.Marshal(req.ContactInfo)
- p.ContactInfo = string(bytes)
- p.StateMsg = "准备中"
- p.State = "APPLYMENT_STATE_PREPARE"
- if err = p.Insert(db); err != nil {
- db.Rollback()
- return nil, errors.DataBaseError
- }
- if p.ID == 0 {
- db.Rollback()
- return nil, errors.DataBaseError
- }
- // 调三方接口进件
- mreq := &pb_v1.WxMerchantApplyRequest{}
- mreq.BusinessCode = businessCode
- copyContactInfo(mreq, req)
- copySubjectInfo(mreq, req)
- copyBankInfo(mreq, req)
- copyBusinessInfo(mreq, req)
- mreply, err := pb.Thirdparty.WxMerchantApply(ctx, mreq)
- if err != nil {
- db.Rollback()
- return nil, err
- }
- db.Commit()
- // 更新记录
- where := map[string]interface{}{
- "id": p.ID,
- }
- values := map[string]interface{}{
- "apply_id": mreply.ApplymentId,
- "state": "APPLYMENT_STATE_AUDITING",
- }
- // 此处不管失败情况
- _ = p.Update(database.DB(), where, values)
- utils.RobotMsg(fmt.Sprintf("微信商户(%s)提交审核,请关注", req.BusinessInfo.MerchantShortname))
- return reply, nil
- }
|