1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127 |
- # -*- coding: utf-8 -*-
- #!/usr/bin/env python
- import requests
- from typing import TYPE_CHECKING, Optional
- import datetime
- import logging
- import os
- import random
- from django.conf import settings
- from mongoengine import StringField, EmbeddedDocument, EmbeddedDocumentField, DateTimeField, IntField, MapField, \
- BooleanField, LazyReferenceField, EmbeddedDocumentListField
- from apilib.monetary import JDMerchantPermillage
- from apps.web.core import ROLE
- from apps.web.core.db import Searchable, JDMerchantPermillageField
- from apps.web.core.file import AliOssFileUploader
- from apps.web.core.models import JDOpenPayApp, CustomerPayRelation, JDAggrePayApp
- from apps.web.merchant.constant import COMPANY_TYPE, PRIATE_OR_PUBLIC, MerchantStatus, ProductType, ProductStatus, \
- ProductRateType, DEFAULT_TRADE_FEE, WechatSubjectType, IdentificationType, CertType, MicroBizType, MERCHANT_OWNER_ROLE, MerchantVersion, MerchantLogAction, ContactType, \
- JdOpenMerchantType, JdOpenMerchantStatus
- from apps.web.merchant.signal import merchant_user_submit, merchant_jd_access, create_customer_success, create_settle_success, create_shop_success, upload_attach_success, \
- complete_success, merchant_enter
- from library.jdopen.constants import OPEN_SECRET_KEY, OPEN_ACCESS_KEY
- if TYPE_CHECKING:
- from apps.web.core.bridge.wechat.v3api import WechatApiProxy
- from apps.web.dealer.models import Dealer
- from apps.web.agent.models import Agent
- logger = logging.getLogger(__name__)
- class MerchantLog(Searchable):
- """
- 商户的日志表
- """
- merchantId = StringField(verbose_name=u"商户的ID")
- action = StringField(verbose_name="u操作动作", choices=MerchantLogAction.choices())
- dateTimeAdded = DateTimeField(verbose_name=u"操作时间", default=datetime.datetime.now)
- description = StringField(verbose_name=u"描述")
- meta = {
- 'collection': 'merchant_log',
- 'db_alias': 'logdata'
- }
- @classmethod
- def create_one(cls, merchantId, action, description=""):
- cls(
- merchantId=merchantId,
- action=action,
- description=description
- ).save()
- @classmethod
- def submit(cls, merchantId, description=""):
- """
- 创建 提交/修改数据完毕 的记录
- """
- return cls.create_one(
- merchantId, MerchantLogAction.SUBMIT, str(description)
- )
- @classmethod
- def add_app(cls, merchantId, description=""):
- return cls.create_one(
- merchantId, MerchantLogAction.ADD_JD_APP, str(description)
- )
- @classmethod
- def change_pay_type(cls, merchantId, description=""):
- return cls.create_one(
- merchantId, MerchantLogAction.CHANGE_PAY_APP, str(description)
- )
- @classmethod
- def submit_wechat(cls, merchantId, description=""):
- return cls.create_one(
- merchantId, MerchantLogAction.SUBMIT_WECHAT, str(description)
- )
- @classmethod
- def submit_ali(cls, merchantId, description=""):
- return cls.create_one(
- merchantId, MerchantLogAction.SUBMIT_ALI, str(description)
- )
- @classmethod
- def auth_apply_success(cls, merchantId, description=""):
- return cls.create_one(
- merchantId, MerchantLogAction.AUTH_APPLY_SUCCESS, str(description)
- )
- @classmethod
- def fail(cls, merchantId, description=""):
- return cls.create_one(
- merchantId, MerchantLogAction.FAIL, str(description)
- )
- class MerchantAgent(Searchable):
- """
- 将商户号 和 代理商账号绑定起来 这样方便 代理商收取手续费的时候 直接从相应的网关获取
- """
- agentNo = StringField(verbose_name="商户号的服务商商户号")
- agentId = StringField(verbose_name="服务商的agentId", default="")
- agentSystemId = StringField(verbose_name="服务商的systemId", default="")
- dateTimeAdded = DateTimeField(verbose_name="添加进来的时间")
- def __str__(self):
- return self.agentNo
- @classmethod
- def get_agent_id(cls, agentSystemId):
- merchantAgent = cls.objects.filter(agentSystemId=agentSystemId).first() or cls()
- return merchantAgent.agentId
- @classmethod
- def default_merchant_agent(cls):
- wflSystemId = os.environ.get("JD_SYSTEM_ID") or "112122276PSP"
- return cls.objects.filter(agentSystemId=wflSystemId).first()
- class LadderList(EmbeddedDocument):
- type = StringField(default="1")
- minVal = StringField(default="0")
- maxVal = StringField(default="1000")
- cardType = StringField(default="DE")
- fee = JDMerchantPermillageField(default=JDMerchantPermillage(DEFAULT_TRADE_FEE))
- maxfee = StringField("1000000")
- def to_dict(self):
- return {
- "type": self.type,
- "minVal": self.minVal,
- "maxVal": self.maxVal,
- "cardType": self.cardType,
- "fee": self.fee,
- "maxfee": self.maxfee
- }
- class MerchantProduct(EmbeddedDocument):
- productId = StringField(verbose_name=u"产品编码", choices=ProductType.choices())
- status = IntField(verbose_name=u"产品的开通状态", choices=ProductStatus.choices(), default=ProductStatus.INIT)
- rateType = StringField(verbose_name=u"产品的费率类型", choices=ProductRateType.choices(), default=ProductRateType.PERCENTAGE)
- mfee = JDMerchantPermillageField(verbose_name=u"产品的费率 一般就是之前经销商的提现的费率 由代理商设置 需要注意的是发送给金东的时候 单位是100%", default=JDMerchantPermillage(6))
- payToolId = StringField(verbose_name=u"支付工具的ID 固定值", default="0")
- # ladderList = ListField(verbose_name = u'京东的固定的费率(只有当产品id是403的时候这个字段才有用)')
- ladderList = EmbeddedDocumentField(verbose_name = u'京东的固定的费率(只有当产品id是403的时候这个字段才有用)', document_type=LadderList)
- def support_apply(self):
- """
- 产品是否支持开通 主要看状态 初始化的产品可以开通
- """
- return self.status == ProductStatus.INIT
- def to_wait(self):
- self.status = ProductStatus.WAITING
- self.save()
- def to_fail(self):
- self.status = ProductStatus.FAIL
- self.save()
- def to_success(self):
- self.status = ProductStatus.SUCCESS
- self.save()
- @classmethod
- def created_product(cls, productId, mfee):
- product = cls(productId=productId)
- product.mfee = mfee
- # jd 的支付方式 加上费率阶梯
- if product.productId == ProductType.JD:
- ladderMap = LadderList()
- ladderMap.fee = mfee
- product.ladderList = ladderMap
- return product
- class MerchantAddress(Searchable):
- name = StringField(verbose_name=u"行政区名称", required=True)
- code = StringField(verbose_name=u"行政区代码", required=True)
- parentCode = StringField(verbose_name=u"父级code")
- def to_dict(self):
- result = {
- "name": self.name,
- "code": self.code,
- }
- if self.parentCode != "000000":
- result.update({"parentCode": self.parentCode})
- return result
- @classmethod
- def get_name(cls, code):
- record = cls.objects.filter(code=code).first()
- return record.name if record else ""
- @classmethod
- def get_all(cls):
- return [_addr.to_dict() for _addr in cls.objects.all()]
- @classmethod
- def get_addr_by_parent(cls, parentCode=None):
- if parentCode is None:
- parentCode = "000000"
- return [_addr.to_dict() for _addr in cls.objects.filter(parentCode=parentCode)]
- @classmethod
- def get_provide_code(cls, provinceName):
- """
- 获取省级code
- """
- try:
- province = cls.objects.get(name=provinceName, parentCode="000000") # type: MerchantAddress
- except Exception as e:
- logger.error("get province <{}> code error = {}".format(provinceName, e))
- return ""
- return province.code
- @classmethod
- def get_city_code(cls, cityName, provinceCode):
- try:
- city = cls.objects.get(name=cityName, parentCode=provinceCode) # type: MerchantAddress
- except Exception as e:
- logger.error("get province <{}> city <{}> code error = {}".format(provinceCode, cityName, e))
- return ""
- return city.code
- @classmethod
- def get_area_code(cls, areaName, cityCode):
- try:
- area = cls.objects.get(name=areaName, parentCode=cityCode) # type: MerchantAddress
- except Exception as e:
- logger.error("get city <{}> area <{}> code error = {}".format(cityCode, areaName, e))
- return ""
- return area.code
- class WxMerchantAddress(Searchable):
- name = StringField(verbose_name=u"地址")
- code = StringField(verbose_name=u"编码")
- @classmethod
- def get_code(cls, name):
- try:
- return cls.objects.get(name=name).code
- except Exception:
- return "440305"
- # 营业执照信息
- class BusinessLicenceInfo(EmbeddedDocument):
- """营业执照"""
- licenceNumber = StringField(verbose_name=u"营业执照注册号")
- licenceCopy = StringField(verbose_name=u"营业执照照片URL")
- merchantName = StringField(verbose_name=u"商户简称")
- legalPerson = StringField(verbose_name=u"法人姓名")
- companyAddress = StringField(verbose_name=u"注册地址")
- licenceStart = StringField(verbose_name=u"营业执照起始日期")
- licenceEnd = StringField(verbose_name=u"营业执照结束日期")
- def to_apply(self, server): # type:(WechatApiProxy) -> dict
- licenceCopy = AliOssFileUploader.load(self.licenceCopy)
- response = server.upload_image(licenceCopy, os.path.basename(self.licenceCopy))
- return {
- "licence_number": self.licenceNumber,
- "licence_copy": response.get("media_id", ""),
- "merchant_name": self.merchantName,
- "legal_person": self.legalPerson,
- "company_address": self.companyAddress,
- "licence_valid_date": '["{}","{}"]'.format(self.licenceStart, self.licenceEnd),
- }
- def save_certificate_info(self, businessLicenceInfo):
- self.licenceNumber = businessLicenceInfo["busCode"]
- self.licenceCopy = businessLicenceInfo["busLicenseUrl"]
- self.merchantName = businessLicenceInfo["busName"]
- self.legalPerson = businessLicenceInfo["busLegal"]
- self.companyAddress = "{}{}{}{}".format(
- businessLicenceInfo["province"]["name"],
- businessLicenceInfo["city"]["name"],
- businessLicenceInfo["area"]["name"],
- businessLicenceInfo["addr"],
- )
- self.licenceStart = businessLicenceInfo["startTime"]
- self.licenceEnd = businessLicenceInfo["endTime"]
- # 登记证书信息
- class CertificateInfo(EmbeddedDocument):
- """登记证书"""
- certType = StringField(verbose_name=u"登记证书类型", choices=CertType.choices())
- certNumber = StringField(verbose_name=u"证书编号")
- certCopy = StringField(verbose_name=u"证书的照片URL")
- merchantName = StringField(verbose_name=u"商户简称")
- legalPerson = StringField(verbose_name=u"法人姓名")
- companyAddress = StringField(verbose_name=u"注册地址")
- certStart = StringField(verbose_name=u"证书起始日期")
- certEnd = StringField(verbose_name=u"证书结束日期")
- def to_apply(self, server): # type:(WechatApiProxy) -> dict
- certCopy = AliOssFileUploader.load(self.certCopy)
- response = server.upload_image(certCopy, os.path.basename(self.certCopy))
- return {
- "cert_type": self.certType,
- "cert_number": self.certNumber,
- "cert_copy": response.get("media_id", ""),
- "merchant_name": self.merchantName,
- "legal_person": self.legalPerson,
- "company_address": self.companyAddress,
- "cert_valid_date": '["{}","{}"]'.format(self.certStart, self.certEnd),
- }
- # 辅助材料信息
- class AssistProveInfo(EmbeddedDocument):
- """辅助材料证明"""
- microBizType = StringField(verbose_name=u"小微商户类型", default=MicroBizType.MICRO_TYPE_STORE.code, choices=MicroBizType.choices())
- storeName = StringField(verbose_name=u"门店名称")
- # 省市县 以,分割
- storeAddressCode = StringField(verbose_name=u"门店的地址的code")
- storeAddress = StringField(verbose_name=u"门店的地址 具体区、街道")
- storeHeaderCopy = StringField(verbose_name=u"门头照")
- storeIndoorCopy = StringField(verbose_name=u"门内照")
- @staticmethod
- def load_addr_code(p, c, a):
- return WxMerchantAddress.get_code("{}{}{}".format(p, c, a))
- def to_apply(self, server): # type:(WechatApiProxy) -> dict
- storeHeaderCopy = AliOssFileUploader.load(self.storeHeaderCopy)
- responseHeader = server.upload_image(storeHeaderCopy, os.path.basename(self.storeHeaderCopy))
- storeIndoorCopy = AliOssFileUploader.load(self.storeIndoorCopy)
- responseIndoor = server.upload_image(storeIndoorCopy, os.path.basename(self.storeIndoorCopy))
- return {
- "micro_biz_type": self.microBizType,
- "store_name": self.storeName,
- "store_address_code": self.storeAddressCode,
- "store_address": self.storeAddress,
- "store_header_copy": responseHeader.get("media_id"),
- "store_indoor_copy": responseIndoor.get("media_id")
- }
- def save_certificate_info(self, assistProveInfo):
- self.storeName = assistProveInfo["storeShotName"]
- self.storeHeaderCopy = assistProveInfo["storeAUrl"]
- self.storeIndoorCopy = assistProveInfo["storeBUrl"]
- province = assistProveInfo["province"]["name"]
- city = assistProveInfo["city"]["name"]
- area = assistProveInfo["area"]["name"]
- self.storeAddress = assistProveInfo["addr"]
- self.storeAddressCode = self.load_addr_code(province, city, area)
- return self
- # 法人相关信息
- class LegalPersonInfo(EmbeddedDocument):
- """
- 法人信息
- """
- mainType = StringField(verbose_name=u"法人证件类型(目前仅支持身份证)", default=IdentificationType.IDENTIFICATION_TYPE_IDCARD.code, choices=IdentificationType.choices())
- lepName = StringField(verbose_name=u"法人姓名")
- lepCardNo = StringField(verbose_name=u"法人身份证号")
- lepCardStart = StringField(verbose_name=u"法人身份证起始日期")
- lepCardEnd = StringField(verbose_name=u"法人身份证结束日期")
- lepCardUrlA = StringField(verbose_name=u"法人身份证人像面")
- lepCardUrlB = StringField(verbose_name=u"法人身份证国徽面")
- # 以下都是不需要的
- lepProvinceCode = StringField(verbose_name=u"法人身份证 省CODE")
- lepCityCode = StringField(verbose_name=u"法人身份证 市CODE")
- lepAreaCode = StringField(verbose_name=u"法人身份证 区CODE")
- lepProvince = StringField(verbose_name=u"法人身份证 省")
- lepCity = StringField(verbose_name=u"法人身份证 市")
- lepArea = StringField(verbose_name=u"法人身份证 区")
- lepAddr = StringField(verbose_name=u"法人地址 详细")
- def to_apply(self, server): # type:(WechatApiProxy) -> dict
- """
- 法人的有三个信息需要加密处理 两个图片信息需要上传处理
- """
- # 上传图片 并获取其中的 media_id
- lepCardContentA = AliOssFileUploader.load(self.lepCardUrlA)
- responseA = server.upload_image(lepCardContentA, os.path.basename(self.lepCardUrlA))
- lepCardContentB = AliOssFileUploader.load(self.lepCardUrlB)
- responseB = server.upload_image(lepCardContentB, os.path.basename(self.lepCardUrlB))
- return {
- "identification_type": self.mainType,
- "identification_name": server.rsa_encrypt(self.lepName),
- "identification_number": server.rsa_encrypt(self.lepCardNo),
- "identification_address": server.rsa_encrypt("{}{}{}{}".format(self.lepProvince, self.lepCity, self.lepArea, self.lepAddr)),
- "identification_valid_date": '["{}","{}"]'.format(self.lepCardStart, self.lepCardEnd),
- "identification_front_copy": responseA.get("media_id", ""),
- "identification_back_copy": responseB.get("media_id", ""),
- "owner": True
- }
- def save_certificate_info(self, legalInfo):
- self.lepName = legalInfo["name"]
- self.lepCardNo = legalInfo["cardNo"]
- self.lepCardStart = legalInfo["startTime"]
- self.lepCardEnd = legalInfo["endTime"]
- self.lepCardUrlA = legalInfo["urlA"]
- self.lepCardUrlB = legalInfo["urlB"]
- self.lepProvinceCode = legalInfo["province"]["code"]
- self.lepCityCode = legalInfo["city"]["code"]
- self.lepAreaCode = legalInfo["area"]["code"]
- self.lepProvince = legalInfo["province"]["name"]
- self.lepCity = legalInfo["city"]["name"]
- self.lepArea = legalInfo["area"]["name"]
- self.lepAddr = legalInfo["addr"]
- return self
- # 经营主体相关信息
- class SubjectInfo(EmbeddedDocument):
- """
- 主体信息 最为关键的信息 主要是种类繁多 根据主体的类型会有变化
- """
- mainType = StringField(verbose_name=u"主体的类型", choices=WechatSubjectType.choices())
- businessLicenceInfo = EmbeddedDocumentField(verbose_name="营业执照信息" ,document_type=BusinessLicenceInfo)
- certificateInfo = EmbeddedDocumentField(verbose_name=u"登记证书信息", document_type=CertificateInfo)
- companyProveCopy = StringField(verbose_name=u"单位证明函照片")
- assistProveInfo = EmbeddedDocumentField(verbose_name=u"辅助材料证明", document_type=AssistProveInfo)
- def to_apply(self, server): # type:(WechatApiProxy) -> dict
- data = {
- "subject_type": self.mainType,
- }
- # 存在营业执照信息 企业类型
- if self.businessLicenceInfo:
- data["business_licence_info"] = self.businessLicenceInfo.to_apply(server)
- # 登记证书 事业单位和其他组织都需要
- if self.certificateInfo:
- data["certificate_info"] = self.certificateInfo.to_apply(server)
- # 事业单位必带
- if self.companyProveCopy:
- companyProveCopy = AliOssFileUploader.load(self.companyProveCopy)
- response = server.upload_image(companyProveCopy, os.path.basename(self.companyProveCopy))
- data["company_prove_copy"] = response.get("media_id", "")
- # 小微企业必须有
- if self.assistProveInfo:
- data["assist_prove_info"] = self.assistProveInfo.to_apply(server)
- return data
- def save_certificate_info(self, businessLicenceInfo=None, certificateInfo=None, companyProveCopy=None, assistProveInfo=None):
- if businessLicenceInfo:
- self.businessLicenceInfo = self.businessLicenceInfo or BusinessLicenceInfo()
- return self.businessLicenceInfo.save_certificate_info(businessLicenceInfo)
- elif certificateInfo:
- self.certificateInfo = self.certificateInfo or CertificateInfo()
- return self.certificateInfo.save_certificate_info(certificateInfo)
- elif companyProveCopy:
- self.companyProveCopy = companyProveCopy
- else:
- self.assistProveInfo = self.assistProveInfo or AssistProveInfo()
- return self.assistProveInfo.save_certificate_info(assistProveInfo)
- # 联系人相关信息
- class ContactPersonInfo(EmbeddedDocument):
- """
- 联系人信息
- """
- mainType = StringField(verbose_name=u"联系人证件类型(目前仅支持身份证)", default=IdentificationType.IDENTIFICATION_TYPE_IDCARD.code, choices=IdentificationType.choices())
- contactType = StringField(verbose_name=u"联系人的类型", choices=ContactType.choices(), default=ContactType.LEGAL.code)
- businessAuthorizationLetter = StringField(verbose_name="业务办理授权函", default="")
- contactName = StringField(verbose_name=u"联系人姓名")
- contactMobile = StringField(verbose_name=u"联系人手机号")
- contactCardNo = StringField(verbose_name=u"联系人身份证号")
- # 以下四个信息是保存供显示 并不发送到微信
- contactCardStart = StringField(verbose_name=u"联系人身份证起始日期")
- contactCardEnd = StringField(verbose_name=u"联系人身份证结束日期")
- contactCardUrlA = StringField(verbose_name=u"联系人身份证人像面")
- contactCardUrlB = StringField(verbose_name=u"联系人身份证国徽面")
- contactProvinceCode = StringField(verbose_name=u"联系人身份证 省CODE")
- contactCityCode = StringField(verbose_name=u"联系人身份证 市CODE")
- contactAreaCode = StringField(verbose_name=u"联系人身份证 区CODE")
- contactProvince = StringField(verbose_name=u"联系人身份证 省")
- contactCity = StringField(verbose_name=u"联系人身份证 市")
- contactArea = StringField(verbose_name=u"联系人身份证 区")
- contactAddr = StringField(verbose_name=u"联系人地址 详细")
- def to_apply(self, server): # type:(WechatApiProxy) -> dict
- """
- 联系人的三个信息都需要加密进行处理
- """
- baseData = {
- "contact_type": str(self.contactType),
- "name": server.rsa_encrypt(self.contactName),
- "mobile": server.rsa_encrypt(self.contactMobile),
- "id_card_number": server.rsa_encrypt(self.contactCardNo)
- }
- if self.contactType == ContactType.SUPER:
- baseData["contact_id_doc_type"] = str(self.mainType)
- baseData["contact_id_doc_copy"] = server.upload_image_from_oss(self.contactCardUrlA).get("media_id", "")
- baseData["contact_id_doc_copy_back"] = server.upload_image_from_oss(self.contactCardUrlB).get("media_id", "")
- baseData["contact_period_begin"] = self.contactCardStart
- baseData["contact_period_end"] = self.contactCardEnd
- baseData["business_authorization_letter"] = server.upload_image_from_oss(self.businessAuthorizationLetter).get("media_id", "")
- return baseData
- def save_certificate_info(self, contactInfo):
- self.contactType = contactInfo["contactType"]
- self.businessAuthorizationLetter = contactInfo["businessAuthorizationLetter"]
- self.contactName = contactInfo["name"]
- self.contactCardNo = contactInfo["cardNo"]
- self.contactCardStart = contactInfo["startTime"]
- self.contactCardEnd = contactInfo["endTime"]
- self.contactCardUrlA = contactInfo["urlA"]
- self.contactCardUrlB = contactInfo["urlB"]
- self.contactProvinceCode = contactInfo["province"]["code"]
- self.contactCityCode = contactInfo["city"]["code"]
- self.contactAreaCode = contactInfo["area"]["code"]
- self.contactProvince = contactInfo["province"]["name"]
- self.contactCity = contactInfo["city"]["name"]
- self.contactArea = contactInfo["area"]["name"]
- self.contactAddr = contactInfo["addr"]
- return self
- def save_mobile_info(self, mobile):
- self.contactMobile = mobile
- return self
- # 商户的实名申请信息
- class WechatApplyMerchant(Searchable):
- """
- 微信侧申请商户号所需要的资料
- """
- # 原始的资料信息
- contactInfo = EmbeddedDocumentField(verbose_name = u"联系人信息", document_type = ContactPersonInfo, default=ContactPersonInfo)
- legalInfo = EmbeddedDocumentField(verbose_name = u"法人信息", document_type = LegalPersonInfo, default=LegalPersonInfo)
- subjectInfo = EmbeddedDocumentField(verbose_name = u"经营主体信息", document_type = SubjectInfo, default=SubjectInfo)
- # 微信的业务申请信息
- channelId = StringField(verbose_name=u"渠道商户号")
- subMerchantId = StringField(verbose_name=u"微信子商户编号")
- applymentId = StringField(verbose_name=u"申请的ID")
- businessCode = StringField(verbose_name=u"业务申请编号")
- # 支付宝的业务申请信息
- subAliMerchantId = StringField(verbose_name=u"支付宝的子商编")
- aliApplymentId = StringField(verbose_name=u"支付宝的申请编号")
- aliBusinessCode = StringField(verbose_name=u"支付宝的业务编号")
- def update_sub_merchant(self, **kwargs):
- if "channel" in kwargs:
- self.channelId = kwargs["channel"]
- if "subMchId" in kwargs:
- self.subMerchantId = kwargs["subMchId"]
- if "subCustomerNum" in kwargs:
- self.subAliMerchantId = kwargs["subCustomerNum"]
- return self.save()
- def to_apply(self, server): # type:(WechatApiProxy) -> dict
- # 申请的时候 申请单编号刷新
- business_code = "{}_{}_{}".format(self.channelId, self.subMerchantId, datetime.datetime.now().strftime("%Y%m%d%H%M%S"))
- self.businessCode = business_code
- self.save()
- # 获取联系人类型 小微商户和个人卖家 则联系人类型为法人;其余的 可选法人 或 经办人
- if self.subjectInfo.mainType == WechatSubjectType.SUBJECT_TYPE_MICRO:
- contact_type = "LEGAL"
- else:
- if self.contactInfo.contactCardNo == self.legalInfo.lepCardNo:
- contact_type = "LEGAL"
- else:
- contact_type = "SUPER"
- # 根据联系人的类型 决定上传数据的不同
- if contact_type == "LEGAL":
- contact_info = {
- "contact_type": contact_type,
- "name": server.rsa_encrypt(self.contactInfo.contactName),
- "mobile": server.rsa_encrypt(self.contactInfo.contactMobile),
- "id_card_number": server.rsa_encrypt(self.contactInfo.contactCardNo)
- }
- else:
- contact_info = {
- "contact_type": contact_type,
- "name": server.rsa_encrypt(self.contactInfo.contactName),
- "contact_id_doc_type": IdentificationType.IDENTIFICATION_TYPE_IDCARD.code,
- "id_card_number": server.rsa_encrypt(self.contactInfo.contactCardNo),
- "contact_id_doc_copy": server.upload_image_from_oss(self.contactInfo.contactCardUrlA).get("media_id", ""),
- "contact_id_doc_copy_back": server.upload_image_from_oss(self.contactInfo.contactCardUrlB).get("media_id", ""),
- "contact_period_begin": self.contactInfo.contactCardStart,
- "contact_period_end": self.contactInfo.contactCardEnd,
- "business_authorization_letter": server.upload_image_from_oss(self.contactInfo.businessAuthorizationLetter).get("media_id", ""),
- "mobile": server.rsa_encrypt(self.contactInfo.contactMobile)
- }
- return {
- "channel_id": self.channelId,
- "business_code": business_code,
- "contact_info": contact_info,
- "subject_info": self.subjectInfo.to_apply(server),
- "identification_info": self.legalInfo.to_apply(server),
- "addition_info": {
- "confirm_mchid_list": [self.subMerchantId]
- }
- }
- def to_ali_submit(self, applymentId, businessCode=""):
- self.aliApplymentId = str(applymentId)
- if businessCode:
- self.aliBusinessCode = businessCode
- return self.save()
- def to_wechat_submit(self, applymentId, businessCode=""):
- self.applymentId = str(applymentId)
- if businessCode:
- self.businessCode = businessCode
- return self.save()
- def to_success(self, applymentId, businessCode=""):
- """
- 申请成功之后 写入申请单的编号
- """
- def to_cancel(self):
- """
- 取消申请单成功后 将此次申请的参数全部清除
- """
- self.applymentId = ""
- self.businessCode = ""
- return self.save()
- # 京东商户申请所需信息
- class MerchantSourceInfo(Searchable):
- """
- 京东申请所需要的材料
- """
- ownerId = StringField(verbose_name=u"商户拥有者的ID")
- ownerRole = StringField(verbose_name=u"商户拥有者身份", choices=MERCHANT_OWNER_ROLE.choices(), default=MERCHANT_OWNER_ROLE.DEALER)
- merchantAgent = LazyReferenceField(verbose_name="商户号的服务商", document_type=MerchantAgent )
- serial_no = StringField(verbose_name=u"订单流水号")
- merchantNo = StringField(verbose_name=u"商户号")
- desKey = StringField(verbose_name=u"商户密钥")
- mdKey = StringField(verbose_name=u"商户md")
- status = IntField(verbose_name=u"商户的状态", choices=MerchantStatus.choices(), default=MerchantStatus.INIT)
- merchantType = StringField(verbose_name=u"商户性质", choices=COMPANY_TYPE.choices())
- errorDescription = StringField(verbose_name=u"失败原因", default="")
- dateTimeAdded = DateTimeField(verbose_name=u"创建时间")
- dateTimeUpdated = DateTimeField(verbose_name=u"状态更新时间")
- # 版本信息 用于控制兼容代码
- version = StringField(verbose_name=u"商户版本信息", default=None)
- # 法人信息
- identifyCardAUrl = StringField(verbose_name=u"法人证件(人像)")
- identifyCardBUrl = StringField(verbose_name=u"法人证件(国徽)")
- identifyCardCUrl = StringField(verbose_name=u"法人证件(手持)")
- identifyCardName = StringField(verbose_name=u"法人证件 姓名")
- identifyCardCode = StringField(verbose_name=u"法人证件 号码")
- identifyCardStartTime = StringField(verbose_name=u"法人证件 起始日期")
- identifyCardEndTime = StringField(verbose_name=u"法人证件 结束日期")
- identifyCardLongTime = BooleanField(verbose_name=u"法人证件 是否是长期")
- identifyCardProvinceCode = StringField(verbose_name="法人 省CODE")
- identifyCardCityCode = StringField(verbose_name=u"法人 市CODE")
- identifyCardAreaCode = StringField(verbose_name=u"法人 区CODE")
- identifyCardProvince = StringField(verbose_name=u"法人 省 ")
- identifyCardCity = StringField(verbose_name=u"法人 市")
- identifyCardArea = StringField(verbose_name=u"法人 区")
- identifyCardAddr = StringField(verbose_name=u"法人 详细地址")
- # 联系人信息
- contactPersonName = StringField(verbose_name=u"联系人 姓名")
- contactPersonPhone = StringField(verbose_name=u"联系人 手机")
- contactPersonEmail = StringField(verbose_name="联系人 邮箱")
- # 营业执照相关的信息 当商户为企业的时候存在
- busLicenseUrl = StringField(verbose_name=u"企业的营业执照")
- busName = StringField(verbose_name=u"企业名称")
- busCode = StringField(verbose_name=u"营业执照统一社会信用码")
- busProvinceCode = StringField(verbose_name=u"营业地址所在省code")
- busCityCode = StringField(verbose_name=u"营业地址所在市code")
- busAreaCode = StringField(verbose_name=u"营业地址所在区code")
- busProvince = StringField(verbose_name=u"营业地址所在省")
- busCity = StringField(verbose_name=u"营业地址所在市")
- busArea = StringField(verbose_name=u"营业地址所在区")
- busAddr = StringField(verbose_name=u"营业地址")
- # 结算的相关信息
- bankCardUrl = StringField(verbose_name=u"银行卡/开户许可证")
- bankCardCode = StringField(verbose_name=u"银行卡/开户许可证 名称")
- bankCardName = StringField(verbose_name=u"银行卡/开户许可证 开户行")
- bankCardSubCode = StringField(verbose_name=u"银行卡/开户许可证 支行CODE")
- bankCardSubName = StringField(verbose_name=u"银行卡/开户许可证 支行名称")
- # 经营的相关信息
- storeShotName = StringField(verbose_name=u"门店简称")
- storeAUrl = StringField(verbose_name=u"门店的照片 门头照")
- storeBUrl = StringField(verbose_name=u"门店的照片 出入口")
- storeCUrl = StringField(verbose_name=u"门店的照片 店内")
- shopProvinceCode = StringField(verbose_name=u"门店所在省code")
- shopCityCode = StringField(verbose_name=u"门店所在市code")
- shopAreaCode = StringField(verbose_name=u"门店所在地区code")
- shopProvince = StringField(verbose_name=u"门店所在省")
- shopCity = StringField(verbose_name=u"门店所在市")
- shopArea = StringField(verbose_name=u"门店所在地区")
- shopAddr = StringField(verbose_name=u"商户所在详细地址")
- products = MapField(EmbeddedDocumentField(verbose_name=u"开通的支付产品", document_type=MerchantProduct))
- regEmail = StringField(verbose_name=u"注册邮箱号. 也这个作为商户登录账号")
- wxApplier = LazyReferenceField(verbose_name=u"微信申请的信息", document_type= WechatApplyMerchant)
- def __repr__(self):
- return "Merchant Source Info <{}>".format(self.id)
- def load_enter_image_info(self):
- """
- 加载 商户入驻所需要的图片信息
- :return:
- """
- result = dict()
- # 营业执照的照片
- result['blicUrla'] = self.blicUrla
- # 如果是企业用户 还需要上传银行开户许可证的照片
- if self.companyType == COMPANY_TYPE.ENTERPRISE:
- result['occUrla'] = self.occUrla
- # 身份证的照片
- result['lepUrla'] = self.lepUrla
- result['lepUrlb'] = self.lepUrlb
- result['lepUrlc'] = self.lepUrlc
- # 门店的照片
- result['img'] = self.img
- result['enterimg'] = self.enterimg
- result['innerimg'] = self.innerimg
- # 结算类照片
- result['cardPhoto'] = self.cardPhoto
- result['settleManPhotoFront'] = self.settleManPhotoFront
- result['settleManPhotoBack'] = self.settleManPhotoBack
- result['settleHoldingIDCard'] = self.settleHoldingIDCard
- return result
- def load_enter_entity_info(self):
- """
- 加载商户进件所需要的 entity的信息
- :return:
- """
- result = dict()
- # 首先添加公共类信息 即必传递的信息
- result['companyType'] = self.companyType
- result['serialNo'] = self.serialNo
- result['agentNo'] = self.agentNo
- result['regEmail'] = self.regEmail
- result['regPhone'] = self.regPhone
- result['blicCardType'] = self.blicCardType
- result['blicCompanyName'] = self.blicCompanyName
- result['abMerchantName'] = self.abMerchantName
- # 企业商户需要增加的部分信息
- if self.companyType == COMPANY_TYPE.ENTERPRISE:
- result['blicUscc'] = self.blicUscc
- result['blicScope'] = self.blicScope
- result['indTwoCode'] = self.indTwoCode
- result['blicProvince'] = self.blicProvince
- result['blicCity'] = self.blicCity
- result['blicAddress'] = self.blicAddress
- result['blicLongTerm'] = self.blicLongTerm
- result['blicValidityStart'] = self.blicValidityStart
- result['blicValidityEnd'] = self.blicValidityEnd
- result['lepCardType'] = self.lepCardType
- result['lepName'] = self.lepName
- result['lepCardNo'] = self.lepCardNo
- result['lepLongTerm'] = self.lepLongTerm
- result['lepValidityStart'] = self.lepValidityStart
- result['lepValidityEnd'] = self.lepValidityEnd
- result['contactName'] = self.contactName
- result['contactPhone'] = self.contactPhone
- result['contactEmail'] = self.contactEmail
- result['contactProvince'] = self.contactProvince
- result['contactCity'] = self.contactCity
- result['contactAddress'] = self.contactAddress
- result['ifPhyStore'] = self.ifPhyStore
- result['storeProvince'] = self.storeProvince
- result['storeCity'] = self.storeCity
- result['storeAddress'] = self.storeAddress
- result['settleToCard'] = self.settleToCard
- result['priatePublic'] = self.priatePublic
- result['bankName'] = self.bankName
- result['subBankCode'] = self.subBankCode
- result['bankAccountNo'] = self.bankAccountNo
- result['bankAccountName'] = self.bankAccountName
- result['settleCardPhone'] = self.settleCardPhone
- result['settlementPeriod'] = self.settlementPeriod
- result['directoryList'] = self.directoryList
- # 如果存在商户的商户号 说明是修改了
- if self.merchantNo:
- result['merchantNo'] = self.merchantNo
- return result
- def load_product_info(self, product):
- """
- 加载京东产品申请的产品信息
- :return:
- """
- serialNo = self.generate_serial_no(self.ownerId)
- result = {
- "agentNo": self.agentNo,
- "merchantNo": self.merchantNo,
- "serialNo": serialNo,
- "productId": product.productId,
- "payToolId": product.payToolId,
- "mfeeType": product.rateType,
- }
- if product.productId in [ProductType.WECHAT, ProductType.ALIPAY]:
- result.update({"mfee": product.mfee})
- elif product.productId in [ProductType.JD]:
- result.update({"ladderList": [product.ladderList.to_dict()]})
- return result
- def load_query_info(self):
- """
- 获取查询 京东商户的 条件信息
- :return:
- """
- serialNo = self.generate_serial_no(self.ownerId)
- result = {
- "serialNo": serialNo,
- "merchantNo": self.merchantNo,
- }
- return result
- @staticmethod
- def load_address_name(code):
- return MerchantAddress.get_name(code)
- def add_product(self, productType):
- """
- 初始化微信和支付宝两个产品 wechat alipay
- 再加上一个 京东的
- """
- productId = getattr(ProductType, productType.upper(), None)
- assert productId in ProductType.choices(), u"不支持的产品类型"
- product = self.products.get(productType)
- if product and product.status != ProductStatus.FAIL:
- return
- # 费率固定为 千分之6
- mfee = JDMerchantPermillage(DEFAULT_TRADE_FEE)
- self.products[productType] = MerchantProduct.created_product(
- productId=productId,
- mfee=mfee
- )
- def is_product_fail(self):
- """
- 产品有无开通失败的
- """
- return any(map(lambda x: x.status == ProductStatus.FAIL, self.products.values()))
- def is_product_success(self):
- """
- 产品是否均开通成功
- """
- return all(map(lambda x: x.status == ProductStatus.SUCCESS, self.products.values()))
- def enter_success(self, merchantNo, serialNo):
- """
- 将商户申请状态切换为 等待 同时初始化 支付产品
- """
- # 修改的时候不会有 merchantNo
- if merchantNo:
- self.merchantNo = merchantNo
- if serialNo:
- self.serial_no = serialNo
- self.errorDescription = ""
- self.add_product("wechat")
- self.add_product("alipay")
- self.add_product("jd")
- # 重置错误信息
- self.save()
- merchant_enter.send(sender=self.__class__, merchantId=str(self.id))
- return self
- def support_apply(self):
- """
- 是否支持 开通商户产品
- """
- if self.status != MerchantStatus.WAITING:
- return False
- if not self.products:
- return False
- return True
- @staticmethod
- def load_image_content(url):
- """
- 获取图像的二进制数据
- :return:
- """
- return AliOssFileUploader.load(url)
- @staticmethod
- def generate_serial_no(ownerId):
- return "{}{}{}".format(datetime.datetime.now().strftime("%Y%m%d%H%M%S"), ownerId, random.randint(1000, 9999)).upper()
- @staticmethod
- def trans_merchant_type(merchantType):
- """转换京东进件的类型"""
- # 个人商户
- if merchantType == "SUBJECT_TYPE_MICRO":
- return COMPANY_TYPE.NORMAL_PERSON
- # 企业商户
- return COMPANY_TYPE.ENTERPRISE
- @staticmethod
- def trans_end_time(endTime):
- if endTime == "forever":
- return u"长期"
- return endTime
- @classmethod
- def get_source_record(cls, owner): # type:(Optional[Agent, Dealer]) -> MerchantSourceInfo
- """
- 获取原始的申请记录
- """
- _owner = owner.merchantRegister
- return cls.objects.filter(ownerId=str(_owner.id), ownerRole=str(_owner.role)).first() or cls(ownerId=str(_owner.id), ownerRole=str(_owner.role))
- @property
- def owner(self):
- """
- 做一次缓存 防止频繁访问数据库
- """
- if hasattr(self, "_owner"):
- return self._owner
- owner = ROLE.from_role_id(self.ownerRole, self.ownerId)
- setattr(self, "_owner", owner)
- return owner
- @property
- def agentNo(self):
- """服务商 修改为 和我们系统的agent绑定"""
- merchantAgent = self.merchantAgent.fetch()
- return merchantAgent.agentNo
- # 照片信息类
- @property
- def blicUrla(self):
- """
- 营业执照的照片
- 文档规定 自然人的情况下 营业执照传递合同租凭 和对方技术人员沟通 这个地方可以就传身份证件
- :return:
- """
- url = self.busLicenseUrl
- if self.companyType == COMPANY_TYPE.NORMAL_PERSON:
- url = self.identifyCardAUrl
- return self.load_image_content(url)
- @property
- def occUrla(self):
- """
- 银行开户许可证 非必传选项 当商户类型为企业的时候必传递 沟通就传递营业执照
- :return:
- """
- return self.load_image_content(self.busLicenseUrl)
- @property
- def blicObaUrla(self):
- """
- 税字号图片 企业商户五类证件的时候才需要(目前应该不需要)
- :return:
- """
- return
- @property
- def blicTrcUrla(self):
- """
- 组织机构代码 企业商户五类证件的时候才需要(目前应该不需要)
- :return:
- """
- return
- @property
- def lepUrla(self):
- """
- 身份证证件的正面
- :return:
- """
- return self.load_image_content(self.identifyCardAUrl)
- @property
- def lepUrlb(self):
- """
- 身份证证件的反面
- :return:
- """
- return self.load_image_content(self.identifyCardBUrl)
- @property
- def lepUrlc(self):
- """
- 手持身份证 照片 只有当商户类型为自然人的时候需要
- 经过宋伟沟通 这个地方也可以传递身份证的正面信息
- :return:
- """
- return self.load_image_content(self.identifyCardCUrl)
- @property
- def img(self):
- """
- 经营门店的门头照片
- :return:
- """
- return self.load_image_content(self.storeAUrl)
- @property
- def enterimg(self):
- """
- 经营门店的入口照片
- :return:
- """
- return self.load_image_content(self.storeBUrl)
- @property
- def innerimg(self):
- """
- 经营门店的店内信息
- :return:
- """
- return self.load_image_content(self.storeCUrl)
- @property
- def cardPhoto(self):
- """
- 结算银行卡正面图片
- :return:
- """
- return self.load_image_content(self.bankCardUrl)
- @property
- def settleManPhotoFront(self):
- """
- 结算人身份证的正面照
- :return:
- """
- return self.lepUrla
- @property
- def settleManPhotoBack(self):
- """
- 结算人身份证背面照
- :return:
- """
- return self.lepUrlb
- @property
- def settleHoldingIDCard(self):
- """
- 结算人身份证的手持照
- :return:
- """
- return self.load_image_content(self.identifyCardCUrl)
- @property
- def settleHoldingBankCard(self):
- """
- 结算人手持银行卡 暂时不需要
- :return:
- """
- return
- # 报文信息(entity)
- @property
- def companyType(self):
- """
- 公司的性质 目前支持的就是企业性质或个人性质
- :return:
- """
- return self.merchantType
- @property
- def serialNo(self):
- """
- 订单流水号 需要注意的是 一旦商户入驻成功, 订单流水号不变 修改信息的时候 以成功入驻的流水号为准
- 这个地方处理的逻辑是 用户入驻成功之后 才会将流水号写入进去 否则的话就为空 就会重新生成
- :return:
- """
- if not self.serial_no:
- self.serial_no = self.generate_serial_no(self.ownerId)
- return self.serial_no
- else:
- return self.serial_no
- @serialNo.setter
- def serialNo(self, value):
- """
- 当设置 流水号的时候 说明商户入驻已经提交成功了 这个时候顺便将商户的状态 从init 转换为 等待中
- :param value:
- :return:
- """
- if self.status != MerchantStatus.INIT:
- return
- self.status = MerchantStatus.WAITING
- self.serial_no = value
- self.save()
- self.reload()
- @property
- def regPhone(self):
- return self.owner.username
- @property
- def blicCardType(self):
- """
- 企业包含:统一社会信用代码类-USC,普通五证类-BLI,多证合一类-OCI
- 自然人:身份证-ID
- 目前企业的简化了 只支持统一社会信用代码 即USC
- :return:
- """
- if self.companyType == COMPANY_TYPE.ENTERPRISE:
- return "USC"
- return "ID"
- @property
- def blicCompanyName(self):
- """
- 实体商户的名称
- 企业商户 的时候就传递企业商户证件照上面的名称
- 个人商户时填姓名+(自然人)
- :return:
- """
- if self.companyType == COMPANY_TYPE.ENTERPRISE:
- return self.busName
- return u"商户_{}".format(self.identifyCardName)
- @property
- def abMerchantName(self):
- """
- 商户简称
- :return:
- """
- return self.storeShotName
- @property
- def blicUscc(self):
- """
- 统一社会信用码
- :return:
- """
- return self.busCode
- @property
- def blicObaCardNo(self):
- """
- 税务登记号 暂时不需要
- :return:
- """
- return
- @property
- def blicTrcCardNo(self):
- """
- 组织机构代码 目前不需要
- :return:
- """
- return
- @property
- def blicScope(self):
- """
- TODO 经营范围 企业商户需要
- :return:
- """
- return u"自主类设备经营"
- @property
- def indTwoCode(self):
- # 行业编号
- return "033"
- @property
- def blicProvince(self):
- """
- 营业地址所在省
- 对于个人用户 可以填写联系人所在的
- :return:
- """
- if self.companyType == COMPANY_TYPE.ENTERPRISE:
- return self.busProvince
- return self.shopProvince
- @property
- def blicCity(self):
- """
- 营业地址所在市
- 对于个人商户 可以填写联系人所在的市
- :return:
- """
- if self.companyType == COMPANY_TYPE.ENTERPRISE:
- return self.busCity
- return self.shopCity
- @property
- def blicAddress(self):
- """
- 营业地址的地区
- 对于个人商户而言 可以填写联系人所在的地址
- :return:
- """
- if self.companyType == COMPANY_TYPE.ENTERPRISE:
- return self.busArea + self.busAddr
- return self.shopArea + self.shopAddr
- @property
- def blicLongTerm(self):
- """
- 营业执照 是否长期
- :return:
- """
- # TODO zjl
- return self.identifyCardLongTime
- @property
- def blicValidityStart(self):
- """
- 营业执照起始时间
- :return:
- """
- return self.identifyCardStartTime
- @property
- def blicValidityEnd(self):
- """
- 营业执照结束时间
- :return:
- """
- return self.identifyCardEndTime if not self.identifyCardLongTime else u"长期"
- @property
- def lepCardType(self):
- """
- 法人证件类型 目前固定为ID
- :return:
- """
- return "ID"
- @property
- def lepName(self):
- """
- 法人证件姓名 就是身份证
- :return:
- """
- return self.identifyCardName
- @property
- def lepCardNo(self):
- """
- 法人的证件号 就是身份证号
- :return:
- """
- return self.identifyCardCode
- @property
- def lepLongTerm(self):
- """
- 法人证件是否长期
- :return:
- """
- return self.identifyCardLongTime
- @property
- def lepValidityStart(self):
- """
- 法人证件的起始类型
- :return:
- """
- return self.identifyCardStartTime
- @property
- def lepValidityEnd(self):
- """
- 法人证件的类型到期
- :return:
- """
- return self.identifyCardEndTime if not self.identifyCardLongTime else u"长期"
- @property
- def contactName(self):
- """
- 联系人姓名
- :return:
- """
- if self.contactPersonName:
- return self.contactPersonName
- return self.identifyCardName
- @property
- def contactPhone(self):
- """
- 联系人的电话号码
- :return:
- """
- return self.contactPersonPhone
- @property
- def contactEmail(self):
- """
- 联系人的电子邮箱
- :return:
- """
- return self.contactPersonEmail
- @property
- def contactProvince(self):
- """
- 联系人的省
- :return:
- """
- return self.identifyCardProvince
- @property
- def contactCity(self):
- """
- 联系人的市
- :return:
- """
- return self.identifyCardCity
- @property
- def contactAddress(self):
- """
- 联系人的详细地址
- :return:
- """
- return self.identifyCardArea + self.identifyCardAddr
- @property
- def ifPhyStore(self):
- """
- 门店是否线下 固定值
- :return:
- """
- return True
- @property
- def storeProvince(self):
- """
- 门店所在的省
- :return:
- """
- return self.shopProvince
- @property
- def storeCity(self):
- """
- 门店所在的市
- :return:
- """
- return self.shopCity
- @property
- def storeAddress(self):
- """
- 门店所在的地址
- :return:
- """
- return self.shopArea + self.shopAddr
- @property
- def settleToCard(self):
- """
- 是否结算到卡 固定值
- :return:
- """
- return "1"
- @property
- def priatePublic(self):
- """
- 结算账户的公私标志 企业用户一律是对公账户 个人账户一律是私人账户
- :return:
- """
- if self.companyType == COMPANY_TYPE.ENTERPRISE:
- return PRIATE_OR_PUBLIC.PUBLIC.value
- return PRIATE_OR_PUBLIC.PRIATE.value
- @property
- def bankName(self):
- """
- 结算银行的名称
- :return:
- """
- return self.bankCardName
- @property
- def subBankCode(self):
- """
- 结算银行的支行联行号
- :return:
- """
- return self.bankCardSubCode
- @property
- def bankAccountNo(self):
- """
- 结算银行卡的账号
- :return:
- """
- return self.bankCardCode
- @property
- def bankAccountName(self):
- """
- 结算的账户名称
- :return:
- """
- if self.companyType == COMPANY_TYPE.ENTERPRISE:
- return self.busName
- return self.identifyCardName
- @property
- def settleCardPhone(self):
- """
- 结算银行卡绑定的手机号码
- :return:
- """
- return self.owner.username
- @property
- def settlementPeriod(self):
- """
- 结算的周期 固定D1
- :return:
- """
- return "D1"
- @property
- def directoryList(self):
- """
- 商户的授权目录
- :return:
- """
- return ["{}/".format(settings.SERVER_END_BASE_URL)]
- @property
- def loginLink(self):
- return "https://passport.jdpay.com/login/index.do"
- @property
- def wxSource(self): # type:() -> WechatApplyMerchant
- """
- """
- if not getattr(self, "_wxSource", None):
- setattr(self, "_wxSource", self.wxApplier.fetch() if self.wxApplier else WechatApplyMerchant())
- return getattr(self, "_wxSource")
- @property
- def merchantStatus(self):
- """
- 商户的申请状态 做兼容使用
- """
- if self.status in [
- MerchantStatus.INIT, MerchantStatus.WAITING, MerchantStatus.FAIL, MerchantStatus.SUCCESS,
- MerchantStatus.AUTH_WAITING, MerchantStatus.AUTH_SUCCESS
- ]:
- return int(self.status)
- # 微信等待审核的状态 当客户是实名等待确认的时候 每次都去拉取同步一次 保证信息的真实准确
- elif self.status in [int(MerchantStatus.AUTH_APPLY_SUCCESS)]:
- from apps.web.merchant.utils import is_wechat_authorized, is_alipay_authorized
- if is_wechat_authorized(self) and is_alipay_authorized(self):
- self.to_wx_success()
- return int(MerchantStatus.AUTH_SUCCESS)
- else:
- return int(self.status)
- def get_help_message(self):
- """
- 显示当前步骤的帮助信息
- """
- if self.status == MerchantStatus.INIT:
- return u"您尚未提交商户资料,请及时提交商户资料,避免影响您后续收款"
- if self.status == MerchantStatus.WAITING:
- return u"您已提交资料,请耐心等待商户审核通过"
- if self.status == MerchantStatus.FAIL:
- return u"商户申请失败,失败原因为 <{}>".format(self.errorDescription)
- if self.status == MerchantStatus.CONFIRM:
- return u"您的商户申请已经通过,正准备提交微信完成商户实名"
- if self.status == MerchantStatus.AUTH_WAITING:
- return u"您的资料资料已提交到微信平台,正在进行商户实名申请中,请耐心等待实名申请通过"
- if self.status == MerchantStatus.AUTH_APPLY_SUCCESS:
- return u"您的实名申请已经通过审核,请点击下方按钮前往确认实名意愿"
- if self.status == MerchantStatus.AUTH_SUCCESS:
- return u"你的商户已经完成开通,请点击下方按钮完成收款方式切换"
- return u"商户开通完成"
- def get_merchant_info(self): # type:() -> dict
- """
- 获取商户的基本信息
- """
- data = {
- # 商户类型
- "merchantType": self.wxSource.subjectInfo.mainType,
- # 商户号
- "merchantNo": self.merchantNo,
- # 商户的状态
- "status": self.merchantStatus,
- # 提交资料的时间
- "created": self.dateTimeAdded,
- # 联系人
- "contactName": self.contactName,
- # 联系电话
- "contactPhone": self.contactPhone,
- # 登录账号:
- "regEmail": self.regEmail,
- # 数据的更新时间
- "updated": self.dateTimeUpdated
- }
- return data
- def get_help_info(self):
- """
- 获取帮助信息
- """
- return {
- # 帮助按钮的链接
- "helpHtml": "http://mp.weixin.qq.com/s?__biz=MzU2NDQ1MTM2NQ==&mid=2247483688&idx=1&sn=d4f935020d8051d7af1236019a76eae3&chksm=fc4b8062cb3c0974b47b75036012e01a28ba88172f91f3f63abbb23d177a25526671ae1d77e1&scene=18#wechat_redirect",
- # 帮助的文字 或提示信息
- "helpMessage": self.get_help_message()
- }
- def get_legal_info(self):
- """
- 获取法人的信息
- """
- return {
- "urlA": self.wxSource.legalInfo.lepCardUrlA,
- "urlB": self.wxSource.legalInfo.lepCardUrlB,
- "name": self.wxSource.legalInfo.lepName,
- "cardNo": self.wxSource.legalInfo.lepCardNo,
- "startTime": self.wxSource.legalInfo.lepCardStart,
- "endTime": self.wxSource.legalInfo.lepCardEnd,
- "province": {
- "code": self.wxSource.legalInfo.lepProvinceCode,
- "name": self.wxSource.legalInfo.lepProvince
- },
- "city": {
- "code": self.wxSource.legalInfo.lepCityCode,
- "name": self.wxSource.legalInfo.lepCity
- },
- "area": {
- "code": self.wxSource.legalInfo.lepAreaCode,
- "name": self.wxSource.legalInfo.lepArea
- },
- "addr": self.wxSource.legalInfo.lepAddr
- }
- def get_contact_info(self):
- """
- 获取联系人的信息
- """
- # 只有自然人
- if self.merchantType == COMPANY_TYPE.NORMAL_PERSON:
- return None
- return {
- "urlA": self.wxSource.contactInfo.contactCardUrlA,
- "urlB": self.wxSource.contactInfo.contactCardUrlB,
- "name": self.wxSource.contactInfo.contactName,
- "cardNo": self.wxSource.contactInfo.contactCardNo,
- "startTime": self.wxSource.contactInfo.contactCardStart,
- "endTime": self.wxSource.contactInfo.contactCardEnd,
- "province": {
- "code": self.wxSource.contactInfo.contactProvinceCode,
- "name": self.wxSource.contactInfo.contactProvince
- },
- "city": {
- "code": self.wxSource.contactInfo.contactCityCode,
- "name": self.wxSource.contactInfo.contactCity
- },
- "area": {
- "code": self.wxSource.contactInfo.contactAreaCode,
- "name": self.wxSource.contactInfo.contactArea
- },
- "addr": self.wxSource.contactInfo.contactAddr
- }
- def get_licence_info(self):
- """
- 获取营业执照的信息
- """
- # 只有自然人
- if self.merchantType == COMPANY_TYPE.NORMAL_PERSON:
- return None
- if self.wxSource.subjectInfo.businessLicenceInfo:
- return {
- "businessLicenceInfo": {
- "busLicenseUrl": self.wxSource.subjectInfo.businessLicenceInfo.licenceCopy,
- "busCode": self.wxSource.subjectInfo.businessLicenceInfo.licenceNumber,
- "busName": self.wxSource.subjectInfo.businessLicenceInfo.merchantName,
- "startTime": self.wxSource.subjectInfo.businessLicenceInfo.licenceStart,
- "endTime": self.wxSource.subjectInfo.businessLicenceInfo.licenceEnd,
- "province": {
- "code": self.busProvinceCode,
- "name": self.busProvince
- },
- "city": {
- "code": self.busCityCode,
- "name": self.busCity
- },
- "area": {
- "code": self.busAreaCode,
- "name": self.busArea
- },
- "addr": self.busAddr
- }
- }
- def get_certificate_info(self):
- """
- 获取商户提交的证件资料
- """
- return {
- # 商户类型
- "contactType": self.wxSource.contactInfo.contactType,
- "businessAuthorizationLetter": self.wxSource.contactInfo.businessAuthorizationLetter,
- "legalInfo": self.get_legal_info(),
- "contactInfo": self.get_contact_info(),
- "subjectInfo": self.get_licence_info(),
- }
- def save_certificate_info(self, payload):
- """
- 保存商户提交的证件资料
- """
- # 首先处理商户类型的信息
- self.errorDescription = ""
- self.merchantAgent = MerchantAgent.default_merchant_agent()
- self.merchantType = self.trans_merchant_type(payload["merchantType"])
- # 配置法人的证件照片信息
- self.identifyCardAUrl = payload["legalInfo"]["urlA"]
- self.identifyCardBUrl = payload["legalInfo"]["urlB"]
- self.identifyCardCUrl = payload["legalInfo"]["urlA"]
- # 配置法人的证件文字信息
- self.identifyCardName = payload["legalInfo"]["name"]
- self.identifyCardCode = payload["legalInfo"]["cardNo"]
- self.identifyCardStartTime = payload["legalInfo"]["startTime"]
- self.identifyCardEndTime = self.trans_end_time(payload["legalInfo"]["endTime"])
- self.identifyCardLongTime = self.identifyCardEndTime == u"长期"
- # 配置法人证件的地址信息
- self.identifyCardProvinceCode = payload["legalInfo"]["province"]["code"]
- self.identifyCardCityCode = payload["legalInfo"]["city"]["code"]
- self.identifyCardAreaCode = payload["legalInfo"]["area"]["code"]
- self.identifyCardProvince = payload["legalInfo"]["province"]["name"]
- self.identifyCardCity = payload["legalInfo"]["city"]["name"]
- self.identifyCardArea = payload["legalInfo"]["area"]["name"]
- self.identifyCardAddr = payload["legalInfo"]["addr"]
- # 存储商户的联系人信息 如果商户类型是个人企业 联系人即为自身
- if self.merchantType == COMPANY_TYPE.NORMAL_PERSON:
- self.contactPersonName = payload["legalInfo"]["name"]
- else:
- self.contactPersonName = payload["contactInfo"]["name"]
- # 如果商户号类型为企业的商户 则需要保存商户信息
- if self.merchantType != COMPANY_TYPE.NORMAL_PERSON:
- self.busLicenseUrl = payload["subjectInfo"]["businessLicenceInfo"]["busLicenseUrl"]
- self.busName = payload["subjectInfo"]["businessLicenceInfo"]["busName"]
- self.busCode = payload["subjectInfo"]["businessLicenceInfo"]["busCode"]
- self.busProvinceCode = payload["subjectInfo"]["businessLicenceInfo"]["province"]["code"]
- self.busCityCode = payload["subjectInfo"]["businessLicenceInfo"]["city"]["code"]
- self.busAreaCode = payload["subjectInfo"]["businessLicenceInfo"]["area"]["code"]
- self.busProvince = payload["subjectInfo"]["businessLicenceInfo"]["province"]["name"]
- self.busCity = payload["subjectInfo"]["businessLicenceInfo"]["city"]["name"]
- self.busArea = payload["subjectInfo"]["businessLicenceInfo"]["area"]["name"]
- self.busAddr = payload["subjectInfo"]["businessLicenceInfo"]["addr"]
- # 保存微信申请所需的信息
- self.wxSource.subjectInfo.mainType = payload["merchantType"]
- self.wxSource.legalInfo.save_certificate_info(payload["legalInfo"])
- self.wxSource.contactInfo.save_certificate_info(payload["contactInfo"])
- # 如果是 企业商户 保存一下营业执照的信息
- if self.merchantType != COMPANY_TYPE.NORMAL_PERSON:
- businessLicenceInfo = payload["subjectInfo"]["businessLicenceInfo"]
- businessLicenceInfo["busLegal"] = self.identifyCardName
- self.wxSource.subjectInfo.save_certificate_info(businessLicenceInfo=businessLicenceInfo)
- self.wxApplier = self.wxSource.save()
- if self.status == int(MerchantStatus.INIT):
- self.dateTimeAdded = datetime.datetime.now()
- self.dateTimeUpdated = datetime.datetime.now()
- return self.save()
- def get_settlement_info(self):
- """
- 获取用户提交的结算信息资料
- """
- return {
- "bankCardImg": self.bankCardUrl,
- "bankCardCode": self.bankCardCode,
- "bankName": self.bankCardName,
- "bankCardSubCode": self.bankCardSubCode,
- "bankCardSubName": self.bankCardSubName
- }
- def save_settlement_info(self, payload):
- """
- 保存商户的结算信息
- """
- # 图片的照片
- self.bankCardUrl = payload["bankCardImg"]
- # 银行名称
- self.bankCardName = payload["bankName"]
- # 银行卡号码
- self.bankCardCode = payload["bankCardCode"]
- # 支行联行号
- self.bankCardSubCode = payload["bankCardSubCode"]
- # 支行名称
- self.bankCardSubName = payload["bankCardSubName"]
- return self.save()
- def get_business_info(self):
- """
- 获取用户提交的营业信息
- """
- return {
- "storeAUrl": self.storeAUrl,
- "storeBUrl": self.storeBUrl,
- "storeCUrl": self.storeCUrl,
- # 商户简称
- "storeShotName": self.storeShotName,
- # 地址
- "province": {
- "code": self.shopProvinceCode,
- "name": self.shopProvince
- },
- "city": {
- "code": self.shopCityCode,
- "name": self.shopCity
- },
- "area": {
- "code": self.shopAreaCode,
- "name": self.shopArea
- },
- "addr": self.shopAddr,
- "mobile": self.contactPersonPhone,
- }
- def save_business_info(self, payload):
- """
- 保存营业类的信息
- """
- # 商户号一旦申请了,商户简称不允许修改
- self.storeShotName = payload["storeShotName"]
- # 照片信息是可变的
- self.storeAUrl = payload["storeAUrl"]
- self.storeBUrl = payload["storeBUrl"]
- self.storeCUrl = payload["storeCUrl"]
- # 地址信息是可变的
- self.shopProvinceCode = payload["province"]["code"]
- self.shopCityCode = payload["city"]["code"]
- self.shopAreaCode = payload["area"]["code"]
- self.shopProvince = payload["province"]["name"]
- self.shopCity = payload["city"]["name"]
- self.shopArea = payload["area"]["name"]
- self.shopAddr = payload["addr"]
- # 个人信息小微商户的时候 需要保存
- if self.merchantType == COMPANY_TYPE.NORMAL_PERSON:
- self.wxSource.subjectInfo.save_certificate_info(assistProveInfo=payload)
- self.wxApplier = self.wxSource.save()
- return self.save()
- def save_mobile_info(self, mobile):
- """
- 保存手机号信息 商户号一旦确认 手机号不允许修改
- """
- if not self.merchantNo:
- self.contactPersonPhone = mobile
- self.contactPersonEmail = self.regEmail = "{}@163.com".format(self.contactPersonPhone)
- self.wxSource.contactInfo.save_mobile_info(mobile)
- self.wxApplier = self.wxSource.save()
- return self.save()
- return self
- def support_modify(self):
- """
- 只有初始化以及审核失败的时候 才允许填写、修改资料
- """
- return self.status in [int(MerchantStatus.FAIL), int(MerchantStatus.INIT)]
- def support_enter(self):
- """
- 是否支持进件 只有状态为1的时候 才会触发进件
- """
- return self.status in [int(MerchantStatus.WAITING)]
- def support_query_audit(self):
- return self.status in [int(MerchantStatus.WAITING)]
- def support_jdaggre(self):
- """
- 京东app已经可以使用 等待微信实名认证
- """
- return self.status in [int(MerchantStatus.CONFIRM)]
- def support_wechat_audit(self):
- """
- 查询微信的 申请状态
- """
- return self.status in [int(MerchantStatus.AUTH_WAITING)]
- @property
- def is_wechat_submit(self):
- return self.wxSource.applymentId
- @property
- def is_ali_submit(self):
- """
- 阿里的 暂时都视为已经提交
- """
- return True
- def to_waiting(self, **kwargs):
- """
- 切换到入驻申请状态
- """
- assert self.status in [MerchantStatus.INIT, MerchantStatus.FAIL]
- self.status = int(MerchantStatus.WAITING)
- self.dateTimeUpdated = datetime.datetime.now()
- self.save()
- MerchantLog.submit(str(self.id))
- merchant_user_submit.send(sender=self.__class__, merchantId=str(self.id))
- def to_confirm(self, **kwargs):
- """
- 商户此时已经完成开通 准备各项准备工作
- 录入秘钥
- 录入APP
- 录入子商户编号等
- """
- assert self.status == MerchantStatus.WAITING
- desKey, mdKey = kwargs["desKey"], kwargs["mdKey"]
- if not all([desKey, mdKey]):
- return
- self.status = int(MerchantStatus.CONFIRM)
- self.desKey, self.mdKey = desKey, mdKey
- self.dateTimeUpdated = datetime.datetime.now()
- self.save()
- # 代理商、经销商预处理
- self.owner.confirm_merchant(self)
- # 记录一次操作日志
- MerchantLog.add_app(str(self.id))
- # 发送信号 触发下一轮的行动
- merchant_jd_access.send(sender=self.__class__, merchantId=str(self.id))
- def to_wx_waiting(self, **kwargs):
- """
- 状态不再发生变化
- """
- assert self.status == int(MerchantStatus.CONFIRM)
- self.wxSource.to_wechat_submit(kwargs["applymentId"])
- self.dateTimeUpdated = datetime.datetime.now()
- self.save()
- # 记录一次操作日志
- MerchantLog.submit_wechat(str(self.id), description=kwargs["applymentId"])
- def to_ali_waiting(self, **kwargs):
- assert self.status == int(MerchantStatus.CONFIRM)
- self.wxSource.to_ali_submit(kwargs["applymentId"])
- self.dateTimeUpdated = datetime.datetime.now()
- self.status = int(MerchantStatus.AUTH_WAITING)
- self.save()
- # 记录一次操作日志
- MerchantLog.submit_ali(str(self.id), description=kwargs["applymentId"])
- def to_auth_wait(self):
- """
- 实名信息提交完毕
- """
- assert self.status == int(MerchantStatus.CONFIRM)
- self.status = int(MerchantStatus.AUTH_WAITING)
- self.dateTimeUpdated = datetime.datetime.now()
- self.save()
- def to_auth_apply_success(self, **kwargs):
- """
- 全部实名已经通过 内部状态 做强制商户时候使用
- """
- assert self.status == int(MerchantStatus.AUTH_WAITING)
- self.status = int(MerchantStatus.AUTH_APPLY_SUCCESS)
- self.dateTimeUpdated = datetime.datetime.now()
- self.save()
- MerchantLog.auth_apply_success(str(self.id))
- def to_wx_success(self, **kwargs):
- """
- 微信审核通过 防止有些人通过扫描二维码小程序自行提交资料申请 状态放的宽泛一点点
- """
- self.status = int(MerchantStatus.AUTH_SUCCESS)
- self.dateTimeUpdated = datetime.datetime.now()
- self.save()
- def to_success(self, **kwargs):
- """
- 经销商的商户确认开通 需要切换经销商的支付方式 而代理商的仅仅改变状态就可以了
- """
- assert self.status == MerchantStatus.AUTH_SUCCESS
- # 更改商户的状态
- self.status = int(MerchantStatus.SUCCESS)
- self.dateTimeUpdated = datetime.datetime.now()
- self.save()
- # 然后是角色各自处理
- self.owner.success_merchant()
- # 记录一次操作日志
- MerchantLog.change_pay_type(str(self.id))
- def to_fail(self, errorMsg):
- """
- 切换为失败的状态 只有开通产品的时候会调用这个接口 如果入驻的时候失败 直接切换成为初始状态就好
- """
- self.status = int(MerchantStatus.FAIL)
- self.dateTimeUpdated = datetime.datetime.now()
- self.wxApplier = self.wxSource.to_cancel()
- self.errorDescription = errorMsg
- self.save()
- self.reload()
- # 记录一次日志操作
- MerchantLog.fail(str(self.id), description=errorMsg)
- def create_app(self):
- return JDAggrePayApp.get_or_create_by_merchant(self)
- class Area(EmbeddedDocument):
- code = StringField(verbose_name="地区编码")
- name = StringField(verbose_name=u"地区名称")
- def __str__(self):
- return self.name
- def to_dict(self):
- return {
- "name": self.name,
- "code": self.code
- }
- class Attach(EmbeddedDocument):
- url = StringField(verbose_name=u"源")
- attachNum = StringField(verbose_name=u"编号")
- @property
- def content(self):
- res = requests.get(url=self.url, timeout=3)
- return res.content
- def upload_success(self, attachNum):
- self.attachNum = attachNum
- return self.save()
- def update_url(self, url, save=False):
- self.url = url
- return self if not save else self.save()
- class PayBank(EmbeddedDocument):
- num = StringField(verbose_name="产品编号")
- rate = StringField(verbose_name=u"费率", default="0.6")
- @classmethod
- def default_pay_type(cls):
- return [
- # 京东
- cls(num="10031414639876930831001", rate="0.60"),
- cls(num="10031414639876930831004", rate="0.60"),
- cls(num="10031414639876930831005", rate="0.60"),
- cls(num="10031414639876930831013", rate="0.60")
- ]
- def to_dict(self):
- return {
- "num": self.num,
- "rate": self.rate
- }
- class JDOpenApplyInfo(Searchable):
- """
- 京东openAPI 的用户先写的原始资料
- """
- dateTimeAdded = DateTimeField(verbose_name=u"录入信息的时间", default=datetime.datetime.now)
- dateTimeUpdated = DateTimeField(verbose_name=u"记录更新的时间", default=datetime.datetime.now)
- status = IntField(verbose_name=u"商户状态", default=JdOpenMerchantStatus.INIT)
- isDelete = BooleanField(verbose_name=u"是否已经删除", default=False)
- ownerId = StringField(verbose_name=u"商户申请人ID")
- ownerRole = StringField(verbose_name=u"商户申请人角色")
- errorDesc = StringField(verbose_name=u"错误描述")
- # 通过接口返回的参数
- agentNum = StringField(verbose_name=u"服务商编号", default="10001016435484143212321")
- customerNum = StringField(verbose_name=u"商户编号")
- settleNum = StringField(verbose_name=u"结算账户编号")
- shopNum = StringField(verbose_name="商店编号")
- # 商户基础参数 目前行业类型不对外开放
- customerType = StringField(verbose_name=u"商户类型")
- fullName = StringField(verbose_name=u"商户全称")
- shortName = StringField(verbose_name=u"商户简称")
- industry = StringField(verbose_name=u"一级行业", default=u"生活服务") # 统一属于 生活服务 中的 自助服务
- subIndustry = StringField(verbose_name=u"二级行业", default=u"自助") # 统一属于 生活服务 中的 自助服务
- province = EmbeddedDocumentField(verbose_name=u"商户省", document_type=Area)
- city = EmbeddedDocumentField(verbose_name=u"商户市", document_type=Area)
- district = EmbeddedDocumentField(verbose_name=u"商户区", document_type=Area)
- address = StringField(verbose_name=u"商户详细地址")
- mapLng = StringField(verbose_name=u"商户经度")
- mapLat = StringField(verbose_name=u"商户维度")
- # 法人信息参数 目前证件类型不对外开放
- certificateType = StringField(verbose_name=u"证件类型", default="IDENTIFICATION")
- legalImgFront = EmbeddedDocumentField(verbose_name=u"法人身份证正面", document_type=Attach)
- legalImgBack = EmbeddedDocumentField(verbose_name=u"法人身份证背面", document_type=Attach)
- legalName = StringField(verbose_name=u"法人姓名")
- legalCardNo = StringField(verbose_name=u"证件号码")
- legalStart = StringField(verbose_name=u"法人的证件起始")
- legalEnd = StringField(verbose_name=u"法人的证件结束")
- legalProvince = EmbeddedDocumentField(verbose_name=u"法人省", document_type=Area)
- legalCity = EmbeddedDocumentField(verbose_name=u"法人市", document_type=Area)
- legalDistrict = EmbeddedDocumentField(verbose_name=u"法人区", document_type=Area)
- legalAddress = StringField(verbose_name=u"法人详细地址")
- # 联系人信息参数
- contactImgFront = EmbeddedDocumentField(verbose_name=u"联系人身份证正面", document_type=Attach)
- contactImgBack = EmbeddedDocumentField(verbose_name=u"联系人身份证背面", document_type=Attach)
- contactName = StringField(verbose_name=u"联系人姓名")
- contactCardNo = StringField(verbose_name=u"联系人卡号")
- contactStart = StringField(verbose_name=u"联系人证件开始")
- contactEnd = StringField(verbose_name=u"联系人证件结束")
- phoneNumber = StringField(verbose_name=u"登录账号、手机号码")
- # 收款账号相应参数
- accountType = StringField(verbose_name=u"账户类型")
- bankImg = EmbeddedDocumentField(verbose_name=u"银行卡", document_type=Attach)
- bankCardNo = StringField(verbose_name=u"银行卡号")
- bankName = StringField(verbose_name=u"银行名称")
- bankBranchName = StringField(verbose_name=u"支行名称")
- bankProvince = EmbeddedDocumentField(verbose_name=u"银行省", document_type=Area)
- bankCity = EmbeddedDocumentField(verbose_name=u"银行市", document_type=Area)
- settleAmount = StringField(verbose_name=u"起结算金额", default="1")
- payBankList = EmbeddedDocumentListField(verbose_name=u"支付方式", document_type=PayBank)
- bankPhone = StringField(verbose_name=u"银行预留手机号")
- # 营业执照相应参数
- organizationImg = EmbeddedDocumentField(verbose_name=u"营业执照", document_type=Attach)
- organizationName = StringField(verbose_name=u"企业名称")
- organizationNo = StringField(verbose_name=u"统一组织机构代码")
- organizationStart = StringField(verbose_name=u"营业执照的起始")
- organizationEnd = StringField(verbose_name=u"营业执照的结束")
- organizationProvince = EmbeddedDocumentField(verbose_name=u"营业执照省", document_type=Area)
- organizationCity = EmbeddedDocumentField(verbose_name=u"营业执照市", document_type=Area)
- organizationDistrict = EmbeddedDocumentField(verbose_name=u"营业执照区", document_type=Area)
- organizationAddress = StringField(verbose_name=u"营业执照详细地址")
- # 事业单位证书相关参数
- certType = StringField(verbose_name=u"证书类型")
- certImg = EmbeddedDocumentField(verbose_name=u"证书", document_type=Attach)
- certName = StringField(verbose_name=u"组织机构名称")
- certNo = StringField(verbose_name=u"证书编号")
- certStart = StringField(verbose_name=u"营业执照起始")
- certEnd = StringField(verbose_name=u"营业执照结束")
- certProvince = EmbeddedDocumentField(verbose_name=u"证书省", document_type=Area)
- certCity = EmbeddedDocumentField(verbose_name=u"证书市", document_type=Area)
- certDistrict = EmbeddedDocumentField(verbose_name=u"证书区", document_type=Area)
- certAddress = StringField(verbose_name=u"证书详细地址")
- # 门店照相应参数
- shopImgA = EmbeddedDocumentField(verbose_name=u"店铺照", document_type=Attach)
- shopImgB = EmbeddedDocumentField(verbose_name=u"门头照", document_type=Attach)
- shopImgC = EmbeddedDocumentField(verbose_name=u"店内照", document_type=Attach)
- # 个人需要
- identifyhandhold = EmbeddedDocumentField(verbose_name=u"个人手持身份照", document_type=Attach)
- # 企业&个体工商户 需要
- organizationcode = EmbeddedDocumentField(verbose_name=u"税务登记证", document_type=Attach)
- taxregistration = EmbeddedDocumentField(verbose_name=u"税务登记证", document_type=Attach)
- unifiedsocialcreditcode = EmbeddedDocumentField(verbose_name=u"税务登记证", document_type=Attach)
- # 事业单位独有参数
- certificateFile = EmbeddedDocumentField(verbose_name=u"事业单位证明函", document_type=Attach)
- specialQualification = EmbeddedDocumentField(verbose_name=u"特殊资质证书", document_type=Attach)
- # 经办人信息
- businessAuthorizationLetter = EmbeddedDocumentField(verbose_name=u"业务办理授权函", document_type=Attach)
- # 微信申请的消息
- subMerchantId = StringField(verbose_name=u"微信子商编")
- businessCode = StringField(verbose_name=u"微信业务申请单编号")
- applymentId = StringField(verbose_name=u"微信申请编号")
- # 支付宝申请的信息
- subAliMerchantId = StringField(verbose_name=u"支付宝子商编")
- aliApplymentId = StringField(verbose_name=u"支付宝申请编号")
- aliBusinessCode = StringField(verbose_name=u"支付宝实名申请单编号")
- meta = {
- 'collection': 'JDOpenApplyInfo',
- # TODO 需要切换数据库
- # "db_alias": "logdata"
- }
- def __str__(self):
- return "{}_{}".format(self.__class__.__name__, self.id)
- @classmethod
- def create_personal(cls, owner, **kwargs):
- """
- 新建个人商户的信息
- """
- mer = cls.get_merchant_by_owner(owner) #
- if mer and str(mer.id) != kwargs["id"]:
- raise ValueError(u"非所属经销商ID")
- else:
- # 新创建或者是修改
- mer = mer or cls(ownerId=str(owner.id), ownerRole=owner.role)
- mer.customerType = kwargs["customerType"]
- mer.fullName = kwargs["fullName"]
- mer.shortName = kwargs["shortName"]
- mer.province = Area(**kwargs["province"])
- mer.city = Area(**kwargs["city"])
- mer.district = Area(**kwargs["district"])
- mer.address = kwargs["address"]
- mer.mapLng = kwargs["mapLng"]
- mer.mapLat = kwargs["mapLat"]
- mer.legalImgFront = (mer.legalImgFront or Attach()).update_url(kwargs["legalImgFront"])
- mer.legalImgBack = (mer.legalImgBack or Attach()).update_url(kwargs["legalImgBack"])
- mer.legalName = kwargs["legalName"]
- mer.legalCardNo = kwargs["legalCardNo"]
- mer.legalStart = kwargs["legalStart"]
- mer.legalEnd = kwargs["legalEnd"]
- mer.phoneNumber = kwargs["phoneNumber"]
- mer.accountType = kwargs["accountType"]
- mer.bankImg = (mer.bankImg or Attach()).update_url(kwargs["bankImg"])
- mer.bankCardNo = kwargs["bankCardNo"]
- mer.bankName = kwargs["bankName"]
- mer.bankBranchName = kwargs["bankBranchName"]
- mer.bankProvince = Area(**kwargs["bankProvince"])
- mer.bankCity = Area(**kwargs["bankCity"])
- mer.payBankList = PayBank.default_pay_type()
- mer.bankPhone = kwargs["bankPhone"]
- mer.shopImgA = (mer.shopImgA or Attach()).update_url(kwargs["shopImgA"])
- mer.shopImgB = (mer.shopImgB or Attach()).update_url(kwargs["shopImgB"])
- mer.shopImgC = (mer.shopImgC or Attach()).update_url(kwargs["shopImgC"])
- mer.identifyhandhold = (mer.identifyhandhold or Attach()).update_url(kwargs["legalImgHold"])
- mer = mer.save()
- return mer
- @classmethod
- def create_company(cls, owner, **kwargs):
- mer = cls.get_merchant_by_owner(owner) #
- if mer and str(mer.id) != kwargs["id"]:
- raise ValueError(u"非所属经销商ID")
- else:
- # 新创建或者是修改
- mer = mer or cls(ownerId=str(owner.id), ownerRole=owner.role)
- mer.customerType = kwargs["customerType"]
- mer.fullName = kwargs["fullName"]
- mer.shortName = kwargs["shortName"]
- mer.province = Area(**kwargs["province"])
- mer.city = Area(**kwargs["city"])
- mer.district = Area(**kwargs["district"])
- mer.address = kwargs["address"]
- mer.mapLng = kwargs["mapLng"]
- mer.mapLat = kwargs["mapLat"]
- # 企业上户需要加上法人证件的地址 便于微信的实名
- mer.legalImgFront = (mer.legalImgFront or Attach()).update_url(kwargs["legalImgFront"])
- mer.legalImgBack = (mer.legalImgBack or Attach()).update_url(kwargs["legalImgBack"])
- mer.legalName = kwargs["legalName"]
- mer.legalCardNo = kwargs["legalCardNo"]
- mer.legalStart = kwargs["legalStart"]
- mer.legalEnd = kwargs["legalEnd"]
- mer.legalProvince = Area(**kwargs["legalProvince"])
- mer.legalCity = Area(**kwargs["legalCity"])
- mer.legalDistrict = Area(**kwargs["legalDistrict"])
- mer.legalAddress = kwargs["legalAddress"]
- mer.contactImgFront = (mer.contactImgFront or Attach()).update_url(kwargs["contactImgFront"])
- mer.contactImgBack = (mer.contactImgBack or Attach()).update_url(kwargs["contactImgBack"])
- mer.contactName = kwargs["contactName"]
- mer.contactCardNo = kwargs["contactCardNo"]
- mer.contactStart = kwargs["contactStart"]
- mer.contactEnd = kwargs["contactEnd"]
- mer.phoneNumber = kwargs["phoneNumber"]
- mer.accountType = kwargs["accountType"]
- mer.bankImg = (mer.bankImg or Attach()).update_url(kwargs["bankImg"])
- mer.bankCardNo = kwargs["bankCardNo"]
- mer.bankName = kwargs["bankName"]
- mer.bankBranchName = kwargs["bankBranchName"]
- mer.bankProvince = Area(**kwargs["bankProvince"])
- mer.bankCity = Area(**kwargs["bankCity"])
- mer.payBankList = PayBank.default_pay_type()
- mer.bankPhone = kwargs["bankPhone"]
- mer.organizationImg = (mer.organizationImg or Attach()).update_url(kwargs["organizationImg"])
- mer.organizationName = kwargs["organizationName"]
- mer.organizationNo = kwargs["organizationNo"]
- mer.organizationStart = kwargs["organizationStart"]
- mer.organizationEnd = kwargs["organizationEnd"]
- mer.organizationProvince = Area(**kwargs["organizationProvince"])
- mer.organizationCity = Area(**kwargs["organizationCity"])
- mer.organizationDistrict = Area(**kwargs["organizationDistrict"])
- mer.organizationAddress = kwargs["organizationAddress"]
- mer.shopImgA = (mer.shopImgA or Attach()).update_url(kwargs["shopImgA"])
- mer.shopImgB = (mer.shopImgB or Attach()).update_url(kwargs["shopImgB"])
- mer.shopImgC = (mer.shopImgC or Attach()).update_url(kwargs["shopImgC"])
- mer.organizationcode = (mer.organizationcode or Attach()).update_url(kwargs["organizationcode"])
- mer.taxregistration = (mer.taxregistration or Attach()).update_url(kwargs["taxregistration"])
- mer.unifiedsocialcreditcode = (mer.unifiedsocialcreditcode or Attach()).update_url(kwargs["unifiedsocialcreditcode"])
- # 经办人的信息
- mer.businessAuthorizationLetter = (mer.taxregistration or Attach()).update_url(kwargs["businessAuthorizationLetter"])
- mer = mer.save()
- return mer
- @classmethod
- def create_individualbiss(cls, owner, **kwargs):
- """
- 创建个体工商户
- """
- mer = cls.get_merchant_by_owner(owner) #
- if mer and str(mer.id) != kwargs["id"]:
- raise ValueError(u"非所属经销商ID")
- else:
- # 新创建或者是修改
- mer = mer or cls(ownerId=str(owner.id), ownerRole=owner.role)
- mer.customerType = kwargs["customerType"]
- mer.fullName = kwargs["fullName"]
- mer.shortName = kwargs["shortName"]
- mer.province = Area(**kwargs["province"])
- mer.city = Area(**kwargs["city"])
- mer.district = Area(**kwargs["district"])
- mer.address = kwargs["address"]
- mer.mapLng = kwargs["mapLng"]
- mer.mapLat = kwargs["mapLat"]
- mer.legalImgFront = (mer.legalImgFront or Attach()).update_url(kwargs["legalImgFront"])
- mer.legalImgBack = (mer.legalImgBack or Attach()).update_url(kwargs["legalImgBack"])
- mer.legalName = kwargs["legalName"]
- mer.legalCardNo = kwargs["legalCardNo"]
- mer.legalStart = kwargs["legalStart"]
- mer.legalEnd = kwargs["legalEnd"]
- mer.contactImgFront = (mer.contactImgFront or Attach()).update_url(kwargs["contactImgFront"])
- mer.contactImgBack = (mer.contactImgBack or Attach()).update_url(kwargs["contactImgBack"])
- mer.contactName = kwargs["contactName"]
- mer.contactCardNo = kwargs["contactCardNo"]
- mer.contactStart = kwargs["contactStart"]
- mer.contactEnd = kwargs["contactEnd"]
- mer.phoneNumber = kwargs["phoneNumber"]
- mer.accountType = kwargs["accountType"]
- mer.bankImg = (mer.bankImg or Attach()).update_url(kwargs["bankImg"])
- mer.bankCardNo = kwargs["bankCardNo"]
- mer.bankName = kwargs["bankName"]
- mer.bankBranchName = kwargs["bankBranchName"]
- mer.bankProvince = Area(**kwargs["bankProvince"])
- mer.bankCity = Area(**kwargs["bankCity"])
- mer.payBankList = PayBank.default_pay_type()
- mer.bankPhone = kwargs["bankPhone"]
- mer.organizationImg = (mer.organizationImg or Attach()).update_url(kwargs["organizationImg"])
- mer.organizationName = kwargs["organizationName"]
- mer.organizationNo = kwargs["organizationNo"]
- mer.organizationStart = kwargs["organizationStart"]
- mer.organizationEnd = kwargs["organizationEnd"]
- mer.organizationProvince = Area(**kwargs["organizationProvince"])
- mer.organizationCity = Area(**kwargs["organizationCity"])
- mer.organizationDistrict = Area(**kwargs["organizationDistrict"])
- mer.organizationAddress = kwargs["organizationAddress"]
- mer.shopImgA = (mer.shopImgA or Attach()).update_url(kwargs["shopImgA"])
- mer.shopImgB = (mer.shopImgB or Attach()).update_url(kwargs["shopImgB"])
- mer.shopImgC = (mer.shopImgC or Attach()).update_url(kwargs["shopImgC"])
- mer.organizationcode = (mer.organizationcode or Attach()).update_url(kwargs["organizationcode"])
- mer.taxregistration = (mer.taxregistration or Attach()).update_url(kwargs["taxregistration"])
- # 经办人的信息
- mer.businessAuthorizationLetter = (mer.taxregistration or Attach()).update_url(kwargs["businessAuthorizationLetter"])
- mer = mer.save()
- return mer
- @classmethod
- def create_institution(cls, owner, **kwargs):
- """
- 创建事业单位
- """
- mer = cls.get_merchant_by_owner(owner) #
- if mer and str(mer.id) != kwargs["id"]:
- raise ValueError(u"非所属经销商ID")
- else:
- # 新创建或者是修改
- mer = mer or cls(ownerId=str(owner.id), ownerRole=owner.role)
- mer.customerType = kwargs["customerType"]
- mer.fullName = kwargs["fullName"]
- mer.shortName = kwargs["shortName"]
- mer.province = Area(**kwargs["province"])
- mer.city = Area(**kwargs["city"])
- mer.district = Area(**kwargs["district"])
- mer.address = kwargs["address"]
- mer.mapLng = kwargs["mapLng"]
- mer.mapLat = kwargs["mapLat"]
- mer.legalImgFront = (mer.legalImgFront or Attach()).update_url(kwargs["legalImgFront"])
- mer.legalImgBack = (mer.legalImgBack or Attach()).update_url(kwargs["legalImgBack"])
- mer.legalName = kwargs["legalName"]
- mer.legalCardNo = kwargs["legalCardNo"]
- mer.legalStart = kwargs["legalStart"]
- mer.legalEnd = kwargs["legalEnd"]
- mer.contactImgFront = (mer.contactImgFront or Attach()).update_url(kwargs["contactImgFront"])
- mer.contactImgBack = (mer.contactImgBack or Attach()).update_url(kwargs["contactImgBack"])
- mer.contactName = kwargs["contactName"]
- mer.contactCardNo = kwargs["contactCardNo"]
- mer.contactStart = kwargs["contactStart"]
- mer.contactEnd = kwargs["contactEnd"]
- mer.phoneNumber = kwargs["phoneNumber"]
- mer.accountType = kwargs["accountType"]
- mer.bankImg = (mer.bankImg or Attach()).update_url(kwargs["bankImg"])
- mer.bankCardNo = kwargs["bankCardNo"]
- mer.bankName = kwargs["bankName"]
- mer.bankBranchName = kwargs["bankBranchName"]
- mer.bankProvince = Area(**kwargs["bankProvince"])
- mer.bankCity = Area(**kwargs["bankCity"])
- mer.payBankList = PayBank.default_pay_type()
- mer.bankPhone = kwargs["bankPhone"]
- mer.certType = kwargs["certType"]
- mer.certImg = (mer.certImg or Attach()).update_url(kwargs["certImg"])
- mer.certName = kwargs["certName"]
- mer.certNo = kwargs["certNo"]
- mer.certStart = kwargs["certStart"]
- mer.certEnd = kwargs["certEnd"]
- mer.certProvince = Area(**kwargs["certProvince"])
- mer.certCity = Area(**kwargs["certCity"])
- mer.certDistrict = Area(**kwargs["certDistrict"])
- mer.certAddress = kwargs["certAddress"]
- mer.shopImgA = (mer.shopImgA or Attach()).update_url(kwargs["shopImgA"])
- mer.shopImgB = (mer.shopImgB or Attach()).update_url(kwargs["shopImgB"])
- mer.shopImgC = (mer.shopImgC or Attach()).update_url(kwargs["shopImgC"])
- mer.certificateFile = (mer.certificateFile or Attach()).update_url(kwargs["certificateFile"])
- mer.specialQualification = (mer.specialQualification or Attach()).update_url(kwargs["specialQualification"])
- mer.organizationcode = (mer.organizationcode or Attach()).update_url(kwargs["organizationcode"])
- mer.taxregistration = (mer.taxregistration or Attach()).update_url(kwargs["taxregistration"])
- mer.unifiedsocialcreditcode = (mer.unifiedsocialcreditcode or Attach()).update_url(kwargs["unifiedsocialcreditcode"])
- # 经办人的信息
- mer.businessAuthorizationLetter = (mer.taxregistration or Attach()).update_url(kwargs["businessAuthorizationLetter"])
- mer = mer.save()
- return mer
- @classmethod
- def get_merchant_by_status(cls, status):
- return cls.objects.filter(status=status, isDelete=False)
- @classmethod
- def get_merchant_by_owner(cls, owner):
- return cls.objects.filter(ownerId=str(owner.id), ownerRole=str(owner.role), isDelete=False).first()
- @classmethod
- def get_merchant_by_id(cls, _id): # type:(str) -> JDOpenApplyInfo
- return cls.objects.filter(id=_id, isDelete=False).first()
- @property
- def is_personal(self):
- """
- 个人类型商户
- """
- return self.customerType == JdOpenMerchantType.PERSON
- @property
- def is_company(self):
- """
- 企业类型商户
- """
- return self.customerType == JdOpenMerchantType.COMPANY
- @property
- def is_individualbiss(self):
- """
- 个体工商户
- """
- return self.customerType == JdOpenMerchantType.INDIVIDUALBISS
- @property
- def is_institution(self):
- """
- 事业单位
- """
- return self.customerType == JdOpenMerchantType.INSTITUTION
- @property
- def merchantAddr(self):
- return u"{}{}{}{}".format(self.province, self.city, self.district, self.address)
- @property
- def organizationAddr(self):
- return u"{}{}{}{}".format(self.organizationProvince, self.organizationCity, self.organizationDistrict, self.organizationAddress)
- @property
- def certAddr(self):
- return u"{}{}{}{}".format(self.certProvince, self.certCity, self.certDistrict, self.certAddress)
- @property
- def legalAddr(self):
- return u"{}{}{}{}".format(self.legalProvince, self.legalCity, self.legalDistrict, self.legalAddress)
- @property
- def owner(self):
- if hasattr(self, "_owner"):
- return self._owner
- owner = ROLE.from_role_id(self.ownerRole, self.ownerId)
- setattr(self, "_owner", owner)
- return owner
- @property
- def wxSource(self):
- return self
- def get_access_and_secret(self):
- logger.info("[get_access_and_secret] get merchant id = {}".format(self.id))
- return OPEN_ACCESS_KEY, OPEN_SECRET_KEY
- def get_info(self):
- return {
- "id": str(self.id),
- "status": int(self.status),
- "agentNum": str(self.agentNum),
- "customerNum": str(self.customerNum),
- "settleNum": str(self.settleNum),
- "shopNum": str(self.shopNum),
- "customerType": self.customerType,
- "shortName": self.shortName,
- "province": self.province.to_dict() if self.province else {},
- "city": self.city.to_dict() if self.city else {},
- "district": self.district.to_dict() if self.district else {},
- "address": self.address,
- "mapLng": self.mapLng,
- "mapLat": self.mapLat,
- "certificateType": self.certificateType,
- "legalImgFront": self.legalImgFront.url if self.legalImgFront else "",
- "legalImgBack": self.legalImgBack.url if self.legalImgBack else "",
- "legalName": self.legalName,
- "legalCardNo": self.legalCardNo,
- "legalStart": self.legalStart,
- "legalEnd": self.legalEnd,
- "legalForever": True if self.legalEnd == "forever" else False,
- "contactImgFront": self.contactImgFront.url if self.contactImgFront else "",
- "contactImgBack": self.contactImgBack.url if self.contactImgBack else "",
- "contactName": self.contactName,
- "contactCardNo": self.contactCardNo,
- "contactStart": self.contactStart,
- "contactEnd": self.contactEnd,
- "contactForever": True if self.contactEnd == "forever" else False,
- "phoneNumber": self.phoneNumber,
- "accountType": self.accountType,
- "bankImg": self.bankImg.url if self.bankImg else "",
- "bankCardNo": self.bankCardNo,
- "bankName": self.bankName,
- "bankBranchName": self.bankBranchName,
- "bankProvince": self.bankProvince.to_dict() if self.bankProvince else {},
- "bankCity": self.bankCity.to_dict() if self.bankCity else {},
- "bankPhone": self.bankPhone,
- "organizationImg": self.organizationImg.url if self.organizationImg else "",
- "organizationName": self.organizationName,
- "organizationNo": self.organizationNo,
- "organizationStart": self.organizationStart,
- "organizationEnd": self.organizationEnd,
- "organizationForever": True if self.organizationEnd == "forever" else False,
- "organizationProvince": self.organizationProvince.to_dict() if self.organizationProvince else {},
- "organizationCity": self.organizationCity.to_dict() if self.organizationCity else {},
- "organizationDistrict": self.organizationDistrict.to_dict() if self.organizationDistrict else {},
- "organizationAddress": self.organizationAddress,
- "certType": self.certType,
- "certImg": self.certImg.url if self.certImg else "",
- "certNo": self.certNo,
- "certStart": self.certStart,
- "certEnd": self.certEnd,
- "certForever": True if self.certEnd == "forever" else False,
- "certProvince": self.certProvince.to_dict() if self.certProvince else {},
- "certCity": self.certCity.to_dict() if self.certCity else {},
- "certDistrict": self.certDistrict.to_dict() if self.certDistrict else {},
- "certAddress": self.certAddress,
- "shopImgA": self.shopImgA.url if self.shopImgA else "",
- "shopImgB": self.shopImgB.url if self.shopImgB else "",
- "shopImgC": self.shopImgC.url if self.shopImgC else "",
- "legalImgHold": self.identifyhandhold.url if self.identifyhandhold else "",
- "organizationcode": self.organizationcode.url if self.organizationcode else "",
- "taxregistration": self.taxregistration.url if self.taxregistration else "",
- "unifiedsocialcreditcode": self.unifiedsocialcreditcode.url if self.unifiedsocialcreditcode else "",
- "certificateFile": self.certificateFile.url if self.certificateFile else "",
- "specialQualification": self.specialQualification.url if self.specialQualification else "",
- }
- def to_submit(self):
- self.status = JdOpenMerchantStatus.SUBMIT
- self.dateTimeUpdated = datetime.datetime.now()
- MerchantLog.submit(str(self.id))
- self.save()
- merchant_user_submit.send(sender=self.__class__, merchantId=str(self.id))
- return self
- def to_fail(self, message):
- self.status = JdOpenMerchantStatus.FAIL
- self.errorDesc = message
- self.dateTimeUpdated = datetime.datetime.now()
- MerchantLog.fail(str(self.id))
- return self.save()
- def to_customer(self, customerNum):
- self.status = JdOpenMerchantStatus.CUSTOMER
- self.customerNum = customerNum
- self.dateTimeUpdated = datetime.datetime.now()
- self.save()
- create_customer_success.send(sender=self.__class__, merchantId=str(self.id))
- return self
- def to_settle(self, settleNum):
- self.status = JdOpenMerchantStatus.SETTLE
- self.settleNum = settleNum
- self.dateTimeUpdated = datetime.datetime.now()
- self.save()
- create_settle_success.send(sender=self.__class__, merchantId=str(self.id))
- return self
- def to_shop(self, shopNum):
- self.status = JdOpenMerchantStatus.SHOP
- self.shopNum = shopNum
- self.dateTimeUpdated = datetime.datetime.now()
- self.save()
- create_shop_success.send(sender=self.__class__, merchantId=str(self.id))
- return self
- def to_attach(self):
- self.status = JdOpenMerchantStatus.ATTACH
- self.dateTimeUpdated = datetime.datetime.now()
- self.save()
- upload_attach_success.send(sender=self.__class__, merchantId=str(self.id))
- return self
- def to_complete(self):
- self.status = JdOpenMerchantStatus.COMPLETE
- self.dateTimeUpdated = datetime.datetime.now()
- self.save()
- complete_success.send(sender=self.__class__, merchantId=str(self.id))
- return self
- def to_confirm(self):
- self.status = JdOpenMerchantStatus.CONFIRM
- self.dateTimeUpdated = datetime.datetime.now()
- self.save()
- merchant_jd_access.send(sender=self.__class__, merchantId=str(self.id))
- return self
- def to_success(self):
- """
- 京东的商户审核完成 审核完成的时候 创建app
- """
- self.owner.confirm_merchant(self)
- self.status = JdOpenMerchantStatus.SUCCESS
- self.dateTimeUpdated = datetime.datetime.now()
- MerchantLog.add_app(str(self.id))
- return self.save()
- def to_wx_waiting(self, **kwargs):
- self.applymentId = str(kwargs["applymentId"])
- self.dateTimeUpdated = datetime.datetime.now()
- MerchantLog.submit_wechat(str(self.id))
- return self.save()
- def to_wx_audit(self):
- self.status = JdOpenMerchantStatus.AUTH_APPLY_SUCCESS
- self.dateTimeUpdated = datetime.datetime.now()
- return self.save()
- def to_apply(self, server): # type:(WechatApiProxy) -> dict
- """
- 生成微信所需要的信息
- """
- businessCode = "{}{}".format(datetime.datetime.now().strftime("%Y%m%d%H%M%S"), random.randint(1000, 9999)),
- self.businessCode = businessCode
- self.save()
- data = {
- "business_code": businessCode,
- "addition_info": {"confirm_mchid_list": [self.subMerchantId]}
- }
- if self.is_personal:
- contact_info = {
- "contact_type": ContactType.LEGAL.code,
- "name": server.rsa_encrypt(self.legalName),
- "id_card_number": server.rsa_encrypt(self.legalCardNo),
- "mobile": server.rsa_encrypt(self.phoneNumber),
- }
- subject_info = {
- "subject_type": "SUBJECT_TYPE_MICRO",
- "assist_prove_info": {
- "micro_biz_type": "MICRO_TYPE_STORE",
- "store_name": self.shortName,
- "store_address_code": WxMerchantAddress.get_code(u"{}省{}市{}".format(
- self.province.name, self.city.name, self.district.name
- )),
- "store_address": self.merchantAddr,
- "store_header_copy": server.upload_image_from_oss(self.shopImgA.url).get("media_id", ""),
- "store_indoor_copy": server.upload_image_from_oss(self.shopImgB.url).get("media_id", ""),
- }
- }
- identification_info = {
- "identification_type": "IDENTIFICATION_TYPE_IDCARD",
- "identification_name": server.rsa_encrypt(self.legalName),
- "identification_number": server.rsa_encrypt(self.legalCardNo),
- "identification_valid_date": '["{}","{}"]'.format(self.legalStart, self.legalEnd),
- "identification_front_copy": server.upload_image_from_oss(self.legalImgFront.url).get("media_id", ""),
- "identification_back_copy": server.upload_image_from_oss(self.legalImgBack.url).get("media_id", ""),
- }
- elif self.is_company:
- isLegal = self.legalCardNo == self.contactCardNo and self.legalName == self.contactName
- contact_info = {
- "contact_type": ContactType.LEGAL.code if isLegal else ContactType.SUPER.code,
- "name": server.rsa_encrypt(self.contactName),
- "id_card_number": server.rsa_encrypt(self.contactCardNo),
- "mobile": server.rsa_encrypt(self.phoneNumber),
- }
- if not isLegal:
- contact_info.update({
- "contact_id_doc_type": "IDENTIFICATION_TYPE_IDCARD",
- "contact_id_doc_copy": server.upload_image_from_oss(self.contactImgFront.url).get("media_id", ""),
- "contact_id_doc_copy_back": server.upload_image_from_oss(self.contactImgBack.url).get("media_id", ""),
- "contact_period_begin": self.contactStart,
- "contact_period_end": u"长期" if self.contactEnd == "forever" else self.contactEnd,
- "business_authorization_letter": server.upload_image_from_oss(self.businessAuthorizationLetter.url).get("media_id", "")
- })
- subject_info = {
- "subject_type": "SUBJECT_TYPE_ENTERPRISE",
- "business_licence_info": {
- "licence_number": self.organizationcode,
- "licence_copy": server.upload_image_from_oss(self.organizationImg.url).get("media_id", ""),
- "merchant_name": self.organizationName,
- "legal_person": self.legalName,
- "company_address": self.organizationAddr,
- "licence_valid_date": '["{}","{}"]'.format(self.organizationStart, self.organizationEnd),
- },
- }
- identification_info = {
- "identification_type": "IDENTIFICATION_TYPE_IDCARD",
- "identification_name": server.rsa_encrypt(self.legalName),
- "identification_number": server.rsa_encrypt(self.legalCardNo),
- "identification_valid_date": '["{}","{}"]'.format(self.legalStart, self.legalEnd),
- "identification_address": self.legalAddr,
- "identification_front_copy": server.upload_image_from_oss(self.legalImgFront.url).get("media_id", ""),
- "identification_back_copy": server.upload_image_from_oss(self.legalImgBack.url).get("media_id", ""),
- "owner": True
- }
- elif self.is_individualbiss:
- isLegal = self.legalCardNo == self.contactCardNo and self.legalName == self.contactName
- contact_info = {
- "contact_type": ContactType.LEGAL.code if isLegal else ContactType.SUPER.code,
- "name": server.rsa_encrypt(self.contactName),
- "id_card_number": server.rsa_encrypt(self.contactCardNo),
- "mobile": server.rsa_encrypt(self.phoneNumber),
- }
- if not isLegal:
- contact_info.update({
- "contact_id_doc_type": "IDENTIFICATION_TYPE_IDCARD",
- "contact_id_doc_copy": server.upload_image_from_oss(self.contactImgFront.url).get("media_id", ""),
- "contact_id_doc_copy_back": server.upload_image_from_oss(self.contactImgBack.url).get("media_id", ""),
- "contact_period_begin": self.contactStart,
- "contact_period_end": u"长期" if self.contactEnd == "forever" else self.contactEnd,
- "business_authorization_letter": server.upload_image_from_oss(self.businessAuthorizationLetter.url).get("media_id", "")
- })
- subject_info = {
- "subject_type": "SUBJECT_TYPE_INDIVIDUAL",
- "business_licence_info": {
- "licence_number": self.organizationcode,
- "licence_copy": server.upload_image_from_oss(self.organizationImg.url).get("media_id", ""),
- "merchant_name": self.organizationName,
- "legal_person": self.legalName,
- "company_address": self.organizationAddr,
- "licence_valid_date": '["{}","{}"]'.format(self.organizationStart, self.organizationEnd),
- }
- }
- identification_info = {
- "identification_type": "IDENTIFICATION_TYPE_IDCARD",
- "identification_name": server.rsa_encrypt(self.legalName),
- "identification_number": server.rsa_encrypt(self.legalCardNo),
- "identification_valid_date": '["{}","{}"]'.format(self.legalStart, self.legalEnd),
- "identification_address": self.legalAddr,
- "identification_front_copy": server.upload_image_from_oss(self.legalImgFront.url).get("media_id", ""),
- "identification_back_copy": server.upload_image_from_oss(self.legalImgBack.url).get("media_id", ""),
- }
- else:
- isLegal = self.legalCardNo == self.contactCardNo and self.legalName == self.contactName
- contact_info = {
- "contact_type": ContactType.LEGAL.code if isLegal else ContactType.SUPER.code,
- "name": server.rsa_encrypt(self.contactName),
- "id_card_number": server.rsa_encrypt(self.contactCardNo),
- "mobile": server.rsa_encrypt(self.phoneNumber),
- }
- if not isLegal:
- contact_info.update({
- "contact_id_doc_type": "IDENTIFICATION_TYPE_IDCARD",
- "contact_id_doc_copy": server.upload_image_from_oss(self.contactImgFront.url).get("media_id", ""),
- "contact_id_doc_copy_back": server.upload_image_from_oss(self.contactImgBack.url).get("media_id", ""),
- "contact_period_begin": self.contactStart,
- "contact_period_end": u"长期" if self.contactEnd == "forever" else self.contactEnd,
- "business_authorization_letter": server.upload_image_from_oss(self.businessAuthorizationLetter.url).get("media_id", "")
- })
- subject_info = {
- "subject_type": "SUBJECT_TYPE_INSTITUTIONS_CLONED",
- "certificate_info": {
- "cert_type": self.certType,
- "cert_number": self.certNo,
- "cert_copy": server.upload_image_from_oss(self.certImg.url).get("media_id", ""),
- "merchant_name": self.certName,
- "legal_person": self.legalName,
- "company_address": self.certAddr,
- "cert_valid_date": '["{}","{}"]'.format(self.certStart, self.certEnd),
- }
- }
- company_prove_copy = server.upload_image_from_oss(self.certificateFile.url).get("media_id", "")
- # TODO 特殊行业资质许可证填充
- special_operation_list = {
- "category_id": 1,
- "operation_copy_list": server.upload_image_from_oss(self.specialQualification.url).get("media_id", "")
- }
- identification_info = {
- "identification_type": "IDENTIFICATION_TYPE_IDCARD",
- "identification_name": server.rsa_encrypt(self.legalName),
- "identification_number": server.rsa_encrypt(self.legalCardNo),
- "identification_valid_date": '["{}","{}"]'.format(self.legalStart, self.legalEnd),
- "identification_address": self.legalAddr,
- "identification_front_copy": server.upload_image_from_oss(self.legalImgFront.url).get("media_id", ""),
- "identification_back_copy": server.upload_image_from_oss(self.legalImgBack.url).get("media_id", ""),
- }
- data["company_prove_copy"] = company_prove_copy
- data["special_operation_list"] = special_operation_list
- data["contact_info"] = contact_info
- data["subject_info"] = subject_info
- data["identification_info"] = identification_info
- return data
- def to_ali_auth(self, server):
- """
- 转换阿里所需要的实名信息
- """
- businessCode = "{}{}".format(datetime.datetime.now().strftime("%Y%m%d%H%M%S"), random.randint(1000, 9999)),
- self.aliBusinessCode = businessCode
- self.save()
- data = {
- "out_biz_no": businessCode,
- "extra_credentials": {"smid_list": [self.subAliMerchantId]}
- }
- if self.is_personal:
- contact_person_info = {
- "contact_name": self.legalName,
- "contact_phone_no": self.phoneNumber,
- "contact_card_no": self.legalCardNo
- }
- auth_identity_info = {
- "identity_type": "MSE",
- "support_credentials": {
- "merchant_type": "STORE",
- "store_name": self.shortName,
- "province_code": "",
- "province": self.province.name,
- "city_code": "",
- "city": self.city.name,
- "district_code": "",
- "district": self.district.name,
- "store_address": self.address,
- "store_door_img": server.upload_image_from_oss(self.shopImgA.url).get("media_id", ""),
- "store_inner_img": server.upload_image_from_oss(self.shopImgB.url).get("media_id", ""),
- }
- }
- legal_person_info = {
- "card_type": "RESIDENT",
- "person_name": self.legalName,
- "card_no": self.legalCardNo,
- "effect_time": self.legalStart,
- "expire_time": self.legalEnd,
- "card_front_img": server.upload_image_from_oss(self.legalImgFront.url).get("media_id", ""),
- "card_back_img": server.upload_image_from_oss(self.legalImgBack.url).get("media_id", "")
- }
- elif self.is_company:
- contact_person_info = {
- "contact_name": self.contactName,
- "contact_phone_no": self.phoneNumber,
- "contact_card_no": self.contactCardNo
- }
- auth_identity_info = {
- "identity_type": "ENTERPRISE",
- "certificate_type": "BUSINESS_CERT",
- "certificate_info": {
- "cert_no": self.organizationcode,
- "cert_image": server.upload_image_from_oss(self.organizationImg.url).get("media_id", ""),
- "merchant_name": self.organizationName,
- "legal_person_name": self.legalName,
- "register_address": self.organizationAddr,
- "effect_time": self.organizationStart,
- "expire_time": self.organizationEnd
- }
- }
- legal_person_info = {
- "card_type": "RESIDENT",
- "person_name": self.legalName,
- "card_no": self.legalCardNo,
- "effect_time": self.legalStart,
- "expire_time": self.legalEnd,
- "card_front_img": server.upload_image_from_oss(self.legalImgFront.url).get("media_id", ""),
- "card_back_img": server.upload_image_from_oss(self.legalImgBack.url).get("media_id", "")
- }
- elif self.is_individualbiss:
- contact_person_info = {
- "contact_name": self.contactName,
- "contact_phone_no": self.phoneNumber,
- "contact_card_no": self.contactCardNo
- }
- auth_identity_info = {
- "identity_type": "IND_BIZ",
- "certificate_type": "BUSINESS_CERT",
- "certificate_info": {
- "cert_no": self.organizationcode,
- "cert_image": server.upload_image_from_oss(self.organizationImg.url).get("media_id", ""),
- "merchant_name": self.organizationName,
- "legal_person_name": self.legalName,
- "register_address": self.organizationAddr,
- "effect_time": self.organizationStart,
- "expire_time": self.organizationEnd
- }
- }
- legal_person_info = {
- "card_type": "RESIDENT",
- "person_name": self.legalName,
- "card_no": self.legalCardNo,
- "effect_time": self.legalStart,
- "expire_time": self.legalEnd,
- "card_front_img": server.upload_image_from_oss(self.legalImgFront.url).get("media_id", ""),
- "card_back_img": server.upload_image_from_oss(self.legalImgBack.url).get("media_id", "")
- }
- else:
- contact_person_info = {
- "contact_name": self.contactName,
- "contact_phone_no": self.phoneNumber,
- "contact_card_no": self.contactCardNo
- }
- auth_identity_info = {
- "identity_type": "IND_BIZ",
- "certificate_type": "REGISTER_CERT",
- "certificate_info": {
- "cert_type": self.certType,
- "cert_no": self.certNo,
- "cert_image": server.upload_image_from_oss(self.certImg.url).get("media_id", ""),
- "merchant_name": self.certName,
- "legal_person_name": self.legalName,
- "register_address": self.certAddr,
- "effect_time": self.certStart,
- "expire_time": self.certEnd
- }
- }
- legal_person_info = {
- "card_type": "RESIDENT",
- "person_name": self.legalName,
- "card_no": self.legalCardNo,
- "effect_time": self.legalStart,
- "expire_time": self.legalEnd,
- "card_front_img": server.upload_image_from_oss(self.legalImgFront.url).get("media_id", ""),
- "card_back_img": server.upload_image_from_oss(self.legalImgBack.url).get("media_id", "")
- }
- employer_letter_img = server.upload_image_from_oss(self.certificateFile.url).get("media_id", "")
- data["employer_letter_img"] = employer_letter_img
- data["contact_person_info"] = contact_person_info
- data["auth_identity_info"] = auth_identity_info
- data["legal_person_info"] = legal_person_info
- return data
- def update_sub_merchant(self, **kwargs):
- self.subAliMerchantId = kwargs["subAliMerchantId"]
- self.subMerchantId = kwargs["subMerchantId"]
- return self.save()
- def get_help_info(self):
- return {
- # 帮助按钮的链接
- "helpHtml": "http://mp.weixin.qq.com/s?__biz=MzU2NDQ1MTM2NQ==&mid=2247483688&idx=1&sn=d4f935020d8051d7af1236019a76eae3&chksm=fc4b8062cb3c0974b47b75036012e01a28ba88172f91f3f63abbb23d177a25526671ae1d77e1&scene=18#wechat_redirect",
- # 帮助的文字 或提示信息
- "helpMessage": self.get_help_message()
- }
- def get_help_message(self):
- return u"您的实名申请已经通过审核,请点击下方按钮前往确认实名意愿"
- def get_merchant_info(self):
- """
- 获取商户的信息
- """
- data = {
- # 商户号
- "merchantNo": self.customerNum,
- # 商户的状态
- "status": self.status,
- # 提交资料的时间
- "created": self.dateTimeAdded,
- # 联系人
- "contactName": self.contactName,
- # 联系电话
- "contactPhone": self.phoneNumber,
- # 登录账号:
- "regEmail": self.phoneNumber,
- # 数据的更新时间
- "updated": self.dateTimeUpdated
- }
- return data
- @property
- def is_wechat_submit(self):
- return self.wxSource.applymentId
- @property
- def is_ali_submit(self):
- """
- 阿里的 暂时都视为已经提交
- """
- return True
- def create_app(self):
- return JDOpenPayApp.get_or_create_by_merchant(self)
|