models.py 120 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127
  1. # -*- coding: utf-8 -*-
  2. #!/usr/bin/env python
  3. import requests
  4. from typing import TYPE_CHECKING, Optional
  5. import datetime
  6. import logging
  7. import os
  8. import random
  9. from django.conf import settings
  10. from mongoengine import StringField, EmbeddedDocument, EmbeddedDocumentField, DateTimeField, IntField, MapField, \
  11. BooleanField, LazyReferenceField, EmbeddedDocumentListField
  12. from apilib.monetary import JDMerchantPermillage
  13. from apps.web.core import ROLE
  14. from apps.web.core.db import Searchable, JDMerchantPermillageField
  15. from apps.web.core.file import AliOssFileUploader
  16. from apps.web.core.models import JDOpenPayApp, CustomerPayRelation, JDAggrePayApp
  17. from apps.web.merchant.constant import COMPANY_TYPE, PRIATE_OR_PUBLIC, MerchantStatus, ProductType, ProductStatus, \
  18. ProductRateType, DEFAULT_TRADE_FEE, WechatSubjectType, IdentificationType, CertType, MicroBizType, MERCHANT_OWNER_ROLE, MerchantVersion, MerchantLogAction, ContactType, \
  19. JdOpenMerchantType, JdOpenMerchantStatus
  20. from apps.web.merchant.signal import merchant_user_submit, merchant_jd_access, create_customer_success, create_settle_success, create_shop_success, upload_attach_success, \
  21. complete_success, merchant_enter
  22. from library.jdopen.constants import OPEN_SECRET_KEY, OPEN_ACCESS_KEY
  23. if TYPE_CHECKING:
  24. from apps.web.core.bridge.wechat.v3api import WechatApiProxy
  25. from apps.web.dealer.models import Dealer
  26. from apps.web.agent.models import Agent
  27. logger = logging.getLogger(__name__)
  28. class MerchantLog(Searchable):
  29. """
  30. 商户的日志表
  31. """
  32. merchantId = StringField(verbose_name=u"商户的ID")
  33. action = StringField(verbose_name="u操作动作", choices=MerchantLogAction.choices())
  34. dateTimeAdded = DateTimeField(verbose_name=u"操作时间", default=datetime.datetime.now)
  35. description = StringField(verbose_name=u"描述")
  36. meta = {
  37. 'collection': 'merchant_log',
  38. 'db_alias': 'logdata'
  39. }
  40. @classmethod
  41. def create_one(cls, merchantId, action, description=""):
  42. cls(
  43. merchantId=merchantId,
  44. action=action,
  45. description=description
  46. ).save()
  47. @classmethod
  48. def submit(cls, merchantId, description=""):
  49. """
  50. 创建 提交/修改数据完毕 的记录
  51. """
  52. return cls.create_one(
  53. merchantId, MerchantLogAction.SUBMIT, str(description)
  54. )
  55. @classmethod
  56. def add_app(cls, merchantId, description=""):
  57. return cls.create_one(
  58. merchantId, MerchantLogAction.ADD_JD_APP, str(description)
  59. )
  60. @classmethod
  61. def change_pay_type(cls, merchantId, description=""):
  62. return cls.create_one(
  63. merchantId, MerchantLogAction.CHANGE_PAY_APP, str(description)
  64. )
  65. @classmethod
  66. def submit_wechat(cls, merchantId, description=""):
  67. return cls.create_one(
  68. merchantId, MerchantLogAction.SUBMIT_WECHAT, str(description)
  69. )
  70. @classmethod
  71. def submit_ali(cls, merchantId, description=""):
  72. return cls.create_one(
  73. merchantId, MerchantLogAction.SUBMIT_ALI, str(description)
  74. )
  75. @classmethod
  76. def auth_apply_success(cls, merchantId, description=""):
  77. return cls.create_one(
  78. merchantId, MerchantLogAction.AUTH_APPLY_SUCCESS, str(description)
  79. )
  80. @classmethod
  81. def fail(cls, merchantId, description=""):
  82. return cls.create_one(
  83. merchantId, MerchantLogAction.FAIL, str(description)
  84. )
  85. class MerchantAgent(Searchable):
  86. """
  87. 将商户号 和 代理商账号绑定起来 这样方便 代理商收取手续费的时候 直接从相应的网关获取
  88. """
  89. agentNo = StringField(verbose_name="商户号的服务商商户号")
  90. agentId = StringField(verbose_name="服务商的agentId", default="")
  91. agentSystemId = StringField(verbose_name="服务商的systemId", default="")
  92. dateTimeAdded = DateTimeField(verbose_name="添加进来的时间")
  93. def __str__(self):
  94. return self.agentNo
  95. @classmethod
  96. def get_agent_id(cls, agentSystemId):
  97. merchantAgent = cls.objects.filter(agentSystemId=agentSystemId).first() or cls()
  98. return merchantAgent.agentId
  99. @classmethod
  100. def default_merchant_agent(cls):
  101. wflSystemId = os.environ.get("JD_SYSTEM_ID") or "112122276PSP"
  102. return cls.objects.filter(agentSystemId=wflSystemId).first()
  103. class LadderList(EmbeddedDocument):
  104. type = StringField(default="1")
  105. minVal = StringField(default="0")
  106. maxVal = StringField(default="1000")
  107. cardType = StringField(default="DE")
  108. fee = JDMerchantPermillageField(default=JDMerchantPermillage(DEFAULT_TRADE_FEE))
  109. maxfee = StringField("1000000")
  110. def to_dict(self):
  111. return {
  112. "type": self.type,
  113. "minVal": self.minVal,
  114. "maxVal": self.maxVal,
  115. "cardType": self.cardType,
  116. "fee": self.fee,
  117. "maxfee": self.maxfee
  118. }
  119. class MerchantProduct(EmbeddedDocument):
  120. productId = StringField(verbose_name=u"产品编码", choices=ProductType.choices())
  121. status = IntField(verbose_name=u"产品的开通状态", choices=ProductStatus.choices(), default=ProductStatus.INIT)
  122. rateType = StringField(verbose_name=u"产品的费率类型", choices=ProductRateType.choices(), default=ProductRateType.PERCENTAGE)
  123. mfee = JDMerchantPermillageField(verbose_name=u"产品的费率 一般就是之前经销商的提现的费率 由代理商设置 需要注意的是发送给金东的时候 单位是100%", default=JDMerchantPermillage(6))
  124. payToolId = StringField(verbose_name=u"支付工具的ID 固定值", default="0")
  125. # ladderList = ListField(verbose_name = u'京东的固定的费率(只有当产品id是403的时候这个字段才有用)')
  126. ladderList = EmbeddedDocumentField(verbose_name = u'京东的固定的费率(只有当产品id是403的时候这个字段才有用)', document_type=LadderList)
  127. def support_apply(self):
  128. """
  129. 产品是否支持开通 主要看状态 初始化的产品可以开通
  130. """
  131. return self.status == ProductStatus.INIT
  132. def to_wait(self):
  133. self.status = ProductStatus.WAITING
  134. self.save()
  135. def to_fail(self):
  136. self.status = ProductStatus.FAIL
  137. self.save()
  138. def to_success(self):
  139. self.status = ProductStatus.SUCCESS
  140. self.save()
  141. @classmethod
  142. def created_product(cls, productId, mfee):
  143. product = cls(productId=productId)
  144. product.mfee = mfee
  145. # jd 的支付方式 加上费率阶梯
  146. if product.productId == ProductType.JD:
  147. ladderMap = LadderList()
  148. ladderMap.fee = mfee
  149. product.ladderList = ladderMap
  150. return product
  151. class MerchantAddress(Searchable):
  152. name = StringField(verbose_name=u"行政区名称", required=True)
  153. code = StringField(verbose_name=u"行政区代码", required=True)
  154. parentCode = StringField(verbose_name=u"父级code")
  155. def to_dict(self):
  156. result = {
  157. "name": self.name,
  158. "code": self.code,
  159. }
  160. if self.parentCode != "000000":
  161. result.update({"parentCode": self.parentCode})
  162. return result
  163. @classmethod
  164. def get_name(cls, code):
  165. record = cls.objects.filter(code=code).first()
  166. return record.name if record else ""
  167. @classmethod
  168. def get_all(cls):
  169. return [_addr.to_dict() for _addr in cls.objects.all()]
  170. @classmethod
  171. def get_addr_by_parent(cls, parentCode=None):
  172. if parentCode is None:
  173. parentCode = "000000"
  174. return [_addr.to_dict() for _addr in cls.objects.filter(parentCode=parentCode)]
  175. @classmethod
  176. def get_provide_code(cls, provinceName):
  177. """
  178. 获取省级code
  179. """
  180. try:
  181. province = cls.objects.get(name=provinceName, parentCode="000000") # type: MerchantAddress
  182. except Exception as e:
  183. logger.error("get province <{}> code error = {}".format(provinceName, e))
  184. return ""
  185. return province.code
  186. @classmethod
  187. def get_city_code(cls, cityName, provinceCode):
  188. try:
  189. city = cls.objects.get(name=cityName, parentCode=provinceCode) # type: MerchantAddress
  190. except Exception as e:
  191. logger.error("get province <{}> city <{}> code error = {}".format(provinceCode, cityName, e))
  192. return ""
  193. return city.code
  194. @classmethod
  195. def get_area_code(cls, areaName, cityCode):
  196. try:
  197. area = cls.objects.get(name=areaName, parentCode=cityCode) # type: MerchantAddress
  198. except Exception as e:
  199. logger.error("get city <{}> area <{}> code error = {}".format(cityCode, areaName, e))
  200. return ""
  201. return area.code
  202. class WxMerchantAddress(Searchable):
  203. name = StringField(verbose_name=u"地址")
  204. code = StringField(verbose_name=u"编码")
  205. @classmethod
  206. def get_code(cls, name):
  207. try:
  208. return cls.objects.get(name=name).code
  209. except Exception:
  210. return "440305"
  211. # 营业执照信息
  212. class BusinessLicenceInfo(EmbeddedDocument):
  213. """营业执照"""
  214. licenceNumber = StringField(verbose_name=u"营业执照注册号")
  215. licenceCopy = StringField(verbose_name=u"营业执照照片URL")
  216. merchantName = StringField(verbose_name=u"商户简称")
  217. legalPerson = StringField(verbose_name=u"法人姓名")
  218. companyAddress = StringField(verbose_name=u"注册地址")
  219. licenceStart = StringField(verbose_name=u"营业执照起始日期")
  220. licenceEnd = StringField(verbose_name=u"营业执照结束日期")
  221. def to_apply(self, server): # type:(WechatApiProxy) -> dict
  222. licenceCopy = AliOssFileUploader.load(self.licenceCopy)
  223. response = server.upload_image(licenceCopy, os.path.basename(self.licenceCopy))
  224. return {
  225. "licence_number": self.licenceNumber,
  226. "licence_copy": response.get("media_id", ""),
  227. "merchant_name": self.merchantName,
  228. "legal_person": self.legalPerson,
  229. "company_address": self.companyAddress,
  230. "licence_valid_date": '["{}","{}"]'.format(self.licenceStart, self.licenceEnd),
  231. }
  232. def save_certificate_info(self, businessLicenceInfo):
  233. self.licenceNumber = businessLicenceInfo["busCode"]
  234. self.licenceCopy = businessLicenceInfo["busLicenseUrl"]
  235. self.merchantName = businessLicenceInfo["busName"]
  236. self.legalPerson = businessLicenceInfo["busLegal"]
  237. self.companyAddress = "{}{}{}{}".format(
  238. businessLicenceInfo["province"]["name"],
  239. businessLicenceInfo["city"]["name"],
  240. businessLicenceInfo["area"]["name"],
  241. businessLicenceInfo["addr"],
  242. )
  243. self.licenceStart = businessLicenceInfo["startTime"]
  244. self.licenceEnd = businessLicenceInfo["endTime"]
  245. # 登记证书信息
  246. class CertificateInfo(EmbeddedDocument):
  247. """登记证书"""
  248. certType = StringField(verbose_name=u"登记证书类型", choices=CertType.choices())
  249. certNumber = StringField(verbose_name=u"证书编号")
  250. certCopy = StringField(verbose_name=u"证书的照片URL")
  251. merchantName = StringField(verbose_name=u"商户简称")
  252. legalPerson = StringField(verbose_name=u"法人姓名")
  253. companyAddress = StringField(verbose_name=u"注册地址")
  254. certStart = StringField(verbose_name=u"证书起始日期")
  255. certEnd = StringField(verbose_name=u"证书结束日期")
  256. def to_apply(self, server): # type:(WechatApiProxy) -> dict
  257. certCopy = AliOssFileUploader.load(self.certCopy)
  258. response = server.upload_image(certCopy, os.path.basename(self.certCopy))
  259. return {
  260. "cert_type": self.certType,
  261. "cert_number": self.certNumber,
  262. "cert_copy": response.get("media_id", ""),
  263. "merchant_name": self.merchantName,
  264. "legal_person": self.legalPerson,
  265. "company_address": self.companyAddress,
  266. "cert_valid_date": '["{}","{}"]'.format(self.certStart, self.certEnd),
  267. }
  268. # 辅助材料信息
  269. class AssistProveInfo(EmbeddedDocument):
  270. """辅助材料证明"""
  271. microBizType = StringField(verbose_name=u"小微商户类型", default=MicroBizType.MICRO_TYPE_STORE.code, choices=MicroBizType.choices())
  272. storeName = StringField(verbose_name=u"门店名称")
  273. # 省市县 以,分割
  274. storeAddressCode = StringField(verbose_name=u"门店的地址的code")
  275. storeAddress = StringField(verbose_name=u"门店的地址 具体区、街道")
  276. storeHeaderCopy = StringField(verbose_name=u"门头照")
  277. storeIndoorCopy = StringField(verbose_name=u"门内照")
  278. @staticmethod
  279. def load_addr_code(p, c, a):
  280. return WxMerchantAddress.get_code("{}{}{}".format(p, c, a))
  281. def to_apply(self, server): # type:(WechatApiProxy) -> dict
  282. storeHeaderCopy = AliOssFileUploader.load(self.storeHeaderCopy)
  283. responseHeader = server.upload_image(storeHeaderCopy, os.path.basename(self.storeHeaderCopy))
  284. storeIndoorCopy = AliOssFileUploader.load(self.storeIndoorCopy)
  285. responseIndoor = server.upload_image(storeIndoorCopy, os.path.basename(self.storeIndoorCopy))
  286. return {
  287. "micro_biz_type": self.microBizType,
  288. "store_name": self.storeName,
  289. "store_address_code": self.storeAddressCode,
  290. "store_address": self.storeAddress,
  291. "store_header_copy": responseHeader.get("media_id"),
  292. "store_indoor_copy": responseIndoor.get("media_id")
  293. }
  294. def save_certificate_info(self, assistProveInfo):
  295. self.storeName = assistProveInfo["storeShotName"]
  296. self.storeHeaderCopy = assistProveInfo["storeAUrl"]
  297. self.storeIndoorCopy = assistProveInfo["storeBUrl"]
  298. province = assistProveInfo["province"]["name"]
  299. city = assistProveInfo["city"]["name"]
  300. area = assistProveInfo["area"]["name"]
  301. self.storeAddress = assistProveInfo["addr"]
  302. self.storeAddressCode = self.load_addr_code(province, city, area)
  303. return self
  304. # 法人相关信息
  305. class LegalPersonInfo(EmbeddedDocument):
  306. """
  307. 法人信息
  308. """
  309. mainType = StringField(verbose_name=u"法人证件类型(目前仅支持身份证)", default=IdentificationType.IDENTIFICATION_TYPE_IDCARD.code, choices=IdentificationType.choices())
  310. lepName = StringField(verbose_name=u"法人姓名")
  311. lepCardNo = StringField(verbose_name=u"法人身份证号")
  312. lepCardStart = StringField(verbose_name=u"法人身份证起始日期")
  313. lepCardEnd = StringField(verbose_name=u"法人身份证结束日期")
  314. lepCardUrlA = StringField(verbose_name=u"法人身份证人像面")
  315. lepCardUrlB = StringField(verbose_name=u"法人身份证国徽面")
  316. # 以下都是不需要的
  317. lepProvinceCode = StringField(verbose_name=u"法人身份证 省CODE")
  318. lepCityCode = StringField(verbose_name=u"法人身份证 市CODE")
  319. lepAreaCode = StringField(verbose_name=u"法人身份证 区CODE")
  320. lepProvince = StringField(verbose_name=u"法人身份证 省")
  321. lepCity = StringField(verbose_name=u"法人身份证 市")
  322. lepArea = StringField(verbose_name=u"法人身份证 区")
  323. lepAddr = StringField(verbose_name=u"法人地址 详细")
  324. def to_apply(self, server): # type:(WechatApiProxy) -> dict
  325. """
  326. 法人的有三个信息需要加密处理 两个图片信息需要上传处理
  327. """
  328. # 上传图片 并获取其中的 media_id
  329. lepCardContentA = AliOssFileUploader.load(self.lepCardUrlA)
  330. responseA = server.upload_image(lepCardContentA, os.path.basename(self.lepCardUrlA))
  331. lepCardContentB = AliOssFileUploader.load(self.lepCardUrlB)
  332. responseB = server.upload_image(lepCardContentB, os.path.basename(self.lepCardUrlB))
  333. return {
  334. "identification_type": self.mainType,
  335. "identification_name": server.rsa_encrypt(self.lepName),
  336. "identification_number": server.rsa_encrypt(self.lepCardNo),
  337. "identification_address": server.rsa_encrypt("{}{}{}{}".format(self.lepProvince, self.lepCity, self.lepArea, self.lepAddr)),
  338. "identification_valid_date": '["{}","{}"]'.format(self.lepCardStart, self.lepCardEnd),
  339. "identification_front_copy": responseA.get("media_id", ""),
  340. "identification_back_copy": responseB.get("media_id", ""),
  341. "owner": True
  342. }
  343. def save_certificate_info(self, legalInfo):
  344. self.lepName = legalInfo["name"]
  345. self.lepCardNo = legalInfo["cardNo"]
  346. self.lepCardStart = legalInfo["startTime"]
  347. self.lepCardEnd = legalInfo["endTime"]
  348. self.lepCardUrlA = legalInfo["urlA"]
  349. self.lepCardUrlB = legalInfo["urlB"]
  350. self.lepProvinceCode = legalInfo["province"]["code"]
  351. self.lepCityCode = legalInfo["city"]["code"]
  352. self.lepAreaCode = legalInfo["area"]["code"]
  353. self.lepProvince = legalInfo["province"]["name"]
  354. self.lepCity = legalInfo["city"]["name"]
  355. self.lepArea = legalInfo["area"]["name"]
  356. self.lepAddr = legalInfo["addr"]
  357. return self
  358. # 经营主体相关信息
  359. class SubjectInfo(EmbeddedDocument):
  360. """
  361. 主体信息 最为关键的信息 主要是种类繁多 根据主体的类型会有变化
  362. """
  363. mainType = StringField(verbose_name=u"主体的类型", choices=WechatSubjectType.choices())
  364. businessLicenceInfo = EmbeddedDocumentField(verbose_name="营业执照信息" ,document_type=BusinessLicenceInfo)
  365. certificateInfo = EmbeddedDocumentField(verbose_name=u"登记证书信息", document_type=CertificateInfo)
  366. companyProveCopy = StringField(verbose_name=u"单位证明函照片")
  367. assistProveInfo = EmbeddedDocumentField(verbose_name=u"辅助材料证明", document_type=AssistProveInfo)
  368. def to_apply(self, server): # type:(WechatApiProxy) -> dict
  369. data = {
  370. "subject_type": self.mainType,
  371. }
  372. # 存在营业执照信息 企业类型
  373. if self.businessLicenceInfo:
  374. data["business_licence_info"] = self.businessLicenceInfo.to_apply(server)
  375. # 登记证书 事业单位和其他组织都需要
  376. if self.certificateInfo:
  377. data["certificate_info"] = self.certificateInfo.to_apply(server)
  378. # 事业单位必带
  379. if self.companyProveCopy:
  380. companyProveCopy = AliOssFileUploader.load(self.companyProveCopy)
  381. response = server.upload_image(companyProveCopy, os.path.basename(self.companyProveCopy))
  382. data["company_prove_copy"] = response.get("media_id", "")
  383. # 小微企业必须有
  384. if self.assistProveInfo:
  385. data["assist_prove_info"] = self.assistProveInfo.to_apply(server)
  386. return data
  387. def save_certificate_info(self, businessLicenceInfo=None, certificateInfo=None, companyProveCopy=None, assistProveInfo=None):
  388. if businessLicenceInfo:
  389. self.businessLicenceInfo = self.businessLicenceInfo or BusinessLicenceInfo()
  390. return self.businessLicenceInfo.save_certificate_info(businessLicenceInfo)
  391. elif certificateInfo:
  392. self.certificateInfo = self.certificateInfo or CertificateInfo()
  393. return self.certificateInfo.save_certificate_info(certificateInfo)
  394. elif companyProveCopy:
  395. self.companyProveCopy = companyProveCopy
  396. else:
  397. self.assistProveInfo = self.assistProveInfo or AssistProveInfo()
  398. return self.assistProveInfo.save_certificate_info(assistProveInfo)
  399. # 联系人相关信息
  400. class ContactPersonInfo(EmbeddedDocument):
  401. """
  402. 联系人信息
  403. """
  404. mainType = StringField(verbose_name=u"联系人证件类型(目前仅支持身份证)", default=IdentificationType.IDENTIFICATION_TYPE_IDCARD.code, choices=IdentificationType.choices())
  405. contactType = StringField(verbose_name=u"联系人的类型", choices=ContactType.choices(), default=ContactType.LEGAL.code)
  406. businessAuthorizationLetter = StringField(verbose_name="业务办理授权函", default="")
  407. contactName = StringField(verbose_name=u"联系人姓名")
  408. contactMobile = StringField(verbose_name=u"联系人手机号")
  409. contactCardNo = StringField(verbose_name=u"联系人身份证号")
  410. # 以下四个信息是保存供显示 并不发送到微信
  411. contactCardStart = StringField(verbose_name=u"联系人身份证起始日期")
  412. contactCardEnd = StringField(verbose_name=u"联系人身份证结束日期")
  413. contactCardUrlA = StringField(verbose_name=u"联系人身份证人像面")
  414. contactCardUrlB = StringField(verbose_name=u"联系人身份证国徽面")
  415. contactProvinceCode = StringField(verbose_name=u"联系人身份证 省CODE")
  416. contactCityCode = StringField(verbose_name=u"联系人身份证 市CODE")
  417. contactAreaCode = StringField(verbose_name=u"联系人身份证 区CODE")
  418. contactProvince = StringField(verbose_name=u"联系人身份证 省")
  419. contactCity = StringField(verbose_name=u"联系人身份证 市")
  420. contactArea = StringField(verbose_name=u"联系人身份证 区")
  421. contactAddr = StringField(verbose_name=u"联系人地址 详细")
  422. def to_apply(self, server): # type:(WechatApiProxy) -> dict
  423. """
  424. 联系人的三个信息都需要加密进行处理
  425. """
  426. baseData = {
  427. "contact_type": str(self.contactType),
  428. "name": server.rsa_encrypt(self.contactName),
  429. "mobile": server.rsa_encrypt(self.contactMobile),
  430. "id_card_number": server.rsa_encrypt(self.contactCardNo)
  431. }
  432. if self.contactType == ContactType.SUPER:
  433. baseData["contact_id_doc_type"] = str(self.mainType)
  434. baseData["contact_id_doc_copy"] = server.upload_image_from_oss(self.contactCardUrlA).get("media_id", "")
  435. baseData["contact_id_doc_copy_back"] = server.upload_image_from_oss(self.contactCardUrlB).get("media_id", "")
  436. baseData["contact_period_begin"] = self.contactCardStart
  437. baseData["contact_period_end"] = self.contactCardEnd
  438. baseData["business_authorization_letter"] = server.upload_image_from_oss(self.businessAuthorizationLetter).get("media_id", "")
  439. return baseData
  440. def save_certificate_info(self, contactInfo):
  441. self.contactType = contactInfo["contactType"]
  442. self.businessAuthorizationLetter = contactInfo["businessAuthorizationLetter"]
  443. self.contactName = contactInfo["name"]
  444. self.contactCardNo = contactInfo["cardNo"]
  445. self.contactCardStart = contactInfo["startTime"]
  446. self.contactCardEnd = contactInfo["endTime"]
  447. self.contactCardUrlA = contactInfo["urlA"]
  448. self.contactCardUrlB = contactInfo["urlB"]
  449. self.contactProvinceCode = contactInfo["province"]["code"]
  450. self.contactCityCode = contactInfo["city"]["code"]
  451. self.contactAreaCode = contactInfo["area"]["code"]
  452. self.contactProvince = contactInfo["province"]["name"]
  453. self.contactCity = contactInfo["city"]["name"]
  454. self.contactArea = contactInfo["area"]["name"]
  455. self.contactAddr = contactInfo["addr"]
  456. return self
  457. def save_mobile_info(self, mobile):
  458. self.contactMobile = mobile
  459. return self
  460. # 商户的实名申请信息
  461. class WechatApplyMerchant(Searchable):
  462. """
  463. 微信侧申请商户号所需要的资料
  464. """
  465. # 原始的资料信息
  466. contactInfo = EmbeddedDocumentField(verbose_name = u"联系人信息", document_type = ContactPersonInfo, default=ContactPersonInfo)
  467. legalInfo = EmbeddedDocumentField(verbose_name = u"法人信息", document_type = LegalPersonInfo, default=LegalPersonInfo)
  468. subjectInfo = EmbeddedDocumentField(verbose_name = u"经营主体信息", document_type = SubjectInfo, default=SubjectInfo)
  469. # 微信的业务申请信息
  470. channelId = StringField(verbose_name=u"渠道商户号")
  471. subMerchantId = StringField(verbose_name=u"微信子商户编号")
  472. applymentId = StringField(verbose_name=u"申请的ID")
  473. businessCode = StringField(verbose_name=u"业务申请编号")
  474. # 支付宝的业务申请信息
  475. subAliMerchantId = StringField(verbose_name=u"支付宝的子商编")
  476. aliApplymentId = StringField(verbose_name=u"支付宝的申请编号")
  477. aliBusinessCode = StringField(verbose_name=u"支付宝的业务编号")
  478. def update_sub_merchant(self, **kwargs):
  479. if "channel" in kwargs:
  480. self.channelId = kwargs["channel"]
  481. if "subMchId" in kwargs:
  482. self.subMerchantId = kwargs["subMchId"]
  483. if "subCustomerNum" in kwargs:
  484. self.subAliMerchantId = kwargs["subCustomerNum"]
  485. return self.save()
  486. def to_apply(self, server): # type:(WechatApiProxy) -> dict
  487. # 申请的时候 申请单编号刷新
  488. business_code = "{}_{}_{}".format(self.channelId, self.subMerchantId, datetime.datetime.now().strftime("%Y%m%d%H%M%S"))
  489. self.businessCode = business_code
  490. self.save()
  491. # 获取联系人类型 小微商户和个人卖家 则联系人类型为法人;其余的 可选法人 或 经办人
  492. if self.subjectInfo.mainType == WechatSubjectType.SUBJECT_TYPE_MICRO:
  493. contact_type = "LEGAL"
  494. else:
  495. if self.contactInfo.contactCardNo == self.legalInfo.lepCardNo:
  496. contact_type = "LEGAL"
  497. else:
  498. contact_type = "SUPER"
  499. # 根据联系人的类型 决定上传数据的不同
  500. if contact_type == "LEGAL":
  501. contact_info = {
  502. "contact_type": contact_type,
  503. "name": server.rsa_encrypt(self.contactInfo.contactName),
  504. "mobile": server.rsa_encrypt(self.contactInfo.contactMobile),
  505. "id_card_number": server.rsa_encrypt(self.contactInfo.contactCardNo)
  506. }
  507. else:
  508. contact_info = {
  509. "contact_type": contact_type,
  510. "name": server.rsa_encrypt(self.contactInfo.contactName),
  511. "contact_id_doc_type": IdentificationType.IDENTIFICATION_TYPE_IDCARD.code,
  512. "id_card_number": server.rsa_encrypt(self.contactInfo.contactCardNo),
  513. "contact_id_doc_copy": server.upload_image_from_oss(self.contactInfo.contactCardUrlA).get("media_id", ""),
  514. "contact_id_doc_copy_back": server.upload_image_from_oss(self.contactInfo.contactCardUrlB).get("media_id", ""),
  515. "contact_period_begin": self.contactInfo.contactCardStart,
  516. "contact_period_end": self.contactInfo.contactCardEnd,
  517. "business_authorization_letter": server.upload_image_from_oss(self.contactInfo.businessAuthorizationLetter).get("media_id", ""),
  518. "mobile": server.rsa_encrypt(self.contactInfo.contactMobile)
  519. }
  520. return {
  521. "channel_id": self.channelId,
  522. "business_code": business_code,
  523. "contact_info": contact_info,
  524. "subject_info": self.subjectInfo.to_apply(server),
  525. "identification_info": self.legalInfo.to_apply(server),
  526. "addition_info": {
  527. "confirm_mchid_list": [self.subMerchantId]
  528. }
  529. }
  530. def to_ali_submit(self, applymentId, businessCode=""):
  531. self.aliApplymentId = str(applymentId)
  532. if businessCode:
  533. self.aliBusinessCode = businessCode
  534. return self.save()
  535. def to_wechat_submit(self, applymentId, businessCode=""):
  536. self.applymentId = str(applymentId)
  537. if businessCode:
  538. self.businessCode = businessCode
  539. return self.save()
  540. def to_success(self, applymentId, businessCode=""):
  541. """
  542. 申请成功之后 写入申请单的编号
  543. """
  544. def to_cancel(self):
  545. """
  546. 取消申请单成功后 将此次申请的参数全部清除
  547. """
  548. self.applymentId = ""
  549. self.businessCode = ""
  550. return self.save()
  551. # 京东商户申请所需信息
  552. class MerchantSourceInfo(Searchable):
  553. """
  554. 京东申请所需要的材料
  555. """
  556. ownerId = StringField(verbose_name=u"商户拥有者的ID")
  557. ownerRole = StringField(verbose_name=u"商户拥有者身份", choices=MERCHANT_OWNER_ROLE.choices(), default=MERCHANT_OWNER_ROLE.DEALER)
  558. merchantAgent = LazyReferenceField(verbose_name="商户号的服务商", document_type=MerchantAgent )
  559. serial_no = StringField(verbose_name=u"订单流水号")
  560. merchantNo = StringField(verbose_name=u"商户号")
  561. desKey = StringField(verbose_name=u"商户密钥")
  562. mdKey = StringField(verbose_name=u"商户md")
  563. status = IntField(verbose_name=u"商户的状态", choices=MerchantStatus.choices(), default=MerchantStatus.INIT)
  564. merchantType = StringField(verbose_name=u"商户性质", choices=COMPANY_TYPE.choices())
  565. errorDescription = StringField(verbose_name=u"失败原因", default="")
  566. dateTimeAdded = DateTimeField(verbose_name=u"创建时间")
  567. dateTimeUpdated = DateTimeField(verbose_name=u"状态更新时间")
  568. # 版本信息 用于控制兼容代码
  569. version = StringField(verbose_name=u"商户版本信息", default=None)
  570. # 法人信息
  571. identifyCardAUrl = StringField(verbose_name=u"法人证件(人像)")
  572. identifyCardBUrl = StringField(verbose_name=u"法人证件(国徽)")
  573. identifyCardCUrl = StringField(verbose_name=u"法人证件(手持)")
  574. identifyCardName = StringField(verbose_name=u"法人证件 姓名")
  575. identifyCardCode = StringField(verbose_name=u"法人证件 号码")
  576. identifyCardStartTime = StringField(verbose_name=u"法人证件 起始日期")
  577. identifyCardEndTime = StringField(verbose_name=u"法人证件 结束日期")
  578. identifyCardLongTime = BooleanField(verbose_name=u"法人证件 是否是长期")
  579. identifyCardProvinceCode = StringField(verbose_name="法人 省CODE")
  580. identifyCardCityCode = StringField(verbose_name=u"法人 市CODE")
  581. identifyCardAreaCode = StringField(verbose_name=u"法人 区CODE")
  582. identifyCardProvince = StringField(verbose_name=u"法人 省 ")
  583. identifyCardCity = StringField(verbose_name=u"法人 市")
  584. identifyCardArea = StringField(verbose_name=u"法人 区")
  585. identifyCardAddr = StringField(verbose_name=u"法人 详细地址")
  586. # 联系人信息
  587. contactPersonName = StringField(verbose_name=u"联系人 姓名")
  588. contactPersonPhone = StringField(verbose_name=u"联系人 手机")
  589. contactPersonEmail = StringField(verbose_name="联系人 邮箱")
  590. # 营业执照相关的信息 当商户为企业的时候存在
  591. busLicenseUrl = StringField(verbose_name=u"企业的营业执照")
  592. busName = StringField(verbose_name=u"企业名称")
  593. busCode = StringField(verbose_name=u"营业执照统一社会信用码")
  594. busProvinceCode = StringField(verbose_name=u"营业地址所在省code")
  595. busCityCode = StringField(verbose_name=u"营业地址所在市code")
  596. busAreaCode = StringField(verbose_name=u"营业地址所在区code")
  597. busProvince = StringField(verbose_name=u"营业地址所在省")
  598. busCity = StringField(verbose_name=u"营业地址所在市")
  599. busArea = StringField(verbose_name=u"营业地址所在区")
  600. busAddr = StringField(verbose_name=u"营业地址")
  601. # 结算的相关信息
  602. bankCardUrl = StringField(verbose_name=u"银行卡/开户许可证")
  603. bankCardCode = StringField(verbose_name=u"银行卡/开户许可证 名称")
  604. bankCardName = StringField(verbose_name=u"银行卡/开户许可证 开户行")
  605. bankCardSubCode = StringField(verbose_name=u"银行卡/开户许可证 支行CODE")
  606. bankCardSubName = StringField(verbose_name=u"银行卡/开户许可证 支行名称")
  607. # 经营的相关信息
  608. storeShotName = StringField(verbose_name=u"门店简称")
  609. storeAUrl = StringField(verbose_name=u"门店的照片 门头照")
  610. storeBUrl = StringField(verbose_name=u"门店的照片 出入口")
  611. storeCUrl = StringField(verbose_name=u"门店的照片 店内")
  612. shopProvinceCode = StringField(verbose_name=u"门店所在省code")
  613. shopCityCode = StringField(verbose_name=u"门店所在市code")
  614. shopAreaCode = StringField(verbose_name=u"门店所在地区code")
  615. shopProvince = StringField(verbose_name=u"门店所在省")
  616. shopCity = StringField(verbose_name=u"门店所在市")
  617. shopArea = StringField(verbose_name=u"门店所在地区")
  618. shopAddr = StringField(verbose_name=u"商户所在详细地址")
  619. products = MapField(EmbeddedDocumentField(verbose_name=u"开通的支付产品", document_type=MerchantProduct))
  620. regEmail = StringField(verbose_name=u"注册邮箱号. 也这个作为商户登录账号")
  621. wxApplier = LazyReferenceField(verbose_name=u"微信申请的信息", document_type= WechatApplyMerchant)
  622. def __repr__(self):
  623. return "Merchant Source Info <{}>".format(self.id)
  624. def load_enter_image_info(self):
  625. """
  626. 加载 商户入驻所需要的图片信息
  627. :return:
  628. """
  629. result = dict()
  630. # 营业执照的照片
  631. result['blicUrla'] = self.blicUrla
  632. # 如果是企业用户 还需要上传银行开户许可证的照片
  633. if self.companyType == COMPANY_TYPE.ENTERPRISE:
  634. result['occUrla'] = self.occUrla
  635. # 身份证的照片
  636. result['lepUrla'] = self.lepUrla
  637. result['lepUrlb'] = self.lepUrlb
  638. result['lepUrlc'] = self.lepUrlc
  639. # 门店的照片
  640. result['img'] = self.img
  641. result['enterimg'] = self.enterimg
  642. result['innerimg'] = self.innerimg
  643. # 结算类照片
  644. result['cardPhoto'] = self.cardPhoto
  645. result['settleManPhotoFront'] = self.settleManPhotoFront
  646. result['settleManPhotoBack'] = self.settleManPhotoBack
  647. result['settleHoldingIDCard'] = self.settleHoldingIDCard
  648. return result
  649. def load_enter_entity_info(self):
  650. """
  651. 加载商户进件所需要的 entity的信息
  652. :return:
  653. """
  654. result = dict()
  655. # 首先添加公共类信息 即必传递的信息
  656. result['companyType'] = self.companyType
  657. result['serialNo'] = self.serialNo
  658. result['agentNo'] = self.agentNo
  659. result['regEmail'] = self.regEmail
  660. result['regPhone'] = self.regPhone
  661. result['blicCardType'] = self.blicCardType
  662. result['blicCompanyName'] = self.blicCompanyName
  663. result['abMerchantName'] = self.abMerchantName
  664. # 企业商户需要增加的部分信息
  665. if self.companyType == COMPANY_TYPE.ENTERPRISE:
  666. result['blicUscc'] = self.blicUscc
  667. result['blicScope'] = self.blicScope
  668. result['indTwoCode'] = self.indTwoCode
  669. result['blicProvince'] = self.blicProvince
  670. result['blicCity'] = self.blicCity
  671. result['blicAddress'] = self.blicAddress
  672. result['blicLongTerm'] = self.blicLongTerm
  673. result['blicValidityStart'] = self.blicValidityStart
  674. result['blicValidityEnd'] = self.blicValidityEnd
  675. result['lepCardType'] = self.lepCardType
  676. result['lepName'] = self.lepName
  677. result['lepCardNo'] = self.lepCardNo
  678. result['lepLongTerm'] = self.lepLongTerm
  679. result['lepValidityStart'] = self.lepValidityStart
  680. result['lepValidityEnd'] = self.lepValidityEnd
  681. result['contactName'] = self.contactName
  682. result['contactPhone'] = self.contactPhone
  683. result['contactEmail'] = self.contactEmail
  684. result['contactProvince'] = self.contactProvince
  685. result['contactCity'] = self.contactCity
  686. result['contactAddress'] = self.contactAddress
  687. result['ifPhyStore'] = self.ifPhyStore
  688. result['storeProvince'] = self.storeProvince
  689. result['storeCity'] = self.storeCity
  690. result['storeAddress'] = self.storeAddress
  691. result['settleToCard'] = self.settleToCard
  692. result['priatePublic'] = self.priatePublic
  693. result['bankName'] = self.bankName
  694. result['subBankCode'] = self.subBankCode
  695. result['bankAccountNo'] = self.bankAccountNo
  696. result['bankAccountName'] = self.bankAccountName
  697. result['settleCardPhone'] = self.settleCardPhone
  698. result['settlementPeriod'] = self.settlementPeriod
  699. result['directoryList'] = self.directoryList
  700. # 如果存在商户的商户号 说明是修改了
  701. if self.merchantNo:
  702. result['merchantNo'] = self.merchantNo
  703. return result
  704. def load_product_info(self, product):
  705. """
  706. 加载京东产品申请的产品信息
  707. :return:
  708. """
  709. serialNo = self.generate_serial_no(self.ownerId)
  710. result = {
  711. "agentNo": self.agentNo,
  712. "merchantNo": self.merchantNo,
  713. "serialNo": serialNo,
  714. "productId": product.productId,
  715. "payToolId": product.payToolId,
  716. "mfeeType": product.rateType,
  717. }
  718. if product.productId in [ProductType.WECHAT, ProductType.ALIPAY]:
  719. result.update({"mfee": product.mfee})
  720. elif product.productId in [ProductType.JD]:
  721. result.update({"ladderList": [product.ladderList.to_dict()]})
  722. return result
  723. def load_query_info(self):
  724. """
  725. 获取查询 京东商户的 条件信息
  726. :return:
  727. """
  728. serialNo = self.generate_serial_no(self.ownerId)
  729. result = {
  730. "serialNo": serialNo,
  731. "merchantNo": self.merchantNo,
  732. }
  733. return result
  734. @staticmethod
  735. def load_address_name(code):
  736. return MerchantAddress.get_name(code)
  737. def add_product(self, productType):
  738. """
  739. 初始化微信和支付宝两个产品 wechat alipay
  740. 再加上一个 京东的
  741. """
  742. productId = getattr(ProductType, productType.upper(), None)
  743. assert productId in ProductType.choices(), u"不支持的产品类型"
  744. product = self.products.get(productType)
  745. if product and product.status != ProductStatus.FAIL:
  746. return
  747. # 费率固定为 千分之6
  748. mfee = JDMerchantPermillage(DEFAULT_TRADE_FEE)
  749. self.products[productType] = MerchantProduct.created_product(
  750. productId=productId,
  751. mfee=mfee
  752. )
  753. def is_product_fail(self):
  754. """
  755. 产品有无开通失败的
  756. """
  757. return any(map(lambda x: x.status == ProductStatus.FAIL, self.products.values()))
  758. def is_product_success(self):
  759. """
  760. 产品是否均开通成功
  761. """
  762. return all(map(lambda x: x.status == ProductStatus.SUCCESS, self.products.values()))
  763. def enter_success(self, merchantNo, serialNo):
  764. """
  765. 将商户申请状态切换为 等待 同时初始化 支付产品
  766. """
  767. # 修改的时候不会有 merchantNo
  768. if merchantNo:
  769. self.merchantNo = merchantNo
  770. if serialNo:
  771. self.serial_no = serialNo
  772. self.errorDescription = ""
  773. self.add_product("wechat")
  774. self.add_product("alipay")
  775. self.add_product("jd")
  776. # 重置错误信息
  777. self.save()
  778. merchant_enter.send(sender=self.__class__, merchantId=str(self.id))
  779. return self
  780. def support_apply(self):
  781. """
  782. 是否支持 开通商户产品
  783. """
  784. if self.status != MerchantStatus.WAITING:
  785. return False
  786. if not self.products:
  787. return False
  788. return True
  789. @staticmethod
  790. def load_image_content(url):
  791. """
  792. 获取图像的二进制数据
  793. :return:
  794. """
  795. return AliOssFileUploader.load(url)
  796. @staticmethod
  797. def generate_serial_no(ownerId):
  798. return "{}{}{}".format(datetime.datetime.now().strftime("%Y%m%d%H%M%S"), ownerId, random.randint(1000, 9999)).upper()
  799. @staticmethod
  800. def trans_merchant_type(merchantType):
  801. """转换京东进件的类型"""
  802. # 个人商户
  803. if merchantType == "SUBJECT_TYPE_MICRO":
  804. return COMPANY_TYPE.NORMAL_PERSON
  805. # 企业商户
  806. return COMPANY_TYPE.ENTERPRISE
  807. @staticmethod
  808. def trans_end_time(endTime):
  809. if endTime == "forever":
  810. return u"长期"
  811. return endTime
  812. @classmethod
  813. def get_source_record(cls, owner): # type:(Optional[Agent, Dealer]) -> MerchantSourceInfo
  814. """
  815. 获取原始的申请记录
  816. """
  817. _owner = owner.merchantRegister
  818. return cls.objects.filter(ownerId=str(_owner.id), ownerRole=str(_owner.role)).first() or cls(ownerId=str(_owner.id), ownerRole=str(_owner.role))
  819. @property
  820. def owner(self):
  821. """
  822. 做一次缓存 防止频繁访问数据库
  823. """
  824. if hasattr(self, "_owner"):
  825. return self._owner
  826. owner = ROLE.from_role_id(self.ownerRole, self.ownerId)
  827. setattr(self, "_owner", owner)
  828. return owner
  829. @property
  830. def agentNo(self):
  831. """服务商 修改为 和我们系统的agent绑定"""
  832. merchantAgent = self.merchantAgent.fetch()
  833. return merchantAgent.agentNo
  834. # 照片信息类
  835. @property
  836. def blicUrla(self):
  837. """
  838. 营业执照的照片
  839. 文档规定 自然人的情况下 营业执照传递合同租凭 和对方技术人员沟通 这个地方可以就传身份证件
  840. :return:
  841. """
  842. url = self.busLicenseUrl
  843. if self.companyType == COMPANY_TYPE.NORMAL_PERSON:
  844. url = self.identifyCardAUrl
  845. return self.load_image_content(url)
  846. @property
  847. def occUrla(self):
  848. """
  849. 银行开户许可证 非必传选项 当商户类型为企业的时候必传递 沟通就传递营业执照
  850. :return:
  851. """
  852. return self.load_image_content(self.busLicenseUrl)
  853. @property
  854. def blicObaUrla(self):
  855. """
  856. 税字号图片 企业商户五类证件的时候才需要(目前应该不需要)
  857. :return:
  858. """
  859. return
  860. @property
  861. def blicTrcUrla(self):
  862. """
  863. 组织机构代码 企业商户五类证件的时候才需要(目前应该不需要)
  864. :return:
  865. """
  866. return
  867. @property
  868. def lepUrla(self):
  869. """
  870. 身份证证件的正面
  871. :return:
  872. """
  873. return self.load_image_content(self.identifyCardAUrl)
  874. @property
  875. def lepUrlb(self):
  876. """
  877. 身份证证件的反面
  878. :return:
  879. """
  880. return self.load_image_content(self.identifyCardBUrl)
  881. @property
  882. def lepUrlc(self):
  883. """
  884. 手持身份证 照片 只有当商户类型为自然人的时候需要
  885. 经过宋伟沟通 这个地方也可以传递身份证的正面信息
  886. :return:
  887. """
  888. return self.load_image_content(self.identifyCardCUrl)
  889. @property
  890. def img(self):
  891. """
  892. 经营门店的门头照片
  893. :return:
  894. """
  895. return self.load_image_content(self.storeAUrl)
  896. @property
  897. def enterimg(self):
  898. """
  899. 经营门店的入口照片
  900. :return:
  901. """
  902. return self.load_image_content(self.storeBUrl)
  903. @property
  904. def innerimg(self):
  905. """
  906. 经营门店的店内信息
  907. :return:
  908. """
  909. return self.load_image_content(self.storeCUrl)
  910. @property
  911. def cardPhoto(self):
  912. """
  913. 结算银行卡正面图片
  914. :return:
  915. """
  916. return self.load_image_content(self.bankCardUrl)
  917. @property
  918. def settleManPhotoFront(self):
  919. """
  920. 结算人身份证的正面照
  921. :return:
  922. """
  923. return self.lepUrla
  924. @property
  925. def settleManPhotoBack(self):
  926. """
  927. 结算人身份证背面照
  928. :return:
  929. """
  930. return self.lepUrlb
  931. @property
  932. def settleHoldingIDCard(self):
  933. """
  934. 结算人身份证的手持照
  935. :return:
  936. """
  937. return self.load_image_content(self.identifyCardCUrl)
  938. @property
  939. def settleHoldingBankCard(self):
  940. """
  941. 结算人手持银行卡 暂时不需要
  942. :return:
  943. """
  944. return
  945. # 报文信息(entity)
  946. @property
  947. def companyType(self):
  948. """
  949. 公司的性质 目前支持的就是企业性质或个人性质
  950. :return:
  951. """
  952. return self.merchantType
  953. @property
  954. def serialNo(self):
  955. """
  956. 订单流水号 需要注意的是 一旦商户入驻成功, 订单流水号不变 修改信息的时候 以成功入驻的流水号为准
  957. 这个地方处理的逻辑是 用户入驻成功之后 才会将流水号写入进去 否则的话就为空 就会重新生成
  958. :return:
  959. """
  960. if not self.serial_no:
  961. self.serial_no = self.generate_serial_no(self.ownerId)
  962. return self.serial_no
  963. else:
  964. return self.serial_no
  965. @serialNo.setter
  966. def serialNo(self, value):
  967. """
  968. 当设置 流水号的时候 说明商户入驻已经提交成功了 这个时候顺便将商户的状态 从init 转换为 等待中
  969. :param value:
  970. :return:
  971. """
  972. if self.status != MerchantStatus.INIT:
  973. return
  974. self.status = MerchantStatus.WAITING
  975. self.serial_no = value
  976. self.save()
  977. self.reload()
  978. @property
  979. def regPhone(self):
  980. return self.owner.username
  981. @property
  982. def blicCardType(self):
  983. """
  984. 企业包含:统一社会信用代码类-USC,普通五证类-BLI,多证合一类-OCI
  985. 自然人:身份证-ID
  986. 目前企业的简化了 只支持统一社会信用代码 即USC
  987. :return:
  988. """
  989. if self.companyType == COMPANY_TYPE.ENTERPRISE:
  990. return "USC"
  991. return "ID"
  992. @property
  993. def blicCompanyName(self):
  994. """
  995. 实体商户的名称
  996. 企业商户 的时候就传递企业商户证件照上面的名称
  997. 个人商户时填姓名+(自然人)
  998. :return:
  999. """
  1000. if self.companyType == COMPANY_TYPE.ENTERPRISE:
  1001. return self.busName
  1002. return u"商户_{}".format(self.identifyCardName)
  1003. @property
  1004. def abMerchantName(self):
  1005. """
  1006. 商户简称
  1007. :return:
  1008. """
  1009. return self.storeShotName
  1010. @property
  1011. def blicUscc(self):
  1012. """
  1013. 统一社会信用码
  1014. :return:
  1015. """
  1016. return self.busCode
  1017. @property
  1018. def blicObaCardNo(self):
  1019. """
  1020. 税务登记号 暂时不需要
  1021. :return:
  1022. """
  1023. return
  1024. @property
  1025. def blicTrcCardNo(self):
  1026. """
  1027. 组织机构代码 目前不需要
  1028. :return:
  1029. """
  1030. return
  1031. @property
  1032. def blicScope(self):
  1033. """
  1034. TODO 经营范围 企业商户需要
  1035. :return:
  1036. """
  1037. return u"自主类设备经营"
  1038. @property
  1039. def indTwoCode(self):
  1040. # 行业编号
  1041. return "033"
  1042. @property
  1043. def blicProvince(self):
  1044. """
  1045. 营业地址所在省
  1046. 对于个人用户 可以填写联系人所在的
  1047. :return:
  1048. """
  1049. if self.companyType == COMPANY_TYPE.ENTERPRISE:
  1050. return self.busProvince
  1051. return self.shopProvince
  1052. @property
  1053. def blicCity(self):
  1054. """
  1055. 营业地址所在市
  1056. 对于个人商户 可以填写联系人所在的市
  1057. :return:
  1058. """
  1059. if self.companyType == COMPANY_TYPE.ENTERPRISE:
  1060. return self.busCity
  1061. return self.shopCity
  1062. @property
  1063. def blicAddress(self):
  1064. """
  1065. 营业地址的地区
  1066. 对于个人商户而言 可以填写联系人所在的地址
  1067. :return:
  1068. """
  1069. if self.companyType == COMPANY_TYPE.ENTERPRISE:
  1070. return self.busArea + self.busAddr
  1071. return self.shopArea + self.shopAddr
  1072. @property
  1073. def blicLongTerm(self):
  1074. """
  1075. 营业执照 是否长期
  1076. :return:
  1077. """
  1078. # TODO zjl
  1079. return self.identifyCardLongTime
  1080. @property
  1081. def blicValidityStart(self):
  1082. """
  1083. 营业执照起始时间
  1084. :return:
  1085. """
  1086. return self.identifyCardStartTime
  1087. @property
  1088. def blicValidityEnd(self):
  1089. """
  1090. 营业执照结束时间
  1091. :return:
  1092. """
  1093. return self.identifyCardEndTime if not self.identifyCardLongTime else u"长期"
  1094. @property
  1095. def lepCardType(self):
  1096. """
  1097. 法人证件类型 目前固定为ID
  1098. :return:
  1099. """
  1100. return "ID"
  1101. @property
  1102. def lepName(self):
  1103. """
  1104. 法人证件姓名 就是身份证
  1105. :return:
  1106. """
  1107. return self.identifyCardName
  1108. @property
  1109. def lepCardNo(self):
  1110. """
  1111. 法人的证件号 就是身份证号
  1112. :return:
  1113. """
  1114. return self.identifyCardCode
  1115. @property
  1116. def lepLongTerm(self):
  1117. """
  1118. 法人证件是否长期
  1119. :return:
  1120. """
  1121. return self.identifyCardLongTime
  1122. @property
  1123. def lepValidityStart(self):
  1124. """
  1125. 法人证件的起始类型
  1126. :return:
  1127. """
  1128. return self.identifyCardStartTime
  1129. @property
  1130. def lepValidityEnd(self):
  1131. """
  1132. 法人证件的类型到期
  1133. :return:
  1134. """
  1135. return self.identifyCardEndTime if not self.identifyCardLongTime else u"长期"
  1136. @property
  1137. def contactName(self):
  1138. """
  1139. 联系人姓名
  1140. :return:
  1141. """
  1142. if self.contactPersonName:
  1143. return self.contactPersonName
  1144. return self.identifyCardName
  1145. @property
  1146. def contactPhone(self):
  1147. """
  1148. 联系人的电话号码
  1149. :return:
  1150. """
  1151. return self.contactPersonPhone
  1152. @property
  1153. def contactEmail(self):
  1154. """
  1155. 联系人的电子邮箱
  1156. :return:
  1157. """
  1158. return self.contactPersonEmail
  1159. @property
  1160. def contactProvince(self):
  1161. """
  1162. 联系人的省
  1163. :return:
  1164. """
  1165. return self.identifyCardProvince
  1166. @property
  1167. def contactCity(self):
  1168. """
  1169. 联系人的市
  1170. :return:
  1171. """
  1172. return self.identifyCardCity
  1173. @property
  1174. def contactAddress(self):
  1175. """
  1176. 联系人的详细地址
  1177. :return:
  1178. """
  1179. return self.identifyCardArea + self.identifyCardAddr
  1180. @property
  1181. def ifPhyStore(self):
  1182. """
  1183. 门店是否线下 固定值
  1184. :return:
  1185. """
  1186. return True
  1187. @property
  1188. def storeProvince(self):
  1189. """
  1190. 门店所在的省
  1191. :return:
  1192. """
  1193. return self.shopProvince
  1194. @property
  1195. def storeCity(self):
  1196. """
  1197. 门店所在的市
  1198. :return:
  1199. """
  1200. return self.shopCity
  1201. @property
  1202. def storeAddress(self):
  1203. """
  1204. 门店所在的地址
  1205. :return:
  1206. """
  1207. return self.shopArea + self.shopAddr
  1208. @property
  1209. def settleToCard(self):
  1210. """
  1211. 是否结算到卡 固定值
  1212. :return:
  1213. """
  1214. return "1"
  1215. @property
  1216. def priatePublic(self):
  1217. """
  1218. 结算账户的公私标志 企业用户一律是对公账户 个人账户一律是私人账户
  1219. :return:
  1220. """
  1221. if self.companyType == COMPANY_TYPE.ENTERPRISE:
  1222. return PRIATE_OR_PUBLIC.PUBLIC.value
  1223. return PRIATE_OR_PUBLIC.PRIATE.value
  1224. @property
  1225. def bankName(self):
  1226. """
  1227. 结算银行的名称
  1228. :return:
  1229. """
  1230. return self.bankCardName
  1231. @property
  1232. def subBankCode(self):
  1233. """
  1234. 结算银行的支行联行号
  1235. :return:
  1236. """
  1237. return self.bankCardSubCode
  1238. @property
  1239. def bankAccountNo(self):
  1240. """
  1241. 结算银行卡的账号
  1242. :return:
  1243. """
  1244. return self.bankCardCode
  1245. @property
  1246. def bankAccountName(self):
  1247. """
  1248. 结算的账户名称
  1249. :return:
  1250. """
  1251. if self.companyType == COMPANY_TYPE.ENTERPRISE:
  1252. return self.busName
  1253. return self.identifyCardName
  1254. @property
  1255. def settleCardPhone(self):
  1256. """
  1257. 结算银行卡绑定的手机号码
  1258. :return:
  1259. """
  1260. return self.owner.username
  1261. @property
  1262. def settlementPeriod(self):
  1263. """
  1264. 结算的周期 固定D1
  1265. :return:
  1266. """
  1267. return "D1"
  1268. @property
  1269. def directoryList(self):
  1270. """
  1271. 商户的授权目录
  1272. :return:
  1273. """
  1274. return ["{}/".format(settings.SERVER_END_BASE_URL)]
  1275. @property
  1276. def loginLink(self):
  1277. return "https://passport.jdpay.com/login/index.do"
  1278. @property
  1279. def wxSource(self): # type:() -> WechatApplyMerchant
  1280. """
  1281. """
  1282. if not getattr(self, "_wxSource", None):
  1283. setattr(self, "_wxSource", self.wxApplier.fetch() if self.wxApplier else WechatApplyMerchant())
  1284. return getattr(self, "_wxSource")
  1285. @property
  1286. def merchantStatus(self):
  1287. """
  1288. 商户的申请状态 做兼容使用
  1289. """
  1290. if self.status in [
  1291. MerchantStatus.INIT, MerchantStatus.WAITING, MerchantStatus.FAIL, MerchantStatus.SUCCESS,
  1292. MerchantStatus.AUTH_WAITING, MerchantStatus.AUTH_SUCCESS
  1293. ]:
  1294. return int(self.status)
  1295. # 微信等待审核的状态 当客户是实名等待确认的时候 每次都去拉取同步一次 保证信息的真实准确
  1296. elif self.status in [int(MerchantStatus.AUTH_APPLY_SUCCESS)]:
  1297. from apps.web.merchant.utils import is_wechat_authorized, is_alipay_authorized
  1298. if is_wechat_authorized(self) and is_alipay_authorized(self):
  1299. self.to_wx_success()
  1300. return int(MerchantStatus.AUTH_SUCCESS)
  1301. else:
  1302. return int(self.status)
  1303. def get_help_message(self):
  1304. """
  1305. 显示当前步骤的帮助信息
  1306. """
  1307. if self.status == MerchantStatus.INIT:
  1308. return u"您尚未提交商户资料,请及时提交商户资料,避免影响您后续收款"
  1309. if self.status == MerchantStatus.WAITING:
  1310. return u"您已提交资料,请耐心等待商户审核通过"
  1311. if self.status == MerchantStatus.FAIL:
  1312. return u"商户申请失败,失败原因为 <{}>".format(self.errorDescription)
  1313. if self.status == MerchantStatus.CONFIRM:
  1314. return u"您的商户申请已经通过,正准备提交微信完成商户实名"
  1315. if self.status == MerchantStatus.AUTH_WAITING:
  1316. return u"您的资料资料已提交到微信平台,正在进行商户实名申请中,请耐心等待实名申请通过"
  1317. if self.status == MerchantStatus.AUTH_APPLY_SUCCESS:
  1318. return u"您的实名申请已经通过审核,请点击下方按钮前往确认实名意愿"
  1319. if self.status == MerchantStatus.AUTH_SUCCESS:
  1320. return u"你的商户已经完成开通,请点击下方按钮完成收款方式切换"
  1321. return u"商户开通完成"
  1322. def get_merchant_info(self): # type:() -> dict
  1323. """
  1324. 获取商户的基本信息
  1325. """
  1326. data = {
  1327. # 商户类型
  1328. "merchantType": self.wxSource.subjectInfo.mainType,
  1329. # 商户号
  1330. "merchantNo": self.merchantNo,
  1331. # 商户的状态
  1332. "status": self.merchantStatus,
  1333. # 提交资料的时间
  1334. "created": self.dateTimeAdded,
  1335. # 联系人
  1336. "contactName": self.contactName,
  1337. # 联系电话
  1338. "contactPhone": self.contactPhone,
  1339. # 登录账号:
  1340. "regEmail": self.regEmail,
  1341. # 数据的更新时间
  1342. "updated": self.dateTimeUpdated
  1343. }
  1344. return data
  1345. def get_help_info(self):
  1346. """
  1347. 获取帮助信息
  1348. """
  1349. return {
  1350. # 帮助按钮的链接
  1351. "helpHtml": "http://mp.weixin.qq.com/s?__biz=MzU2NDQ1MTM2NQ==&mid=2247483688&idx=1&sn=d4f935020d8051d7af1236019a76eae3&chksm=fc4b8062cb3c0974b47b75036012e01a28ba88172f91f3f63abbb23d177a25526671ae1d77e1&scene=18#wechat_redirect",
  1352. # 帮助的文字 或提示信息
  1353. "helpMessage": self.get_help_message()
  1354. }
  1355. def get_legal_info(self):
  1356. """
  1357. 获取法人的信息
  1358. """
  1359. return {
  1360. "urlA": self.wxSource.legalInfo.lepCardUrlA,
  1361. "urlB": self.wxSource.legalInfo.lepCardUrlB,
  1362. "name": self.wxSource.legalInfo.lepName,
  1363. "cardNo": self.wxSource.legalInfo.lepCardNo,
  1364. "startTime": self.wxSource.legalInfo.lepCardStart,
  1365. "endTime": self.wxSource.legalInfo.lepCardEnd,
  1366. "province": {
  1367. "code": self.wxSource.legalInfo.lepProvinceCode,
  1368. "name": self.wxSource.legalInfo.lepProvince
  1369. },
  1370. "city": {
  1371. "code": self.wxSource.legalInfo.lepCityCode,
  1372. "name": self.wxSource.legalInfo.lepCity
  1373. },
  1374. "area": {
  1375. "code": self.wxSource.legalInfo.lepAreaCode,
  1376. "name": self.wxSource.legalInfo.lepArea
  1377. },
  1378. "addr": self.wxSource.legalInfo.lepAddr
  1379. }
  1380. def get_contact_info(self):
  1381. """
  1382. 获取联系人的信息
  1383. """
  1384. # 只有自然人
  1385. if self.merchantType == COMPANY_TYPE.NORMAL_PERSON:
  1386. return None
  1387. return {
  1388. "urlA": self.wxSource.contactInfo.contactCardUrlA,
  1389. "urlB": self.wxSource.contactInfo.contactCardUrlB,
  1390. "name": self.wxSource.contactInfo.contactName,
  1391. "cardNo": self.wxSource.contactInfo.contactCardNo,
  1392. "startTime": self.wxSource.contactInfo.contactCardStart,
  1393. "endTime": self.wxSource.contactInfo.contactCardEnd,
  1394. "province": {
  1395. "code": self.wxSource.contactInfo.contactProvinceCode,
  1396. "name": self.wxSource.contactInfo.contactProvince
  1397. },
  1398. "city": {
  1399. "code": self.wxSource.contactInfo.contactCityCode,
  1400. "name": self.wxSource.contactInfo.contactCity
  1401. },
  1402. "area": {
  1403. "code": self.wxSource.contactInfo.contactAreaCode,
  1404. "name": self.wxSource.contactInfo.contactArea
  1405. },
  1406. "addr": self.wxSource.contactInfo.contactAddr
  1407. }
  1408. def get_licence_info(self):
  1409. """
  1410. 获取营业执照的信息
  1411. """
  1412. # 只有自然人
  1413. if self.merchantType == COMPANY_TYPE.NORMAL_PERSON:
  1414. return None
  1415. if self.wxSource.subjectInfo.businessLicenceInfo:
  1416. return {
  1417. "businessLicenceInfo": {
  1418. "busLicenseUrl": self.wxSource.subjectInfo.businessLicenceInfo.licenceCopy,
  1419. "busCode": self.wxSource.subjectInfo.businessLicenceInfo.licenceNumber,
  1420. "busName": self.wxSource.subjectInfo.businessLicenceInfo.merchantName,
  1421. "startTime": self.wxSource.subjectInfo.businessLicenceInfo.licenceStart,
  1422. "endTime": self.wxSource.subjectInfo.businessLicenceInfo.licenceEnd,
  1423. "province": {
  1424. "code": self.busProvinceCode,
  1425. "name": self.busProvince
  1426. },
  1427. "city": {
  1428. "code": self.busCityCode,
  1429. "name": self.busCity
  1430. },
  1431. "area": {
  1432. "code": self.busAreaCode,
  1433. "name": self.busArea
  1434. },
  1435. "addr": self.busAddr
  1436. }
  1437. }
  1438. def get_certificate_info(self):
  1439. """
  1440. 获取商户提交的证件资料
  1441. """
  1442. return {
  1443. # 商户类型
  1444. "contactType": self.wxSource.contactInfo.contactType,
  1445. "businessAuthorizationLetter": self.wxSource.contactInfo.businessAuthorizationLetter,
  1446. "legalInfo": self.get_legal_info(),
  1447. "contactInfo": self.get_contact_info(),
  1448. "subjectInfo": self.get_licence_info(),
  1449. }
  1450. def save_certificate_info(self, payload):
  1451. """
  1452. 保存商户提交的证件资料
  1453. """
  1454. # 首先处理商户类型的信息
  1455. self.errorDescription = ""
  1456. self.merchantAgent = MerchantAgent.default_merchant_agent()
  1457. self.merchantType = self.trans_merchant_type(payload["merchantType"])
  1458. # 配置法人的证件照片信息
  1459. self.identifyCardAUrl = payload["legalInfo"]["urlA"]
  1460. self.identifyCardBUrl = payload["legalInfo"]["urlB"]
  1461. self.identifyCardCUrl = payload["legalInfo"]["urlA"]
  1462. # 配置法人的证件文字信息
  1463. self.identifyCardName = payload["legalInfo"]["name"]
  1464. self.identifyCardCode = payload["legalInfo"]["cardNo"]
  1465. self.identifyCardStartTime = payload["legalInfo"]["startTime"]
  1466. self.identifyCardEndTime = self.trans_end_time(payload["legalInfo"]["endTime"])
  1467. self.identifyCardLongTime = self.identifyCardEndTime == u"长期"
  1468. # 配置法人证件的地址信息
  1469. self.identifyCardProvinceCode = payload["legalInfo"]["province"]["code"]
  1470. self.identifyCardCityCode = payload["legalInfo"]["city"]["code"]
  1471. self.identifyCardAreaCode = payload["legalInfo"]["area"]["code"]
  1472. self.identifyCardProvince = payload["legalInfo"]["province"]["name"]
  1473. self.identifyCardCity = payload["legalInfo"]["city"]["name"]
  1474. self.identifyCardArea = payload["legalInfo"]["area"]["name"]
  1475. self.identifyCardAddr = payload["legalInfo"]["addr"]
  1476. # 存储商户的联系人信息 如果商户类型是个人企业 联系人即为自身
  1477. if self.merchantType == COMPANY_TYPE.NORMAL_PERSON:
  1478. self.contactPersonName = payload["legalInfo"]["name"]
  1479. else:
  1480. self.contactPersonName = payload["contactInfo"]["name"]
  1481. # 如果商户号类型为企业的商户 则需要保存商户信息
  1482. if self.merchantType != COMPANY_TYPE.NORMAL_PERSON:
  1483. self.busLicenseUrl = payload["subjectInfo"]["businessLicenceInfo"]["busLicenseUrl"]
  1484. self.busName = payload["subjectInfo"]["businessLicenceInfo"]["busName"]
  1485. self.busCode = payload["subjectInfo"]["businessLicenceInfo"]["busCode"]
  1486. self.busProvinceCode = payload["subjectInfo"]["businessLicenceInfo"]["province"]["code"]
  1487. self.busCityCode = payload["subjectInfo"]["businessLicenceInfo"]["city"]["code"]
  1488. self.busAreaCode = payload["subjectInfo"]["businessLicenceInfo"]["area"]["code"]
  1489. self.busProvince = payload["subjectInfo"]["businessLicenceInfo"]["province"]["name"]
  1490. self.busCity = payload["subjectInfo"]["businessLicenceInfo"]["city"]["name"]
  1491. self.busArea = payload["subjectInfo"]["businessLicenceInfo"]["area"]["name"]
  1492. self.busAddr = payload["subjectInfo"]["businessLicenceInfo"]["addr"]
  1493. # 保存微信申请所需的信息
  1494. self.wxSource.subjectInfo.mainType = payload["merchantType"]
  1495. self.wxSource.legalInfo.save_certificate_info(payload["legalInfo"])
  1496. self.wxSource.contactInfo.save_certificate_info(payload["contactInfo"])
  1497. # 如果是 企业商户 保存一下营业执照的信息
  1498. if self.merchantType != COMPANY_TYPE.NORMAL_PERSON:
  1499. businessLicenceInfo = payload["subjectInfo"]["businessLicenceInfo"]
  1500. businessLicenceInfo["busLegal"] = self.identifyCardName
  1501. self.wxSource.subjectInfo.save_certificate_info(businessLicenceInfo=businessLicenceInfo)
  1502. self.wxApplier = self.wxSource.save()
  1503. if self.status == int(MerchantStatus.INIT):
  1504. self.dateTimeAdded = datetime.datetime.now()
  1505. self.dateTimeUpdated = datetime.datetime.now()
  1506. return self.save()
  1507. def get_settlement_info(self):
  1508. """
  1509. 获取用户提交的结算信息资料
  1510. """
  1511. return {
  1512. "bankCardImg": self.bankCardUrl,
  1513. "bankCardCode": self.bankCardCode,
  1514. "bankName": self.bankCardName,
  1515. "bankCardSubCode": self.bankCardSubCode,
  1516. "bankCardSubName": self.bankCardSubName
  1517. }
  1518. def save_settlement_info(self, payload):
  1519. """
  1520. 保存商户的结算信息
  1521. """
  1522. # 图片的照片
  1523. self.bankCardUrl = payload["bankCardImg"]
  1524. # 银行名称
  1525. self.bankCardName = payload["bankName"]
  1526. # 银行卡号码
  1527. self.bankCardCode = payload["bankCardCode"]
  1528. # 支行联行号
  1529. self.bankCardSubCode = payload["bankCardSubCode"]
  1530. # 支行名称
  1531. self.bankCardSubName = payload["bankCardSubName"]
  1532. return self.save()
  1533. def get_business_info(self):
  1534. """
  1535. 获取用户提交的营业信息
  1536. """
  1537. return {
  1538. "storeAUrl": self.storeAUrl,
  1539. "storeBUrl": self.storeBUrl,
  1540. "storeCUrl": self.storeCUrl,
  1541. # 商户简称
  1542. "storeShotName": self.storeShotName,
  1543. # 地址
  1544. "province": {
  1545. "code": self.shopProvinceCode,
  1546. "name": self.shopProvince
  1547. },
  1548. "city": {
  1549. "code": self.shopCityCode,
  1550. "name": self.shopCity
  1551. },
  1552. "area": {
  1553. "code": self.shopAreaCode,
  1554. "name": self.shopArea
  1555. },
  1556. "addr": self.shopAddr,
  1557. "mobile": self.contactPersonPhone,
  1558. }
  1559. def save_business_info(self, payload):
  1560. """
  1561. 保存营业类的信息
  1562. """
  1563. # 商户号一旦申请了,商户简称不允许修改
  1564. self.storeShotName = payload["storeShotName"]
  1565. # 照片信息是可变的
  1566. self.storeAUrl = payload["storeAUrl"]
  1567. self.storeBUrl = payload["storeBUrl"]
  1568. self.storeCUrl = payload["storeCUrl"]
  1569. # 地址信息是可变的
  1570. self.shopProvinceCode = payload["province"]["code"]
  1571. self.shopCityCode = payload["city"]["code"]
  1572. self.shopAreaCode = payload["area"]["code"]
  1573. self.shopProvince = payload["province"]["name"]
  1574. self.shopCity = payload["city"]["name"]
  1575. self.shopArea = payload["area"]["name"]
  1576. self.shopAddr = payload["addr"]
  1577. # 个人信息小微商户的时候 需要保存
  1578. if self.merchantType == COMPANY_TYPE.NORMAL_PERSON:
  1579. self.wxSource.subjectInfo.save_certificate_info(assistProveInfo=payload)
  1580. self.wxApplier = self.wxSource.save()
  1581. return self.save()
  1582. def save_mobile_info(self, mobile):
  1583. """
  1584. 保存手机号信息 商户号一旦确认 手机号不允许修改
  1585. """
  1586. if not self.merchantNo:
  1587. self.contactPersonPhone = mobile
  1588. self.contactPersonEmail = self.regEmail = "{}@163.com".format(self.contactPersonPhone)
  1589. self.wxSource.contactInfo.save_mobile_info(mobile)
  1590. self.wxApplier = self.wxSource.save()
  1591. return self.save()
  1592. return self
  1593. def support_modify(self):
  1594. """
  1595. 只有初始化以及审核失败的时候 才允许填写、修改资料
  1596. """
  1597. return self.status in [int(MerchantStatus.FAIL), int(MerchantStatus.INIT)]
  1598. def support_enter(self):
  1599. """
  1600. 是否支持进件 只有状态为1的时候 才会触发进件
  1601. """
  1602. return self.status in [int(MerchantStatus.WAITING)]
  1603. def support_query_audit(self):
  1604. return self.status in [int(MerchantStatus.WAITING)]
  1605. def support_jdaggre(self):
  1606. """
  1607. 京东app已经可以使用 等待微信实名认证
  1608. """
  1609. return self.status in [int(MerchantStatus.CONFIRM)]
  1610. def support_wechat_audit(self):
  1611. """
  1612. 查询微信的 申请状态
  1613. """
  1614. return self.status in [int(MerchantStatus.AUTH_WAITING)]
  1615. @property
  1616. def is_wechat_submit(self):
  1617. return self.wxSource.applymentId
  1618. @property
  1619. def is_ali_submit(self):
  1620. """
  1621. 阿里的 暂时都视为已经提交
  1622. """
  1623. return True
  1624. def to_waiting(self, **kwargs):
  1625. """
  1626. 切换到入驻申请状态
  1627. """
  1628. assert self.status in [MerchantStatus.INIT, MerchantStatus.FAIL]
  1629. self.status = int(MerchantStatus.WAITING)
  1630. self.dateTimeUpdated = datetime.datetime.now()
  1631. self.save()
  1632. MerchantLog.submit(str(self.id))
  1633. merchant_user_submit.send(sender=self.__class__, merchantId=str(self.id))
  1634. def to_confirm(self, **kwargs):
  1635. """
  1636. 商户此时已经完成开通 准备各项准备工作
  1637. 录入秘钥
  1638. 录入APP
  1639. 录入子商户编号等
  1640. """
  1641. assert self.status == MerchantStatus.WAITING
  1642. desKey, mdKey = kwargs["desKey"], kwargs["mdKey"]
  1643. if not all([desKey, mdKey]):
  1644. return
  1645. self.status = int(MerchantStatus.CONFIRM)
  1646. self.desKey, self.mdKey = desKey, mdKey
  1647. self.dateTimeUpdated = datetime.datetime.now()
  1648. self.save()
  1649. # 代理商、经销商预处理
  1650. self.owner.confirm_merchant(self)
  1651. # 记录一次操作日志
  1652. MerchantLog.add_app(str(self.id))
  1653. # 发送信号 触发下一轮的行动
  1654. merchant_jd_access.send(sender=self.__class__, merchantId=str(self.id))
  1655. def to_wx_waiting(self, **kwargs):
  1656. """
  1657. 状态不再发生变化
  1658. """
  1659. assert self.status == int(MerchantStatus.CONFIRM)
  1660. self.wxSource.to_wechat_submit(kwargs["applymentId"])
  1661. self.dateTimeUpdated = datetime.datetime.now()
  1662. self.save()
  1663. # 记录一次操作日志
  1664. MerchantLog.submit_wechat(str(self.id), description=kwargs["applymentId"])
  1665. def to_ali_waiting(self, **kwargs):
  1666. assert self.status == int(MerchantStatus.CONFIRM)
  1667. self.wxSource.to_ali_submit(kwargs["applymentId"])
  1668. self.dateTimeUpdated = datetime.datetime.now()
  1669. self.status = int(MerchantStatus.AUTH_WAITING)
  1670. self.save()
  1671. # 记录一次操作日志
  1672. MerchantLog.submit_ali(str(self.id), description=kwargs["applymentId"])
  1673. def to_auth_wait(self):
  1674. """
  1675. 实名信息提交完毕
  1676. """
  1677. assert self.status == int(MerchantStatus.CONFIRM)
  1678. self.status = int(MerchantStatus.AUTH_WAITING)
  1679. self.dateTimeUpdated = datetime.datetime.now()
  1680. self.save()
  1681. def to_auth_apply_success(self, **kwargs):
  1682. """
  1683. 全部实名已经通过 内部状态 做强制商户时候使用
  1684. """
  1685. assert self.status == int(MerchantStatus.AUTH_WAITING)
  1686. self.status = int(MerchantStatus.AUTH_APPLY_SUCCESS)
  1687. self.dateTimeUpdated = datetime.datetime.now()
  1688. self.save()
  1689. MerchantLog.auth_apply_success(str(self.id))
  1690. def to_wx_success(self, **kwargs):
  1691. """
  1692. 微信审核通过 防止有些人通过扫描二维码小程序自行提交资料申请 状态放的宽泛一点点
  1693. """
  1694. self.status = int(MerchantStatus.AUTH_SUCCESS)
  1695. self.dateTimeUpdated = datetime.datetime.now()
  1696. self.save()
  1697. def to_success(self, **kwargs):
  1698. """
  1699. 经销商的商户确认开通 需要切换经销商的支付方式 而代理商的仅仅改变状态就可以了
  1700. """
  1701. assert self.status == MerchantStatus.AUTH_SUCCESS
  1702. # 更改商户的状态
  1703. self.status = int(MerchantStatus.SUCCESS)
  1704. self.dateTimeUpdated = datetime.datetime.now()
  1705. self.save()
  1706. # 然后是角色各自处理
  1707. self.owner.success_merchant()
  1708. # 记录一次操作日志
  1709. MerchantLog.change_pay_type(str(self.id))
  1710. def to_fail(self, errorMsg):
  1711. """
  1712. 切换为失败的状态 只有开通产品的时候会调用这个接口 如果入驻的时候失败 直接切换成为初始状态就好
  1713. """
  1714. self.status = int(MerchantStatus.FAIL)
  1715. self.dateTimeUpdated = datetime.datetime.now()
  1716. self.wxApplier = self.wxSource.to_cancel()
  1717. self.errorDescription = errorMsg
  1718. self.save()
  1719. self.reload()
  1720. # 记录一次日志操作
  1721. MerchantLog.fail(str(self.id), description=errorMsg)
  1722. def create_app(self):
  1723. return JDAggrePayApp.get_or_create_by_merchant(self)
  1724. class Area(EmbeddedDocument):
  1725. code = StringField(verbose_name="地区编码")
  1726. name = StringField(verbose_name=u"地区名称")
  1727. def __str__(self):
  1728. return self.name
  1729. def to_dict(self):
  1730. return {
  1731. "name": self.name,
  1732. "code": self.code
  1733. }
  1734. class Attach(EmbeddedDocument):
  1735. url = StringField(verbose_name=u"源")
  1736. attachNum = StringField(verbose_name=u"编号")
  1737. @property
  1738. def content(self):
  1739. res = requests.get(url=self.url, timeout=3)
  1740. return res.content
  1741. def upload_success(self, attachNum):
  1742. self.attachNum = attachNum
  1743. return self.save()
  1744. def update_url(self, url, save=False):
  1745. self.url = url
  1746. return self if not save else self.save()
  1747. class PayBank(EmbeddedDocument):
  1748. num = StringField(verbose_name="产品编号")
  1749. rate = StringField(verbose_name=u"费率", default="0.6")
  1750. @classmethod
  1751. def default_pay_type(cls):
  1752. return [
  1753. # 京东
  1754. cls(num="10031414639876930831001", rate="0.60"),
  1755. cls(num="10031414639876930831004", rate="0.60"),
  1756. cls(num="10031414639876930831005", rate="0.60"),
  1757. cls(num="10031414639876930831013", rate="0.60")
  1758. ]
  1759. def to_dict(self):
  1760. return {
  1761. "num": self.num,
  1762. "rate": self.rate
  1763. }
  1764. class JDOpenApplyInfo(Searchable):
  1765. """
  1766. 京东openAPI 的用户先写的原始资料
  1767. """
  1768. dateTimeAdded = DateTimeField(verbose_name=u"录入信息的时间", default=datetime.datetime.now)
  1769. dateTimeUpdated = DateTimeField(verbose_name=u"记录更新的时间", default=datetime.datetime.now)
  1770. status = IntField(verbose_name=u"商户状态", default=JdOpenMerchantStatus.INIT)
  1771. isDelete = BooleanField(verbose_name=u"是否已经删除", default=False)
  1772. ownerId = StringField(verbose_name=u"商户申请人ID")
  1773. ownerRole = StringField(verbose_name=u"商户申请人角色")
  1774. errorDesc = StringField(verbose_name=u"错误描述")
  1775. # 通过接口返回的参数
  1776. agentNum = StringField(verbose_name=u"服务商编号", default="10001016435484143212321")
  1777. customerNum = StringField(verbose_name=u"商户编号")
  1778. settleNum = StringField(verbose_name=u"结算账户编号")
  1779. shopNum = StringField(verbose_name="商店编号")
  1780. # 商户基础参数 目前行业类型不对外开放
  1781. customerType = StringField(verbose_name=u"商户类型")
  1782. fullName = StringField(verbose_name=u"商户全称")
  1783. shortName = StringField(verbose_name=u"商户简称")
  1784. industry = StringField(verbose_name=u"一级行业", default=u"生活服务") # 统一属于 生活服务 中的 自助服务
  1785. subIndustry = StringField(verbose_name=u"二级行业", default=u"自助") # 统一属于 生活服务 中的 自助服务
  1786. province = EmbeddedDocumentField(verbose_name=u"商户省", document_type=Area)
  1787. city = EmbeddedDocumentField(verbose_name=u"商户市", document_type=Area)
  1788. district = EmbeddedDocumentField(verbose_name=u"商户区", document_type=Area)
  1789. address = StringField(verbose_name=u"商户详细地址")
  1790. mapLng = StringField(verbose_name=u"商户经度")
  1791. mapLat = StringField(verbose_name=u"商户维度")
  1792. # 法人信息参数 目前证件类型不对外开放
  1793. certificateType = StringField(verbose_name=u"证件类型", default="IDENTIFICATION")
  1794. legalImgFront = EmbeddedDocumentField(verbose_name=u"法人身份证正面", document_type=Attach)
  1795. legalImgBack = EmbeddedDocumentField(verbose_name=u"法人身份证背面", document_type=Attach)
  1796. legalName = StringField(verbose_name=u"法人姓名")
  1797. legalCardNo = StringField(verbose_name=u"证件号码")
  1798. legalStart = StringField(verbose_name=u"法人的证件起始")
  1799. legalEnd = StringField(verbose_name=u"法人的证件结束")
  1800. legalProvince = EmbeddedDocumentField(verbose_name=u"法人省", document_type=Area)
  1801. legalCity = EmbeddedDocumentField(verbose_name=u"法人市", document_type=Area)
  1802. legalDistrict = EmbeddedDocumentField(verbose_name=u"法人区", document_type=Area)
  1803. legalAddress = StringField(verbose_name=u"法人详细地址")
  1804. # 联系人信息参数
  1805. contactImgFront = EmbeddedDocumentField(verbose_name=u"联系人身份证正面", document_type=Attach)
  1806. contactImgBack = EmbeddedDocumentField(verbose_name=u"联系人身份证背面", document_type=Attach)
  1807. contactName = StringField(verbose_name=u"联系人姓名")
  1808. contactCardNo = StringField(verbose_name=u"联系人卡号")
  1809. contactStart = StringField(verbose_name=u"联系人证件开始")
  1810. contactEnd = StringField(verbose_name=u"联系人证件结束")
  1811. phoneNumber = StringField(verbose_name=u"登录账号、手机号码")
  1812. # 收款账号相应参数
  1813. accountType = StringField(verbose_name=u"账户类型")
  1814. bankImg = EmbeddedDocumentField(verbose_name=u"银行卡", document_type=Attach)
  1815. bankCardNo = StringField(verbose_name=u"银行卡号")
  1816. bankName = StringField(verbose_name=u"银行名称")
  1817. bankBranchName = StringField(verbose_name=u"支行名称")
  1818. bankProvince = EmbeddedDocumentField(verbose_name=u"银行省", document_type=Area)
  1819. bankCity = EmbeddedDocumentField(verbose_name=u"银行市", document_type=Area)
  1820. settleAmount = StringField(verbose_name=u"起结算金额", default="1")
  1821. payBankList = EmbeddedDocumentListField(verbose_name=u"支付方式", document_type=PayBank)
  1822. bankPhone = StringField(verbose_name=u"银行预留手机号")
  1823. # 营业执照相应参数
  1824. organizationImg = EmbeddedDocumentField(verbose_name=u"营业执照", document_type=Attach)
  1825. organizationName = StringField(verbose_name=u"企业名称")
  1826. organizationNo = StringField(verbose_name=u"统一组织机构代码")
  1827. organizationStart = StringField(verbose_name=u"营业执照的起始")
  1828. organizationEnd = StringField(verbose_name=u"营业执照的结束")
  1829. organizationProvince = EmbeddedDocumentField(verbose_name=u"营业执照省", document_type=Area)
  1830. organizationCity = EmbeddedDocumentField(verbose_name=u"营业执照市", document_type=Area)
  1831. organizationDistrict = EmbeddedDocumentField(verbose_name=u"营业执照区", document_type=Area)
  1832. organizationAddress = StringField(verbose_name=u"营业执照详细地址")
  1833. # 事业单位证书相关参数
  1834. certType = StringField(verbose_name=u"证书类型")
  1835. certImg = EmbeddedDocumentField(verbose_name=u"证书", document_type=Attach)
  1836. certName = StringField(verbose_name=u"组织机构名称")
  1837. certNo = StringField(verbose_name=u"证书编号")
  1838. certStart = StringField(verbose_name=u"营业执照起始")
  1839. certEnd = StringField(verbose_name=u"营业执照结束")
  1840. certProvince = EmbeddedDocumentField(verbose_name=u"证书省", document_type=Area)
  1841. certCity = EmbeddedDocumentField(verbose_name=u"证书市", document_type=Area)
  1842. certDistrict = EmbeddedDocumentField(verbose_name=u"证书区", document_type=Area)
  1843. certAddress = StringField(verbose_name=u"证书详细地址")
  1844. # 门店照相应参数
  1845. shopImgA = EmbeddedDocumentField(verbose_name=u"店铺照", document_type=Attach)
  1846. shopImgB = EmbeddedDocumentField(verbose_name=u"门头照", document_type=Attach)
  1847. shopImgC = EmbeddedDocumentField(verbose_name=u"店内照", document_type=Attach)
  1848. # 个人需要
  1849. identifyhandhold = EmbeddedDocumentField(verbose_name=u"个人手持身份照", document_type=Attach)
  1850. # 企业&个体工商户 需要
  1851. organizationcode = EmbeddedDocumentField(verbose_name=u"税务登记证", document_type=Attach)
  1852. taxregistration = EmbeddedDocumentField(verbose_name=u"税务登记证", document_type=Attach)
  1853. unifiedsocialcreditcode = EmbeddedDocumentField(verbose_name=u"税务登记证", document_type=Attach)
  1854. # 事业单位独有参数
  1855. certificateFile = EmbeddedDocumentField(verbose_name=u"事业单位证明函", document_type=Attach)
  1856. specialQualification = EmbeddedDocumentField(verbose_name=u"特殊资质证书", document_type=Attach)
  1857. # 经办人信息
  1858. businessAuthorizationLetter = EmbeddedDocumentField(verbose_name=u"业务办理授权函", document_type=Attach)
  1859. # 微信申请的消息
  1860. subMerchantId = StringField(verbose_name=u"微信子商编")
  1861. businessCode = StringField(verbose_name=u"微信业务申请单编号")
  1862. applymentId = StringField(verbose_name=u"微信申请编号")
  1863. # 支付宝申请的信息
  1864. subAliMerchantId = StringField(verbose_name=u"支付宝子商编")
  1865. aliApplymentId = StringField(verbose_name=u"支付宝申请编号")
  1866. aliBusinessCode = StringField(verbose_name=u"支付宝实名申请单编号")
  1867. meta = {
  1868. 'collection': 'JDOpenApplyInfo',
  1869. # TODO 需要切换数据库
  1870. # "db_alias": "logdata"
  1871. }
  1872. def __str__(self):
  1873. return "{}_{}".format(self.__class__.__name__, self.id)
  1874. @classmethod
  1875. def create_personal(cls, owner, **kwargs):
  1876. """
  1877. 新建个人商户的信息
  1878. """
  1879. mer = cls.get_merchant_by_owner(owner) #
  1880. if mer and str(mer.id) != kwargs["id"]:
  1881. raise ValueError(u"非所属经销商ID")
  1882. else:
  1883. # 新创建或者是修改
  1884. mer = mer or cls(ownerId=str(owner.id), ownerRole=owner.role)
  1885. mer.customerType = kwargs["customerType"]
  1886. mer.fullName = kwargs["fullName"]
  1887. mer.shortName = kwargs["shortName"]
  1888. mer.province = Area(**kwargs["province"])
  1889. mer.city = Area(**kwargs["city"])
  1890. mer.district = Area(**kwargs["district"])
  1891. mer.address = kwargs["address"]
  1892. mer.mapLng = kwargs["mapLng"]
  1893. mer.mapLat = kwargs["mapLat"]
  1894. mer.legalImgFront = (mer.legalImgFront or Attach()).update_url(kwargs["legalImgFront"])
  1895. mer.legalImgBack = (mer.legalImgBack or Attach()).update_url(kwargs["legalImgBack"])
  1896. mer.legalName = kwargs["legalName"]
  1897. mer.legalCardNo = kwargs["legalCardNo"]
  1898. mer.legalStart = kwargs["legalStart"]
  1899. mer.legalEnd = kwargs["legalEnd"]
  1900. mer.phoneNumber = kwargs["phoneNumber"]
  1901. mer.accountType = kwargs["accountType"]
  1902. mer.bankImg = (mer.bankImg or Attach()).update_url(kwargs["bankImg"])
  1903. mer.bankCardNo = kwargs["bankCardNo"]
  1904. mer.bankName = kwargs["bankName"]
  1905. mer.bankBranchName = kwargs["bankBranchName"]
  1906. mer.bankProvince = Area(**kwargs["bankProvince"])
  1907. mer.bankCity = Area(**kwargs["bankCity"])
  1908. mer.payBankList = PayBank.default_pay_type()
  1909. mer.bankPhone = kwargs["bankPhone"]
  1910. mer.shopImgA = (mer.shopImgA or Attach()).update_url(kwargs["shopImgA"])
  1911. mer.shopImgB = (mer.shopImgB or Attach()).update_url(kwargs["shopImgB"])
  1912. mer.shopImgC = (mer.shopImgC or Attach()).update_url(kwargs["shopImgC"])
  1913. mer.identifyhandhold = (mer.identifyhandhold or Attach()).update_url(kwargs["legalImgHold"])
  1914. mer = mer.save()
  1915. return mer
  1916. @classmethod
  1917. def create_company(cls, owner, **kwargs):
  1918. mer = cls.get_merchant_by_owner(owner) #
  1919. if mer and str(mer.id) != kwargs["id"]:
  1920. raise ValueError(u"非所属经销商ID")
  1921. else:
  1922. # 新创建或者是修改
  1923. mer = mer or cls(ownerId=str(owner.id), ownerRole=owner.role)
  1924. mer.customerType = kwargs["customerType"]
  1925. mer.fullName = kwargs["fullName"]
  1926. mer.shortName = kwargs["shortName"]
  1927. mer.province = Area(**kwargs["province"])
  1928. mer.city = Area(**kwargs["city"])
  1929. mer.district = Area(**kwargs["district"])
  1930. mer.address = kwargs["address"]
  1931. mer.mapLng = kwargs["mapLng"]
  1932. mer.mapLat = kwargs["mapLat"]
  1933. # 企业上户需要加上法人证件的地址 便于微信的实名
  1934. mer.legalImgFront = (mer.legalImgFront or Attach()).update_url(kwargs["legalImgFront"])
  1935. mer.legalImgBack = (mer.legalImgBack or Attach()).update_url(kwargs["legalImgBack"])
  1936. mer.legalName = kwargs["legalName"]
  1937. mer.legalCardNo = kwargs["legalCardNo"]
  1938. mer.legalStart = kwargs["legalStart"]
  1939. mer.legalEnd = kwargs["legalEnd"]
  1940. mer.legalProvince = Area(**kwargs["legalProvince"])
  1941. mer.legalCity = Area(**kwargs["legalCity"])
  1942. mer.legalDistrict = Area(**kwargs["legalDistrict"])
  1943. mer.legalAddress = kwargs["legalAddress"]
  1944. mer.contactImgFront = (mer.contactImgFront or Attach()).update_url(kwargs["contactImgFront"])
  1945. mer.contactImgBack = (mer.contactImgBack or Attach()).update_url(kwargs["contactImgBack"])
  1946. mer.contactName = kwargs["contactName"]
  1947. mer.contactCardNo = kwargs["contactCardNo"]
  1948. mer.contactStart = kwargs["contactStart"]
  1949. mer.contactEnd = kwargs["contactEnd"]
  1950. mer.phoneNumber = kwargs["phoneNumber"]
  1951. mer.accountType = kwargs["accountType"]
  1952. mer.bankImg = (mer.bankImg or Attach()).update_url(kwargs["bankImg"])
  1953. mer.bankCardNo = kwargs["bankCardNo"]
  1954. mer.bankName = kwargs["bankName"]
  1955. mer.bankBranchName = kwargs["bankBranchName"]
  1956. mer.bankProvince = Area(**kwargs["bankProvince"])
  1957. mer.bankCity = Area(**kwargs["bankCity"])
  1958. mer.payBankList = PayBank.default_pay_type()
  1959. mer.bankPhone = kwargs["bankPhone"]
  1960. mer.organizationImg = (mer.organizationImg or Attach()).update_url(kwargs["organizationImg"])
  1961. mer.organizationName = kwargs["organizationName"]
  1962. mer.organizationNo = kwargs["organizationNo"]
  1963. mer.organizationStart = kwargs["organizationStart"]
  1964. mer.organizationEnd = kwargs["organizationEnd"]
  1965. mer.organizationProvince = Area(**kwargs["organizationProvince"])
  1966. mer.organizationCity = Area(**kwargs["organizationCity"])
  1967. mer.organizationDistrict = Area(**kwargs["organizationDistrict"])
  1968. mer.organizationAddress = kwargs["organizationAddress"]
  1969. mer.shopImgA = (mer.shopImgA or Attach()).update_url(kwargs["shopImgA"])
  1970. mer.shopImgB = (mer.shopImgB or Attach()).update_url(kwargs["shopImgB"])
  1971. mer.shopImgC = (mer.shopImgC or Attach()).update_url(kwargs["shopImgC"])
  1972. mer.organizationcode = (mer.organizationcode or Attach()).update_url(kwargs["organizationcode"])
  1973. mer.taxregistration = (mer.taxregistration or Attach()).update_url(kwargs["taxregistration"])
  1974. mer.unifiedsocialcreditcode = (mer.unifiedsocialcreditcode or Attach()).update_url(kwargs["unifiedsocialcreditcode"])
  1975. # 经办人的信息
  1976. mer.businessAuthorizationLetter = (mer.taxregistration or Attach()).update_url(kwargs["businessAuthorizationLetter"])
  1977. mer = mer.save()
  1978. return mer
  1979. @classmethod
  1980. def create_individualbiss(cls, owner, **kwargs):
  1981. """
  1982. 创建个体工商户
  1983. """
  1984. mer = cls.get_merchant_by_owner(owner) #
  1985. if mer and str(mer.id) != kwargs["id"]:
  1986. raise ValueError(u"非所属经销商ID")
  1987. else:
  1988. # 新创建或者是修改
  1989. mer = mer or cls(ownerId=str(owner.id), ownerRole=owner.role)
  1990. mer.customerType = kwargs["customerType"]
  1991. mer.fullName = kwargs["fullName"]
  1992. mer.shortName = kwargs["shortName"]
  1993. mer.province = Area(**kwargs["province"])
  1994. mer.city = Area(**kwargs["city"])
  1995. mer.district = Area(**kwargs["district"])
  1996. mer.address = kwargs["address"]
  1997. mer.mapLng = kwargs["mapLng"]
  1998. mer.mapLat = kwargs["mapLat"]
  1999. mer.legalImgFront = (mer.legalImgFront or Attach()).update_url(kwargs["legalImgFront"])
  2000. mer.legalImgBack = (mer.legalImgBack or Attach()).update_url(kwargs["legalImgBack"])
  2001. mer.legalName = kwargs["legalName"]
  2002. mer.legalCardNo = kwargs["legalCardNo"]
  2003. mer.legalStart = kwargs["legalStart"]
  2004. mer.legalEnd = kwargs["legalEnd"]
  2005. mer.contactImgFront = (mer.contactImgFront or Attach()).update_url(kwargs["contactImgFront"])
  2006. mer.contactImgBack = (mer.contactImgBack or Attach()).update_url(kwargs["contactImgBack"])
  2007. mer.contactName = kwargs["contactName"]
  2008. mer.contactCardNo = kwargs["contactCardNo"]
  2009. mer.contactStart = kwargs["contactStart"]
  2010. mer.contactEnd = kwargs["contactEnd"]
  2011. mer.phoneNumber = kwargs["phoneNumber"]
  2012. mer.accountType = kwargs["accountType"]
  2013. mer.bankImg = (mer.bankImg or Attach()).update_url(kwargs["bankImg"])
  2014. mer.bankCardNo = kwargs["bankCardNo"]
  2015. mer.bankName = kwargs["bankName"]
  2016. mer.bankBranchName = kwargs["bankBranchName"]
  2017. mer.bankProvince = Area(**kwargs["bankProvince"])
  2018. mer.bankCity = Area(**kwargs["bankCity"])
  2019. mer.payBankList = PayBank.default_pay_type()
  2020. mer.bankPhone = kwargs["bankPhone"]
  2021. mer.organizationImg = (mer.organizationImg or Attach()).update_url(kwargs["organizationImg"])
  2022. mer.organizationName = kwargs["organizationName"]
  2023. mer.organizationNo = kwargs["organizationNo"]
  2024. mer.organizationStart = kwargs["organizationStart"]
  2025. mer.organizationEnd = kwargs["organizationEnd"]
  2026. mer.organizationProvince = Area(**kwargs["organizationProvince"])
  2027. mer.organizationCity = Area(**kwargs["organizationCity"])
  2028. mer.organizationDistrict = Area(**kwargs["organizationDistrict"])
  2029. mer.organizationAddress = kwargs["organizationAddress"]
  2030. mer.shopImgA = (mer.shopImgA or Attach()).update_url(kwargs["shopImgA"])
  2031. mer.shopImgB = (mer.shopImgB or Attach()).update_url(kwargs["shopImgB"])
  2032. mer.shopImgC = (mer.shopImgC or Attach()).update_url(kwargs["shopImgC"])
  2033. mer.organizationcode = (mer.organizationcode or Attach()).update_url(kwargs["organizationcode"])
  2034. mer.taxregistration = (mer.taxregistration or Attach()).update_url(kwargs["taxregistration"])
  2035. # 经办人的信息
  2036. mer.businessAuthorizationLetter = (mer.taxregistration or Attach()).update_url(kwargs["businessAuthorizationLetter"])
  2037. mer = mer.save()
  2038. return mer
  2039. @classmethod
  2040. def create_institution(cls, owner, **kwargs):
  2041. """
  2042. 创建事业单位
  2043. """
  2044. mer = cls.get_merchant_by_owner(owner) #
  2045. if mer and str(mer.id) != kwargs["id"]:
  2046. raise ValueError(u"非所属经销商ID")
  2047. else:
  2048. # 新创建或者是修改
  2049. mer = mer or cls(ownerId=str(owner.id), ownerRole=owner.role)
  2050. mer.customerType = kwargs["customerType"]
  2051. mer.fullName = kwargs["fullName"]
  2052. mer.shortName = kwargs["shortName"]
  2053. mer.province = Area(**kwargs["province"])
  2054. mer.city = Area(**kwargs["city"])
  2055. mer.district = Area(**kwargs["district"])
  2056. mer.address = kwargs["address"]
  2057. mer.mapLng = kwargs["mapLng"]
  2058. mer.mapLat = kwargs["mapLat"]
  2059. mer.legalImgFront = (mer.legalImgFront or Attach()).update_url(kwargs["legalImgFront"])
  2060. mer.legalImgBack = (mer.legalImgBack or Attach()).update_url(kwargs["legalImgBack"])
  2061. mer.legalName = kwargs["legalName"]
  2062. mer.legalCardNo = kwargs["legalCardNo"]
  2063. mer.legalStart = kwargs["legalStart"]
  2064. mer.legalEnd = kwargs["legalEnd"]
  2065. mer.contactImgFront = (mer.contactImgFront or Attach()).update_url(kwargs["contactImgFront"])
  2066. mer.contactImgBack = (mer.contactImgBack or Attach()).update_url(kwargs["contactImgBack"])
  2067. mer.contactName = kwargs["contactName"]
  2068. mer.contactCardNo = kwargs["contactCardNo"]
  2069. mer.contactStart = kwargs["contactStart"]
  2070. mer.contactEnd = kwargs["contactEnd"]
  2071. mer.phoneNumber = kwargs["phoneNumber"]
  2072. mer.accountType = kwargs["accountType"]
  2073. mer.bankImg = (mer.bankImg or Attach()).update_url(kwargs["bankImg"])
  2074. mer.bankCardNo = kwargs["bankCardNo"]
  2075. mer.bankName = kwargs["bankName"]
  2076. mer.bankBranchName = kwargs["bankBranchName"]
  2077. mer.bankProvince = Area(**kwargs["bankProvince"])
  2078. mer.bankCity = Area(**kwargs["bankCity"])
  2079. mer.payBankList = PayBank.default_pay_type()
  2080. mer.bankPhone = kwargs["bankPhone"]
  2081. mer.certType = kwargs["certType"]
  2082. mer.certImg = (mer.certImg or Attach()).update_url(kwargs["certImg"])
  2083. mer.certName = kwargs["certName"]
  2084. mer.certNo = kwargs["certNo"]
  2085. mer.certStart = kwargs["certStart"]
  2086. mer.certEnd = kwargs["certEnd"]
  2087. mer.certProvince = Area(**kwargs["certProvince"])
  2088. mer.certCity = Area(**kwargs["certCity"])
  2089. mer.certDistrict = Area(**kwargs["certDistrict"])
  2090. mer.certAddress = kwargs["certAddress"]
  2091. mer.shopImgA = (mer.shopImgA or Attach()).update_url(kwargs["shopImgA"])
  2092. mer.shopImgB = (mer.shopImgB or Attach()).update_url(kwargs["shopImgB"])
  2093. mer.shopImgC = (mer.shopImgC or Attach()).update_url(kwargs["shopImgC"])
  2094. mer.certificateFile = (mer.certificateFile or Attach()).update_url(kwargs["certificateFile"])
  2095. mer.specialQualification = (mer.specialQualification or Attach()).update_url(kwargs["specialQualification"])
  2096. mer.organizationcode = (mer.organizationcode or Attach()).update_url(kwargs["organizationcode"])
  2097. mer.taxregistration = (mer.taxregistration or Attach()).update_url(kwargs["taxregistration"])
  2098. mer.unifiedsocialcreditcode = (mer.unifiedsocialcreditcode or Attach()).update_url(kwargs["unifiedsocialcreditcode"])
  2099. # 经办人的信息
  2100. mer.businessAuthorizationLetter = (mer.taxregistration or Attach()).update_url(kwargs["businessAuthorizationLetter"])
  2101. mer = mer.save()
  2102. return mer
  2103. @classmethod
  2104. def get_merchant_by_status(cls, status):
  2105. return cls.objects.filter(status=status, isDelete=False)
  2106. @classmethod
  2107. def get_merchant_by_owner(cls, owner):
  2108. return cls.objects.filter(ownerId=str(owner.id), ownerRole=str(owner.role), isDelete=False).first()
  2109. @classmethod
  2110. def get_merchant_by_id(cls, _id): # type:(str) -> JDOpenApplyInfo
  2111. return cls.objects.filter(id=_id, isDelete=False).first()
  2112. @property
  2113. def is_personal(self):
  2114. """
  2115. 个人类型商户
  2116. """
  2117. return self.customerType == JdOpenMerchantType.PERSON
  2118. @property
  2119. def is_company(self):
  2120. """
  2121. 企业类型商户
  2122. """
  2123. return self.customerType == JdOpenMerchantType.COMPANY
  2124. @property
  2125. def is_individualbiss(self):
  2126. """
  2127. 个体工商户
  2128. """
  2129. return self.customerType == JdOpenMerchantType.INDIVIDUALBISS
  2130. @property
  2131. def is_institution(self):
  2132. """
  2133. 事业单位
  2134. """
  2135. return self.customerType == JdOpenMerchantType.INSTITUTION
  2136. @property
  2137. def merchantAddr(self):
  2138. return u"{}{}{}{}".format(self.province, self.city, self.district, self.address)
  2139. @property
  2140. def organizationAddr(self):
  2141. return u"{}{}{}{}".format(self.organizationProvince, self.organizationCity, self.organizationDistrict, self.organizationAddress)
  2142. @property
  2143. def certAddr(self):
  2144. return u"{}{}{}{}".format(self.certProvince, self.certCity, self.certDistrict, self.certAddress)
  2145. @property
  2146. def legalAddr(self):
  2147. return u"{}{}{}{}".format(self.legalProvince, self.legalCity, self.legalDistrict, self.legalAddress)
  2148. @property
  2149. def owner(self):
  2150. if hasattr(self, "_owner"):
  2151. return self._owner
  2152. owner = ROLE.from_role_id(self.ownerRole, self.ownerId)
  2153. setattr(self, "_owner", owner)
  2154. return owner
  2155. @property
  2156. def wxSource(self):
  2157. return self
  2158. def get_access_and_secret(self):
  2159. logger.info("[get_access_and_secret] get merchant id = {}".format(self.id))
  2160. return OPEN_ACCESS_KEY, OPEN_SECRET_KEY
  2161. def get_info(self):
  2162. return {
  2163. "id": str(self.id),
  2164. "status": int(self.status),
  2165. "agentNum": str(self.agentNum),
  2166. "customerNum": str(self.customerNum),
  2167. "settleNum": str(self.settleNum),
  2168. "shopNum": str(self.shopNum),
  2169. "customerType": self.customerType,
  2170. "shortName": self.shortName,
  2171. "province": self.province.to_dict() if self.province else {},
  2172. "city": self.city.to_dict() if self.city else {},
  2173. "district": self.district.to_dict() if self.district else {},
  2174. "address": self.address,
  2175. "mapLng": self.mapLng,
  2176. "mapLat": self.mapLat,
  2177. "certificateType": self.certificateType,
  2178. "legalImgFront": self.legalImgFront.url if self.legalImgFront else "",
  2179. "legalImgBack": self.legalImgBack.url if self.legalImgBack else "",
  2180. "legalName": self.legalName,
  2181. "legalCardNo": self.legalCardNo,
  2182. "legalStart": self.legalStart,
  2183. "legalEnd": self.legalEnd,
  2184. "legalForever": True if self.legalEnd == "forever" else False,
  2185. "contactImgFront": self.contactImgFront.url if self.contactImgFront else "",
  2186. "contactImgBack": self.contactImgBack.url if self.contactImgBack else "",
  2187. "contactName": self.contactName,
  2188. "contactCardNo": self.contactCardNo,
  2189. "contactStart": self.contactStart,
  2190. "contactEnd": self.contactEnd,
  2191. "contactForever": True if self.contactEnd == "forever" else False,
  2192. "phoneNumber": self.phoneNumber,
  2193. "accountType": self.accountType,
  2194. "bankImg": self.bankImg.url if self.bankImg else "",
  2195. "bankCardNo": self.bankCardNo,
  2196. "bankName": self.bankName,
  2197. "bankBranchName": self.bankBranchName,
  2198. "bankProvince": self.bankProvince.to_dict() if self.bankProvince else {},
  2199. "bankCity": self.bankCity.to_dict() if self.bankCity else {},
  2200. "bankPhone": self.bankPhone,
  2201. "organizationImg": self.organizationImg.url if self.organizationImg else "",
  2202. "organizationName": self.organizationName,
  2203. "organizationNo": self.organizationNo,
  2204. "organizationStart": self.organizationStart,
  2205. "organizationEnd": self.organizationEnd,
  2206. "organizationForever": True if self.organizationEnd == "forever" else False,
  2207. "organizationProvince": self.organizationProvince.to_dict() if self.organizationProvince else {},
  2208. "organizationCity": self.organizationCity.to_dict() if self.organizationCity else {},
  2209. "organizationDistrict": self.organizationDistrict.to_dict() if self.organizationDistrict else {},
  2210. "organizationAddress": self.organizationAddress,
  2211. "certType": self.certType,
  2212. "certImg": self.certImg.url if self.certImg else "",
  2213. "certNo": self.certNo,
  2214. "certStart": self.certStart,
  2215. "certEnd": self.certEnd,
  2216. "certForever": True if self.certEnd == "forever" else False,
  2217. "certProvince": self.certProvince.to_dict() if self.certProvince else {},
  2218. "certCity": self.certCity.to_dict() if self.certCity else {},
  2219. "certDistrict": self.certDistrict.to_dict() if self.certDistrict else {},
  2220. "certAddress": self.certAddress,
  2221. "shopImgA": self.shopImgA.url if self.shopImgA else "",
  2222. "shopImgB": self.shopImgB.url if self.shopImgB else "",
  2223. "shopImgC": self.shopImgC.url if self.shopImgC else "",
  2224. "legalImgHold": self.identifyhandhold.url if self.identifyhandhold else "",
  2225. "organizationcode": self.organizationcode.url if self.organizationcode else "",
  2226. "taxregistration": self.taxregistration.url if self.taxregistration else "",
  2227. "unifiedsocialcreditcode": self.unifiedsocialcreditcode.url if self.unifiedsocialcreditcode else "",
  2228. "certificateFile": self.certificateFile.url if self.certificateFile else "",
  2229. "specialQualification": self.specialQualification.url if self.specialQualification else "",
  2230. }
  2231. def to_submit(self):
  2232. self.status = JdOpenMerchantStatus.SUBMIT
  2233. self.dateTimeUpdated = datetime.datetime.now()
  2234. MerchantLog.submit(str(self.id))
  2235. self.save()
  2236. merchant_user_submit.send(sender=self.__class__, merchantId=str(self.id))
  2237. return self
  2238. def to_fail(self, message):
  2239. self.status = JdOpenMerchantStatus.FAIL
  2240. self.errorDesc = message
  2241. self.dateTimeUpdated = datetime.datetime.now()
  2242. MerchantLog.fail(str(self.id))
  2243. return self.save()
  2244. def to_customer(self, customerNum):
  2245. self.status = JdOpenMerchantStatus.CUSTOMER
  2246. self.customerNum = customerNum
  2247. self.dateTimeUpdated = datetime.datetime.now()
  2248. self.save()
  2249. create_customer_success.send(sender=self.__class__, merchantId=str(self.id))
  2250. return self
  2251. def to_settle(self, settleNum):
  2252. self.status = JdOpenMerchantStatus.SETTLE
  2253. self.settleNum = settleNum
  2254. self.dateTimeUpdated = datetime.datetime.now()
  2255. self.save()
  2256. create_settle_success.send(sender=self.__class__, merchantId=str(self.id))
  2257. return self
  2258. def to_shop(self, shopNum):
  2259. self.status = JdOpenMerchantStatus.SHOP
  2260. self.shopNum = shopNum
  2261. self.dateTimeUpdated = datetime.datetime.now()
  2262. self.save()
  2263. create_shop_success.send(sender=self.__class__, merchantId=str(self.id))
  2264. return self
  2265. def to_attach(self):
  2266. self.status = JdOpenMerchantStatus.ATTACH
  2267. self.dateTimeUpdated = datetime.datetime.now()
  2268. self.save()
  2269. upload_attach_success.send(sender=self.__class__, merchantId=str(self.id))
  2270. return self
  2271. def to_complete(self):
  2272. self.status = JdOpenMerchantStatus.COMPLETE
  2273. self.dateTimeUpdated = datetime.datetime.now()
  2274. self.save()
  2275. complete_success.send(sender=self.__class__, merchantId=str(self.id))
  2276. return self
  2277. def to_confirm(self):
  2278. self.status = JdOpenMerchantStatus.CONFIRM
  2279. self.dateTimeUpdated = datetime.datetime.now()
  2280. self.save()
  2281. merchant_jd_access.send(sender=self.__class__, merchantId=str(self.id))
  2282. return self
  2283. def to_success(self):
  2284. """
  2285. 京东的商户审核完成 审核完成的时候 创建app
  2286. """
  2287. self.owner.confirm_merchant(self)
  2288. self.status = JdOpenMerchantStatus.SUCCESS
  2289. self.dateTimeUpdated = datetime.datetime.now()
  2290. MerchantLog.add_app(str(self.id))
  2291. return self.save()
  2292. def to_wx_waiting(self, **kwargs):
  2293. self.applymentId = str(kwargs["applymentId"])
  2294. self.dateTimeUpdated = datetime.datetime.now()
  2295. MerchantLog.submit_wechat(str(self.id))
  2296. return self.save()
  2297. def to_wx_audit(self):
  2298. self.status = JdOpenMerchantStatus.AUTH_APPLY_SUCCESS
  2299. self.dateTimeUpdated = datetime.datetime.now()
  2300. return self.save()
  2301. def to_apply(self, server): # type:(WechatApiProxy) -> dict
  2302. """
  2303. 生成微信所需要的信息
  2304. """
  2305. businessCode = "{}{}".format(datetime.datetime.now().strftime("%Y%m%d%H%M%S"), random.randint(1000, 9999)),
  2306. self.businessCode = businessCode
  2307. self.save()
  2308. data = {
  2309. "business_code": businessCode,
  2310. "addition_info": {"confirm_mchid_list": [self.subMerchantId]}
  2311. }
  2312. if self.is_personal:
  2313. contact_info = {
  2314. "contact_type": ContactType.LEGAL.code,
  2315. "name": server.rsa_encrypt(self.legalName),
  2316. "id_card_number": server.rsa_encrypt(self.legalCardNo),
  2317. "mobile": server.rsa_encrypt(self.phoneNumber),
  2318. }
  2319. subject_info = {
  2320. "subject_type": "SUBJECT_TYPE_MICRO",
  2321. "assist_prove_info": {
  2322. "micro_biz_type": "MICRO_TYPE_STORE",
  2323. "store_name": self.shortName,
  2324. "store_address_code": WxMerchantAddress.get_code(u"{}省{}市{}".format(
  2325. self.province.name, self.city.name, self.district.name
  2326. )),
  2327. "store_address": self.merchantAddr,
  2328. "store_header_copy": server.upload_image_from_oss(self.shopImgA.url).get("media_id", ""),
  2329. "store_indoor_copy": server.upload_image_from_oss(self.shopImgB.url).get("media_id", ""),
  2330. }
  2331. }
  2332. identification_info = {
  2333. "identification_type": "IDENTIFICATION_TYPE_IDCARD",
  2334. "identification_name": server.rsa_encrypt(self.legalName),
  2335. "identification_number": server.rsa_encrypt(self.legalCardNo),
  2336. "identification_valid_date": '["{}","{}"]'.format(self.legalStart, self.legalEnd),
  2337. "identification_front_copy": server.upload_image_from_oss(self.legalImgFront.url).get("media_id", ""),
  2338. "identification_back_copy": server.upload_image_from_oss(self.legalImgBack.url).get("media_id", ""),
  2339. }
  2340. elif self.is_company:
  2341. isLegal = self.legalCardNo == self.contactCardNo and self.legalName == self.contactName
  2342. contact_info = {
  2343. "contact_type": ContactType.LEGAL.code if isLegal else ContactType.SUPER.code,
  2344. "name": server.rsa_encrypt(self.contactName),
  2345. "id_card_number": server.rsa_encrypt(self.contactCardNo),
  2346. "mobile": server.rsa_encrypt(self.phoneNumber),
  2347. }
  2348. if not isLegal:
  2349. contact_info.update({
  2350. "contact_id_doc_type": "IDENTIFICATION_TYPE_IDCARD",
  2351. "contact_id_doc_copy": server.upload_image_from_oss(self.contactImgFront.url).get("media_id", ""),
  2352. "contact_id_doc_copy_back": server.upload_image_from_oss(self.contactImgBack.url).get("media_id", ""),
  2353. "contact_period_begin": self.contactStart,
  2354. "contact_period_end": u"长期" if self.contactEnd == "forever" else self.contactEnd,
  2355. "business_authorization_letter": server.upload_image_from_oss(self.businessAuthorizationLetter.url).get("media_id", "")
  2356. })
  2357. subject_info = {
  2358. "subject_type": "SUBJECT_TYPE_ENTERPRISE",
  2359. "business_licence_info": {
  2360. "licence_number": self.organizationcode,
  2361. "licence_copy": server.upload_image_from_oss(self.organizationImg.url).get("media_id", ""),
  2362. "merchant_name": self.organizationName,
  2363. "legal_person": self.legalName,
  2364. "company_address": self.organizationAddr,
  2365. "licence_valid_date": '["{}","{}"]'.format(self.organizationStart, self.organizationEnd),
  2366. },
  2367. }
  2368. identification_info = {
  2369. "identification_type": "IDENTIFICATION_TYPE_IDCARD",
  2370. "identification_name": server.rsa_encrypt(self.legalName),
  2371. "identification_number": server.rsa_encrypt(self.legalCardNo),
  2372. "identification_valid_date": '["{}","{}"]'.format(self.legalStart, self.legalEnd),
  2373. "identification_address": self.legalAddr,
  2374. "identification_front_copy": server.upload_image_from_oss(self.legalImgFront.url).get("media_id", ""),
  2375. "identification_back_copy": server.upload_image_from_oss(self.legalImgBack.url).get("media_id", ""),
  2376. "owner": True
  2377. }
  2378. elif self.is_individualbiss:
  2379. isLegal = self.legalCardNo == self.contactCardNo and self.legalName == self.contactName
  2380. contact_info = {
  2381. "contact_type": ContactType.LEGAL.code if isLegal else ContactType.SUPER.code,
  2382. "name": server.rsa_encrypt(self.contactName),
  2383. "id_card_number": server.rsa_encrypt(self.contactCardNo),
  2384. "mobile": server.rsa_encrypt(self.phoneNumber),
  2385. }
  2386. if not isLegal:
  2387. contact_info.update({
  2388. "contact_id_doc_type": "IDENTIFICATION_TYPE_IDCARD",
  2389. "contact_id_doc_copy": server.upload_image_from_oss(self.contactImgFront.url).get("media_id", ""),
  2390. "contact_id_doc_copy_back": server.upload_image_from_oss(self.contactImgBack.url).get("media_id", ""),
  2391. "contact_period_begin": self.contactStart,
  2392. "contact_period_end": u"长期" if self.contactEnd == "forever" else self.contactEnd,
  2393. "business_authorization_letter": server.upload_image_from_oss(self.businessAuthorizationLetter.url).get("media_id", "")
  2394. })
  2395. subject_info = {
  2396. "subject_type": "SUBJECT_TYPE_INDIVIDUAL",
  2397. "business_licence_info": {
  2398. "licence_number": self.organizationcode,
  2399. "licence_copy": server.upload_image_from_oss(self.organizationImg.url).get("media_id", ""),
  2400. "merchant_name": self.organizationName,
  2401. "legal_person": self.legalName,
  2402. "company_address": self.organizationAddr,
  2403. "licence_valid_date": '["{}","{}"]'.format(self.organizationStart, self.organizationEnd),
  2404. }
  2405. }
  2406. identification_info = {
  2407. "identification_type": "IDENTIFICATION_TYPE_IDCARD",
  2408. "identification_name": server.rsa_encrypt(self.legalName),
  2409. "identification_number": server.rsa_encrypt(self.legalCardNo),
  2410. "identification_valid_date": '["{}","{}"]'.format(self.legalStart, self.legalEnd),
  2411. "identification_address": self.legalAddr,
  2412. "identification_front_copy": server.upload_image_from_oss(self.legalImgFront.url).get("media_id", ""),
  2413. "identification_back_copy": server.upload_image_from_oss(self.legalImgBack.url).get("media_id", ""),
  2414. }
  2415. else:
  2416. isLegal = self.legalCardNo == self.contactCardNo and self.legalName == self.contactName
  2417. contact_info = {
  2418. "contact_type": ContactType.LEGAL.code if isLegal else ContactType.SUPER.code,
  2419. "name": server.rsa_encrypt(self.contactName),
  2420. "id_card_number": server.rsa_encrypt(self.contactCardNo),
  2421. "mobile": server.rsa_encrypt(self.phoneNumber),
  2422. }
  2423. if not isLegal:
  2424. contact_info.update({
  2425. "contact_id_doc_type": "IDENTIFICATION_TYPE_IDCARD",
  2426. "contact_id_doc_copy": server.upload_image_from_oss(self.contactImgFront.url).get("media_id", ""),
  2427. "contact_id_doc_copy_back": server.upload_image_from_oss(self.contactImgBack.url).get("media_id", ""),
  2428. "contact_period_begin": self.contactStart,
  2429. "contact_period_end": u"长期" if self.contactEnd == "forever" else self.contactEnd,
  2430. "business_authorization_letter": server.upload_image_from_oss(self.businessAuthorizationLetter.url).get("media_id", "")
  2431. })
  2432. subject_info = {
  2433. "subject_type": "SUBJECT_TYPE_INSTITUTIONS_CLONED",
  2434. "certificate_info": {
  2435. "cert_type": self.certType,
  2436. "cert_number": self.certNo,
  2437. "cert_copy": server.upload_image_from_oss(self.certImg.url).get("media_id", ""),
  2438. "merchant_name": self.certName,
  2439. "legal_person": self.legalName,
  2440. "company_address": self.certAddr,
  2441. "cert_valid_date": '["{}","{}"]'.format(self.certStart, self.certEnd),
  2442. }
  2443. }
  2444. company_prove_copy = server.upload_image_from_oss(self.certificateFile.url).get("media_id", "")
  2445. # TODO 特殊行业资质许可证填充
  2446. special_operation_list = {
  2447. "category_id": 1,
  2448. "operation_copy_list": server.upload_image_from_oss(self.specialQualification.url).get("media_id", "")
  2449. }
  2450. identification_info = {
  2451. "identification_type": "IDENTIFICATION_TYPE_IDCARD",
  2452. "identification_name": server.rsa_encrypt(self.legalName),
  2453. "identification_number": server.rsa_encrypt(self.legalCardNo),
  2454. "identification_valid_date": '["{}","{}"]'.format(self.legalStart, self.legalEnd),
  2455. "identification_address": self.legalAddr,
  2456. "identification_front_copy": server.upload_image_from_oss(self.legalImgFront.url).get("media_id", ""),
  2457. "identification_back_copy": server.upload_image_from_oss(self.legalImgBack.url).get("media_id", ""),
  2458. }
  2459. data["company_prove_copy"] = company_prove_copy
  2460. data["special_operation_list"] = special_operation_list
  2461. data["contact_info"] = contact_info
  2462. data["subject_info"] = subject_info
  2463. data["identification_info"] = identification_info
  2464. return data
  2465. def to_ali_auth(self, server):
  2466. """
  2467. 转换阿里所需要的实名信息
  2468. """
  2469. businessCode = "{}{}".format(datetime.datetime.now().strftime("%Y%m%d%H%M%S"), random.randint(1000, 9999)),
  2470. self.aliBusinessCode = businessCode
  2471. self.save()
  2472. data = {
  2473. "out_biz_no": businessCode,
  2474. "extra_credentials": {"smid_list": [self.subAliMerchantId]}
  2475. }
  2476. if self.is_personal:
  2477. contact_person_info = {
  2478. "contact_name": self.legalName,
  2479. "contact_phone_no": self.phoneNumber,
  2480. "contact_card_no": self.legalCardNo
  2481. }
  2482. auth_identity_info = {
  2483. "identity_type": "MSE",
  2484. "support_credentials": {
  2485. "merchant_type": "STORE",
  2486. "store_name": self.shortName,
  2487. "province_code": "",
  2488. "province": self.province.name,
  2489. "city_code": "",
  2490. "city": self.city.name,
  2491. "district_code": "",
  2492. "district": self.district.name,
  2493. "store_address": self.address,
  2494. "store_door_img": server.upload_image_from_oss(self.shopImgA.url).get("media_id", ""),
  2495. "store_inner_img": server.upload_image_from_oss(self.shopImgB.url).get("media_id", ""),
  2496. }
  2497. }
  2498. legal_person_info = {
  2499. "card_type": "RESIDENT",
  2500. "person_name": self.legalName,
  2501. "card_no": self.legalCardNo,
  2502. "effect_time": self.legalStart,
  2503. "expire_time": self.legalEnd,
  2504. "card_front_img": server.upload_image_from_oss(self.legalImgFront.url).get("media_id", ""),
  2505. "card_back_img": server.upload_image_from_oss(self.legalImgBack.url).get("media_id", "")
  2506. }
  2507. elif self.is_company:
  2508. contact_person_info = {
  2509. "contact_name": self.contactName,
  2510. "contact_phone_no": self.phoneNumber,
  2511. "contact_card_no": self.contactCardNo
  2512. }
  2513. auth_identity_info = {
  2514. "identity_type": "ENTERPRISE",
  2515. "certificate_type": "BUSINESS_CERT",
  2516. "certificate_info": {
  2517. "cert_no": self.organizationcode,
  2518. "cert_image": server.upload_image_from_oss(self.organizationImg.url).get("media_id", ""),
  2519. "merchant_name": self.organizationName,
  2520. "legal_person_name": self.legalName,
  2521. "register_address": self.organizationAddr,
  2522. "effect_time": self.organizationStart,
  2523. "expire_time": self.organizationEnd
  2524. }
  2525. }
  2526. legal_person_info = {
  2527. "card_type": "RESIDENT",
  2528. "person_name": self.legalName,
  2529. "card_no": self.legalCardNo,
  2530. "effect_time": self.legalStart,
  2531. "expire_time": self.legalEnd,
  2532. "card_front_img": server.upload_image_from_oss(self.legalImgFront.url).get("media_id", ""),
  2533. "card_back_img": server.upload_image_from_oss(self.legalImgBack.url).get("media_id", "")
  2534. }
  2535. elif self.is_individualbiss:
  2536. contact_person_info = {
  2537. "contact_name": self.contactName,
  2538. "contact_phone_no": self.phoneNumber,
  2539. "contact_card_no": self.contactCardNo
  2540. }
  2541. auth_identity_info = {
  2542. "identity_type": "IND_BIZ",
  2543. "certificate_type": "BUSINESS_CERT",
  2544. "certificate_info": {
  2545. "cert_no": self.organizationcode,
  2546. "cert_image": server.upload_image_from_oss(self.organizationImg.url).get("media_id", ""),
  2547. "merchant_name": self.organizationName,
  2548. "legal_person_name": self.legalName,
  2549. "register_address": self.organizationAddr,
  2550. "effect_time": self.organizationStart,
  2551. "expire_time": self.organizationEnd
  2552. }
  2553. }
  2554. legal_person_info = {
  2555. "card_type": "RESIDENT",
  2556. "person_name": self.legalName,
  2557. "card_no": self.legalCardNo,
  2558. "effect_time": self.legalStart,
  2559. "expire_time": self.legalEnd,
  2560. "card_front_img": server.upload_image_from_oss(self.legalImgFront.url).get("media_id", ""),
  2561. "card_back_img": server.upload_image_from_oss(self.legalImgBack.url).get("media_id", "")
  2562. }
  2563. else:
  2564. contact_person_info = {
  2565. "contact_name": self.contactName,
  2566. "contact_phone_no": self.phoneNumber,
  2567. "contact_card_no": self.contactCardNo
  2568. }
  2569. auth_identity_info = {
  2570. "identity_type": "IND_BIZ",
  2571. "certificate_type": "REGISTER_CERT",
  2572. "certificate_info": {
  2573. "cert_type": self.certType,
  2574. "cert_no": self.certNo,
  2575. "cert_image": server.upload_image_from_oss(self.certImg.url).get("media_id", ""),
  2576. "merchant_name": self.certName,
  2577. "legal_person_name": self.legalName,
  2578. "register_address": self.certAddr,
  2579. "effect_time": self.certStart,
  2580. "expire_time": self.certEnd
  2581. }
  2582. }
  2583. legal_person_info = {
  2584. "card_type": "RESIDENT",
  2585. "person_name": self.legalName,
  2586. "card_no": self.legalCardNo,
  2587. "effect_time": self.legalStart,
  2588. "expire_time": self.legalEnd,
  2589. "card_front_img": server.upload_image_from_oss(self.legalImgFront.url).get("media_id", ""),
  2590. "card_back_img": server.upload_image_from_oss(self.legalImgBack.url).get("media_id", "")
  2591. }
  2592. employer_letter_img = server.upload_image_from_oss(self.certificateFile.url).get("media_id", "")
  2593. data["employer_letter_img"] = employer_letter_img
  2594. data["contact_person_info"] = contact_person_info
  2595. data["auth_identity_info"] = auth_identity_info
  2596. data["legal_person_info"] = legal_person_info
  2597. return data
  2598. def update_sub_merchant(self, **kwargs):
  2599. self.subAliMerchantId = kwargs["subAliMerchantId"]
  2600. self.subMerchantId = kwargs["subMerchantId"]
  2601. return self.save()
  2602. def get_help_info(self):
  2603. return {
  2604. # 帮助按钮的链接
  2605. "helpHtml": "http://mp.weixin.qq.com/s?__biz=MzU2NDQ1MTM2NQ==&mid=2247483688&idx=1&sn=d4f935020d8051d7af1236019a76eae3&chksm=fc4b8062cb3c0974b47b75036012e01a28ba88172f91f3f63abbb23d177a25526671ae1d77e1&scene=18#wechat_redirect",
  2606. # 帮助的文字 或提示信息
  2607. "helpMessage": self.get_help_message()
  2608. }
  2609. def get_help_message(self):
  2610. return u"您的实名申请已经通过审核,请点击下方按钮前往确认实名意愿"
  2611. def get_merchant_info(self):
  2612. """
  2613. 获取商户的信息
  2614. """
  2615. data = {
  2616. # 商户号
  2617. "merchantNo": self.customerNum,
  2618. # 商户的状态
  2619. "status": self.status,
  2620. # 提交资料的时间
  2621. "created": self.dateTimeAdded,
  2622. # 联系人
  2623. "contactName": self.contactName,
  2624. # 联系电话
  2625. "contactPhone": self.phoneNumber,
  2626. # 登录账号:
  2627. "regEmail": self.phoneNumber,
  2628. # 数据的更新时间
  2629. "updated": self.dateTimeUpdated
  2630. }
  2631. return data
  2632. @property
  2633. def is_wechat_submit(self):
  2634. return self.wxSource.applymentId
  2635. @property
  2636. def is_ali_submit(self):
  2637. """
  2638. 阿里的 暂时都视为已经提交
  2639. """
  2640. return True
  2641. def create_app(self):
  2642. return JDOpenPayApp.get_or_create_by_merchant(self)