views.py 241 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408
  1. # -*- coding: utf-8 -*-
  2. # !/usr/bin/env python
  3. """
  4. web.user.views
  5. ~~~~~~~~~
  6. 关于扫码终端用户的一切视图
  7. """
  8. import base64
  9. import datetime
  10. import logging
  11. import random
  12. import re
  13. import time
  14. import uuid
  15. from copy import deepcopy
  16. from math import radians, fabs, cos, asin, sqrt, sin, isnan
  17. import simplejson as json
  18. from bson.objectid import ObjectId
  19. from django.conf import settings
  20. from mongoengine.errors import DoesNotExist
  21. from mongoengine.queryset.visitor import Q
  22. from typing import TYPE_CHECKING, cast, Optional, Union, Tuple, Dict
  23. from voluptuous.error import MultipleInvalid
  24. from apilib.monetary import VirtualCoin, RMB
  25. from apilib.utils_datetime import to_datetime, timestamp_to_dt
  26. from apilib.utils_json import JsonResponse
  27. from apilib.utils_string import cn
  28. #: ad
  29. from apilib.utils_sys import memcache_lock
  30. from apilib.utils_url import add_query, before_frag_add_query
  31. from apps import serviceCache
  32. from apps.common.utils import coordinateHandler
  33. from apps.web.ad.models import AdRecord, DevRegToAli
  34. from apps.web.agent.models import Agent, MoniApp
  35. from apps.web.common.proxy import ClientRechargeModelProxy, ClientConsumeModelProxy
  36. from apps.web.common.transaction.pay import OrderCacheMgr, PayManager
  37. from apps.web.common.transaction.refund import RefundManager
  38. from apps.web.common.utils import UserConsumeFilter
  39. from apps.web.common.validation import check_phone_number, check_entity_name
  40. from apps.web.constant import Const, GPS_TYPE, START_DEVICE_STATUS, ErrorCode, RECHARGE_CARD_TYPE, APP_TYPE, \
  41. AppPlatformType, DeviceOnlineStatus, support_policy_weifule, \
  42. support_policy_device, RechargeRecordVia
  43. from apps.web.core import PayAppType, ROLE
  44. from apps.web.core.auth.ali import AlipayAuthBridge
  45. from apps.web.core.auth.wechat import WechatAuthBridge
  46. from apps.web.core.bridge.wechat import WechatClientProxy
  47. from apps.web.core.exceptions import ServiceException, InvalidParameter, InvalidFileSize, \
  48. InvalidFileName, InterceptException
  49. from apps.web.core.file import AliOssFileUploader
  50. from apps.web.core.helpers import ActionDeviceBuilder
  51. from apps.web.core.messages.sms import userMobileVerifySMSProvider
  52. from apps.web.core.models import WechatPayApp, BoundOpenInfo, WechatAuthApp
  53. from apps.web.core.sysparas import SysParas
  54. from apps.web.core.utils import DefaultJsonErrorResponse
  55. from apps.web.core.utils import JsonErrorResponse, JsonOkResponse
  56. from apps.web.dealer.models import Dealer, OnSale, OnSaleRecord, VirtualCard, Complaint, \
  57. DealerMessage
  58. from apps.web.device.define import DeviceChannelType
  59. from apps.web.device.models import Device, Group, FeedBack, Comment, Cell, DeviceType, SwapGroup
  60. from apps.web.device.models import DeviceDict
  61. from apps.web.device.models import GroupDict
  62. from apps.web.device.utils import device_control_cache_key
  63. from apps.web.exceptions import UserServerException
  64. from apps.web.helpers import get_ali_auth_bridge, get_wx_config, get_wechat_auth_bridge, \
  65. get_user_manager_agent, get_app, start_device_lock_key
  66. from apps.web.management.models import Manager
  67. from apps.web.services.bluetooth.service import ActionBtDeviceBuilder
  68. #: user
  69. from apps.web.south_intf.yuchuanApi import YuChuanApi
  70. from apps.web.user import UserAuthState, MoniUserAuthState
  71. from apps.web.user.auth import response_with_login
  72. from apps.web.user.conf import USER_AUTH_REDIRECT_URL, PAY_NOTIFY_URL
  73. from apps.web.user.models import MyUser, ConsumeRecord, RechargeRecord, ServiceProgress, Card, CardRechargeRecord, \
  74. CardConsumeRecord, CardRechargeOrder, UserVirtualCard, VCardConsumeRecord, \
  75. RefundMoneyRecord, MoniUser, VirtualCardRechargeRecord, SwapCardRecord, MonthlyPackage, \
  76. EndUserLocation, Redpack, MyUserDetail
  77. from apps.web.user.transaction import post_pay
  78. from apps.web.user.transaction_deprecated import refund_post_pay
  79. from apps.web.user.utils import (
  80. get_homepage_response, auth_wechat_pay_app,
  81. auth_wechat_manager_app, login_required,
  82. user_last_time_use_ended_cache, parse_auth_payload, batteryInfo,
  83. is_need_renew, check_user_tel, check_black_user, PayParam, BUILDER_MAP, RedpackBuilder)
  84. from apps.web.user.utils2 import get_user_not_complete_order
  85. from apps.web.user.validation import feedbackSchema
  86. from apps.web.utils import (
  87. detect_alipay_client, detect_wechat_client, permission_required, error_tolerate, ErrorResponseRedirect,
  88. NotSupportedPlatformResponseRedirect, get_start_key_status, set_start_key_status,
  89. NetDeviceResponseRedirect, AdAccessResponseRedirect, ExternalResponseRedirect,
  90. FrontEndResponseRedirect, concat_server_end_url, concat_user_cardTicketList_entry_url,
  91. record_operation_behavior, get_client_ip, WechatAuthDummyRedirect, trace_call, concat_user_recharge_url)
  92. from apps.web.wrapper import request_limit_by_user
  93. from library.alipay.exceptions import AliException
  94. from library.wechatbase.exceptions import WechatOAuthDummyException
  95. from taskmanager.mediator import task_caller
  96. if TYPE_CHECKING:
  97. from django.core.handlers.wsgi import WSGIRequest
  98. from django.http import HttpResponse, HttpResponseRedirect
  99. from apps.web.common.proxy import QuerySetProxy
  100. from apps.web.core.db import CustomQuerySet
  101. from apps.web.core.models import PayAppBase
  102. logger = logging.getLogger(__name__)
  103. # 报错页面
  104. defaultErrorResponseRedirect = ErrorResponseRedirect(error = cn(u'系统错误,请重试'))
  105. def checkAdClick(request):
  106. # type: (WSGIRequest)->HttpResponse
  107. """
  108. :param request:
  109. :return:
  110. """
  111. adId = request.GET.get('adId', None)
  112. logger.debug('get adId success adId = %s' % adId)
  113. if not adId:
  114. return ErrorResponseRedirect(error = cn(u'无效的链接,无此广告'))
  115. return AdAccessResponseRedirect(adId = str(adId))
  116. @error_tolerate(nil = defaultErrorResponseRedirect)
  117. @login_required(error_response = ErrorResponseRedirect(error = cn(u'您未登陆,请扫码登录')))
  118. def adAccess(request):
  119. # type: (WSGIRequest)->HttpResponse
  120. """
  121. 减少cookie依赖, 参数全部通过state封装
  122. 用户领取广告效果奖励
  123. :param request:
  124. :return:
  125. """
  126. adId = request.GET.get('state', None)
  127. return ErrorResponseRedirect(error = cn(u'该广告不可用'))
  128. @trace_call(logger = logger)
  129. @error_tolerate(nil = defaultErrorResponseRedirect)
  130. def userLogin(request):
  131. # type: (WSGIRequest)->HttpResponse
  132. """
  133. 用户扫码-> 登陆渲染的首屏页面
  134. 扫码的读取分配入口,同时兼容老式设备号和新式逻辑码
  135. .. 2017/10/30 加入对支付宝识别的兼容。
  136. :param request:
  137. :return:
  138. """
  139. def by_agent(request, agentId, href):
  140. # type: (WSGIRequest, str, str)->(basestring, str)
  141. return UserAuthState.by_agent(agentId=agentId, href=href, productAgentId=agentId)
  142. def by_dev(request, devNo, logicalCode, port=None):
  143. # type: (WSGIRequest, str, str, str)->(basestring, str)
  144. logger.debug('user login. device = (logicalCode=%s), port = %s' % (logicalCode, port))
  145. if (logicalCode is not None) and (devNo is None):
  146. logicalCode = logicalCode.strip()
  147. devNo = Device.get_devNo_by_logicalCode(logicalCode)
  148. if not devNo:
  149. raise UserServerException(u'该设备未开通网络支付,请投币或者联系客服(1002)')
  150. devNo = devNo.strip()
  151. dev = Device.get_dev(devNo) # type: Optional[DeviceDict]
  152. if dev is None:
  153. raise UserServerException(u'该设备未开通网络支付,请投币或者联系客服(1003)')
  154. if not dev.is_registered or 'groupId' not in dev or 'washConfig' not in dev:
  155. raise UserServerException(u'该设备未开通网络支付,请投币或者联系客服(1005)')
  156. if dev.is_expired:
  157. raise UserServerException(
  158. u'设备({})的物联网卡已经过期,目前离线,无法扫码支付。请您联系提醒设备运营商进行充值,以便尽快恢复使用。'.format(
  159. dev.logicalCode))
  160. if dev.is_fault:
  161. raise UserServerException(u'设备故障中,正在等师傅过来维修,您试试看其他设备吧')
  162. if dev.is_DND_now:
  163. raise UserServerException(u'设备处于禁用时段,暂不支持扫码使用')
  164. if dev.ban:
  165. raise UserServerException(u'该设备暂时不可使用,请联系经销商')
  166. if port and dev.channelType != DeviceChannelType.Channel_BT:
  167. isFree = Group.get_group(dev.groupId).get('isFree', False)
  168. if not isFree:
  169. box = ActionDeviceBuilder.create_action_device(dev)
  170. isCanAdd = dev['devType'].get('payableWhileBusy', False)
  171. canUse, desc = box.is_port_can_use(port, isCanAdd)
  172. if not canUse:
  173. raise UserServerException(desc)
  174. dealer = dev.owner # type: Dealer
  175. # 平台agent必须配置自定义公众号, 否则普通扫码用户无法获取
  176. product_agent = get_user_manager_agent(dealer)
  177. state = UserAuthState.by_dev(devNo=devNo,
  178. chargeIndex=port,
  179. agentId=str(dealer.agentId),
  180. productAgentId=str(product_agent.id))
  181. logger.debug('initial user state = {}'.format(repr(state)))
  182. return dev, product_agent, state
  183. def generate_card_recharge_href(_cardNo, _product_agent_id): # type:(str, str) -> Optional[str]
  184. _baseHref = "/user/index.html#/chargeCard?cardNo={}&cardId={}"
  185. try:
  186. card = Card.objects.get(cardNo=_cardNo, agentId=str(_product_agent_id))
  187. except DoesNotExist:
  188. logger.error('card is not exist, cardNo=%s' % _cardNo)
  189. return None
  190. except Exception as e:
  191. logger.error(e)
  192. return None
  193. return _baseHref.format(_cardNo, str(card.id))
  194. def login_context(request):
  195. if 'devNo' not in request.GET and 'l' not in request.GET and 'agentId' not in request.GET:
  196. return ErrorResponseRedirect(error=cn(u'错误的二维码或者二维码损坏,请联系工作人员进行维修'))
  197. href = request.GET.get('redirect', '/user/index.html#/user/me')
  198. if 'agentId' in request.GET:
  199. # 个人中心登录
  200. dev = None # type: Optional[DeviceDict]
  201. product_agent_id = str(request.GET.get("agentId"))
  202. product_agent = Agent.objects(id = product_agent_id).get() # type: Agent
  203. cardNo = request.GET.get("cardNo")
  204. if cardNo:
  205. href = generate_card_recharge_href(cardNo, product_agent_id) or href
  206. state = by_agent(request, product_agent_id, href)
  207. groupId = MyUser._product_group_id(product_agent_id)
  208. else:
  209. # 扫描登录
  210. devNo = request.GET.get('devNo', None)
  211. logicalCode = request.GET.get('l', None)
  212. dev, product_agent, state = by_dev(request, devNo, logicalCode, request.GET.get('chargeIndex', None))
  213. groupId = dev.groupId
  214. if detect_wechat_client(request):
  215. # 微信平台登录
  216. auth_bridge = get_wechat_auth_bridge(
  217. source = product_agent, app_type = APP_TYPE.WECHAT_AUTH) # type: WechatAuthBridge
  218. pay_type = u'微信'
  219. auth_callback = None # 具体处理流程中写死
  220. elif detect_alipay_client(request):
  221. # 支付宝平台登录
  222. auth_bridge = get_ali_auth_bridge(source=product_agent,
  223. app_type=APP_TYPE.ALIPAY_AUTH) # type: AlipayAuthBridge
  224. pay_type = u'支付宝'
  225. auth_callback = USER_AUTH_REDIRECT_URL.ALIPAY
  226. else:
  227. raise UserServerException(u'不支持该平台下扫码')
  228. if not auth_bridge.enable:
  229. raise UserServerException(u'{}平台暂时未开通,请使用其他方式登录'.format(pay_type))
  230. if not product_agent.customizedUserGzhAllowable:
  231. return ErrorResponseRedirect(error=cn(u'系统配置错误,请联系平台客服(10009)'))
  232. return auth_bridge, auth_callback, product_agent, state, pay_type, dev, groupId
  233. def clone_from_login_user(login_user, auth_bridge, groupId, new_product_agent_id, new_agent_id):
  234. if login_user.groupId == groupId:
  235. my_user = login_user
  236. need_save = False
  237. if my_user.agentId != new_agent_id:
  238. my_user.agentId = new_agent_id
  239. need_save = True
  240. if my_user.productAgentId != new_product_agent_id:
  241. my_user.productAgentId = new_product_agent_id
  242. need_save = True
  243. if need_save:
  244. my_user.save()
  245. else:
  246. if login_user.productAgentId == new_product_agent_id:
  247. payload = login_user.cloneable_user_info
  248. else:
  249. payload = {}
  250. payload.update({
  251. 'authAppId': auth_bridge.appid,
  252. 'agentId': new_agent_id,
  253. 'productAgentId': new_product_agent_id
  254. })
  255. my_user = MyUser.get_or_create(app_platform_type = auth_bridge.gateway_type,
  256. open_id = login_user.openId,
  257. group_id = groupId,
  258. **payload)
  259. return my_user
  260. try:
  261. ip = get_client_ip(request)
  262. logger.debug("user<ip={}> login. ".format(ip))
  263. auth_bridge, auth_callback, product_agent, state, pay_type, dev, groupId = login_context(request)
  264. login_user = request.user # type: MyUser
  265. if auth_bridge.gateway_type == AppPlatformType.WECHAT:
  266. need_auth = (not login_user.is_authenticated()) or (login_user.authAppId != auth_bridge.appid)
  267. if state.by == UserAuthState.BY.AGENT:
  268. if need_auth:
  269. manager_auth_bridge = get_wechat_auth_bridge(product_agent, APP_TYPE.WECHAT_USER_MANAGER)
  270. if manager_auth_bridge.appid == auth_bridge.appid:
  271. logger.debug('auth bridge is same with manager auth bridge.')
  272. return ExternalResponseRedirect(
  273. auth_bridge.generate_auth_url_user_scope(
  274. redirect_uri = USER_AUTH_REDIRECT_URL.WECHAT_USER_CENTER_AUTH_USER,
  275. payload = state.encode()))
  276. else:
  277. return ExternalResponseRedirect(
  278. auth_bridge.generate_auth_url_base_scope(
  279. redirect_uri = USER_AUTH_REDIRECT_URL.WECHAT_USER_CENTER_AUTH_BASE,
  280. payload = state.encode()))
  281. else:
  282. my_user = clone_from_login_user(
  283. login_user, auth_bridge, groupId, str(product_agent.id), str(product_agent.id))
  284. manager_auth_bridge = get_wechat_auth_bridge(product_agent, APP_TYPE.WECHAT_USER_MANAGER)
  285. manager_openid = my_user.get_bound_pay_openid(manager_auth_bridge.bound_openid_key)
  286. if manager_openid and (manager_openid != my_user.managerialOpenId):
  287. my_user.managerialAppId = manager_auth_bridge.appid
  288. my_user.managerialOpenId = manager_openid
  289. my_user.save()
  290. if (not manager_openid) or (not my_user.nickname):
  291. state.uid = str(my_user.id)
  292. return ExternalResponseRedirect(
  293. manager_auth_bridge.generate_auth_url_user_scope(
  294. redirect_uri = USER_AUTH_REDIRECT_URL.WECHAT_USER_CENTER_MANAGER_AUTH_USER,
  295. payload = state.encode()))
  296. else:
  297. if need_auth:
  298. return ExternalResponseRedirect(
  299. auth_bridge.generate_auth_url_base_scope(
  300. redirect_uri = USER_AUTH_REDIRECT_URL.WECHAT_AUTH_BASE,
  301. payload = state.encode()))
  302. else:
  303. my_user = clone_from_login_user(
  304. login_user, auth_bridge, groupId, str(product_agent.id),
  305. dev.owner.agentId if dev else str(product_agent.id))
  306. state.uid = str(my_user.id)
  307. response = auth_wechat_manager_app(my_user, product_agent, state, dev)
  308. if response:
  309. return response
  310. response = auth_wechat_pay_app(
  311. my_user, dev.owner, product_agent, state, USER_AUTH_REDIRECT_URL.WECHAT_PAY_AUTH_BASE)
  312. if response:
  313. return response
  314. else:
  315. if not login_user.is_authenticated():
  316. return ExternalResponseRedirect(
  317. auth_bridge.generate_auth_url_user_scope(
  318. redirect_uri=auth_callback,
  319. payload=state.encode()))
  320. else:
  321. my_user = clone_from_login_user(
  322. login_user, auth_bridge, groupId, str(product_agent.id),
  323. dev.owner.agentId if dev else str(product_agent.id))
  324. if my_user.nickname is None:
  325. return ExternalResponseRedirect(
  326. auth_bridge.generate_auth_url_user_scope(
  327. redirect_uri = auth_callback,
  328. payload = state.encode()))
  329. if state.by == UserAuthState.BY.AGENT:
  330. response = FrontEndResponseRedirect(str(state.href))
  331. else:
  332. response = get_homepage_response(auth_bridge.gateway_type, my_user, dev,
  333. state.chargeIndex if state.chargeIndex else '', product_agent)
  334. return response_with_login(request, my_user, response)
  335. except UserServerException as e:
  336. return ErrorResponseRedirect(error=cn(e.message))
  337. except Exception as e:
  338. logger.exception(e)
  339. return ErrorResponseRedirect(error=cn(u'系统错误'))
  340. @trace_call(logger = logger)
  341. @error_tolerate(nil = defaultErrorResponseRedirect, logger = logger)
  342. def wxpayBaseAccess(request):
  343. # type: (WSGIRequest)->HttpResponse
  344. """
  345. 获取微信用户支付的openId
  346. :param request:
  347. :return:
  348. """
  349. def authorize(app, request):
  350. # type: (Optional[WechatPayApp], WSGIRequest)->None
  351. if isinstance(app, WechatPayApp):
  352. code = request.GET.get('code', None)
  353. if not code:
  354. raise InvalidParameter(u'参数错误,请重新扫码({})'.format(ErrorCode.AUTH_CODE_IS_NULL))
  355. auth_bridge = WechatAuthBridge(app)
  356. openId = auth_bridge.authorize(code)
  357. user.set_bound_pay_openid(auth_bridge.bound_openid_key, openId = openId)
  358. user.save()
  359. try:
  360. if 'code' not in request.GET and 'openId' not in request.GET:
  361. raise InvalidParameter(u'参数错误,请重新扫码({})'.format(ErrorCode.AUTH_CODE_IS_NULL))
  362. state = parse_auth_payload(request)
  363. if not state.is_valid():
  364. raise InvalidParameter(u'参数错误,请重新扫码({})'.format(ErrorCode.USER_STATE_IS_NOT_VALID))
  365. user = MyUser.objects.get(id = state.uid) # type: MyUser
  366. dev = Device.get_dev(state.devNo) # type: DeviceDict
  367. product_agent = Agent.objects(id = str(state.productAgentId)).get()
  368. app = get_app(source = product_agent,
  369. app_type = APP_TYPE.WECHAT_ENV_PAY,
  370. role = ROLE.myuser) # type: PayAppBase
  371. authorize(app, request)
  372. response = get_homepage_response(AppPlatformType.WECHAT, user, dev,
  373. state.chargeIndex if state.chargeIndex else '', product_agent)
  374. return response_with_login(request, user, response)
  375. except Exception as e:
  376. logger.exception(e)
  377. return ErrorResponseRedirect(error = u'系统错误, 请重新扫码')
  378. @trace_call(logger = logger)
  379. @error_tolerate(nil = defaultErrorResponseRedirect)
  380. def wechatAuthBase(request):
  381. # type: (WSGIRequest)->HttpResponse
  382. """
  383. 老终端用户扫码进入
  384. 只获取openId
  385. 用户通过扫码转到的中继器
  386. :param request:
  387. :return:
  388. """
  389. try:
  390. auth_code = request.GET.get('code', None)
  391. if auth_code is None:
  392. raise UserServerException(u'网络开小差了,重新扫码试试喔(%s)' % ErrorCode.AUTH_CODE_IS_NULL)
  393. state = parse_auth_payload(request) # type: UserAuthState
  394. logger.info('return to wechatAuthBase. code = %s; state = %s' % (auth_code, state))
  395. product_agent = Agent.objects(id = str(state.productAgentId)).get() # type: Agent
  396. dev = Device.get_dev(state.devNo) # type: DeviceDict
  397. groupId = dev.groupId
  398. auth_bridge = get_wechat_auth_bridge(source = product_agent, app_type = APP_TYPE.WECHAT_AUTH)
  399. logger.debug(
  400. 'wechat auth for login. appid = {}, code = {}, state = {}, agent = {}, group_id = {}'.format(
  401. auth_bridge.appid, auth_code, str(state.encode()), str(product_agent.id), groupId))
  402. openId = auth_bridge.authorize(auth_code)
  403. if not openId:
  404. logger.error(
  405. 'auth error, app = %s; payload = %s' % (repr(auth_bridge.app), str(state.encode())))
  406. return ErrorResponseRedirect(error = u'系统错误,请重新扫码')
  407. payload = {
  408. 'authAppId': auth_bridge.app.appid,
  409. 'agentId': str(state.agentId),
  410. 'productAgentId': str(state.productAgentId),
  411. 'payOpenIdMap': {
  412. auth_bridge.bound_openid_key: BoundOpenInfo(openId = openId)
  413. }
  414. }
  415. manager_auth_bridge = get_wechat_auth_bridge(source = product_agent, app_type = APP_TYPE.WECHAT_USER_MANAGER)
  416. if manager_auth_bridge.appid == auth_bridge.appid:
  417. payload.update({
  418. 'managerialAppId': auth_bridge.appid,
  419. 'managerialOpenId': openId
  420. })
  421. my_user = MyUser.get_or_create(
  422. app_platform_type = AppPlatformType.WECHAT, open_id = openId, group_id = groupId, **payload)
  423. if not my_user:
  424. raise UserServerException(u'网络开小差了,重新扫码试试喔(%s)' % ErrorCode.LOGIN_USER_IS_NULL)
  425. dealer = dev.owner # type: Dealer
  426. state.uid = str(my_user.id)
  427. response = auth_wechat_manager_app(my_user, product_agent, state, dev)
  428. if response:
  429. return response
  430. response = auth_wechat_pay_app(my_user, dealer, product_agent, state, USER_AUTH_REDIRECT_URL.WECHAT_PAY_AUTH_BASE)
  431. if response:
  432. return response
  433. response = get_homepage_response(AppPlatformType.WECHAT, my_user, dev,
  434. state.chargeIndex if state.chargeIndex else '', product_agent)
  435. return response_with_login(request, my_user, response)
  436. except UserServerException as e:
  437. logger.error(e.message)
  438. return ErrorResponseRedirect(error = cn(e.message))
  439. except Exception as e:
  440. logger.exception(e)
  441. return ErrorResponseRedirect(error = cn(u'网络开小差了,重新扫码试试喔'))
  442. @trace_call(logger = logger)
  443. @error_tolerate(nil = ErrorResponseRedirect, logger = logger)
  444. def wechatManagerAuthBase(request):
  445. # type: (WSGIRequest)->HttpResponse
  446. """
  447. manager做基础鉴权, 获取OpenId. 只有从用户信息获取不到managerOpenId的情况下才会走这个分支
  448. :param request:
  449. :return:
  450. """
  451. try:
  452. auth_code = request.GET.get(WechatAuthBridge.auth_code_key, None)
  453. if not auth_code:
  454. raise InvalidParameter(u'参数错误,请重新扫码({})'.format(ErrorCode.AUTH_CODE_IS_NULL))
  455. state = parse_auth_payload(request)
  456. my_user = MyUser.objects.get(id = state.uid)
  457. product_agent = Agent.objects(id = str(state.productAgentId)).get()
  458. manager_auth_bridge = get_wechat_auth_bridge(
  459. source = product_agent, app_type = APP_TYPE.WECHAT_USER_MANAGER) # type: WechatAuthBridge
  460. openId = manager_auth_bridge.authorize(auth_code)
  461. if openId is None:
  462. logger.error(
  463. 'manager auth error, app = %s; state = %s' % (repr(manager_auth_bridge.app), str(state.encode())))
  464. return ErrorResponseRedirect(error = u'系统错误, 请重新扫码')
  465. my_user.managerialAppId = manager_auth_bridge.appid
  466. my_user.managerialOpenId = openId
  467. my_user.set_bound_pay_openid(manager_auth_bridge.bound_openid_key, openId = openId)
  468. my_user.save()
  469. dev = Device.get_dev(state.devNo) # type: DeviceDict
  470. response = auth_wechat_manager_app(my_user, product_agent, state, dev)
  471. if response:
  472. return response
  473. response = auth_wechat_pay_app(my_user, dev.owner, product_agent, state, USER_AUTH_REDIRECT_URL.WECHAT_PAY_AUTH_BASE)
  474. if response:
  475. return response
  476. response = get_homepage_response(AppPlatformType.WECHAT, my_user, dev,
  477. state.chargeIndex if state.chargeIndex else '', product_agent)
  478. return response_with_login(request, my_user, response)
  479. except UserServerException as e:
  480. logger.error(e.message)
  481. return ErrorResponseRedirect(error = cn(e.message))
  482. except WechatOAuthDummyException as e:
  483. logger.error(e.message)
  484. return WechatAuthDummyRedirect()
  485. except Exception as e:
  486. logger.exception(e)
  487. return ErrorResponseRedirect(error = cn(u'网络开小差了,重新扫码试试喔'))
  488. @trace_call(logger = logger)
  489. @error_tolerate(nil = ErrorResponseRedirect, logger = logger)
  490. def wechatManagerAuthUser(request):
  491. # type: (WSGIRequest)->HttpResponse
  492. """
  493. 用户首次授权,需要创建用户
  494. :param request:
  495. :return:
  496. """
  497. try:
  498. auth_code = request.GET.get(WechatAuthBridge.auth_code_key, None)
  499. if not auth_code:
  500. raise InvalidParameter(u'参数错误,请重新扫码({})'.format(ErrorCode.AUTH_CODE_IS_NULL))
  501. state = parse_auth_payload(request)
  502. user = MyUser.objects.get(id = state.uid)
  503. product_agent = Agent.objects(id = str(state.productAgentId)).get()
  504. manager_auth_bridge = get_wechat_auth_bridge(
  505. source = product_agent, app_type = APP_TYPE.WECHAT_USER_MANAGER) # type: WechatAuthBridge
  506. userInfo = manager_auth_bridge.get_user_info(auth_code = auth_code)
  507. openId = userInfo['openId']
  508. if openId is None:
  509. logger.error(
  510. 'manager auth error, app = %s; payload = %s' % (repr(manager_auth_bridge.app), str(state.encode())))
  511. return ErrorResponseRedirect(error = u'系统错误, 请重新扫码')
  512. user.sex = userInfo.get('sex', 0)
  513. user.city = userInfo.get('city', '')
  514. user.province = userInfo.get('province', '')
  515. user.country = userInfo.get('country', '')
  516. user.nickname = userInfo.get('nickname', '')
  517. user.avatar = userInfo.get('avatar', '')
  518. user.unionId = userInfo.get('unionid', '')
  519. user.set_bound_pay_openid(manager_auth_bridge.bound_openid_key, openId = openId)
  520. user.managerialAppId = manager_auth_bridge.appid
  521. user.managerialOpenId = openId
  522. user.save()
  523. dev = Device.get_dev(state.devNo) # type: DeviceDict
  524. response = auth_wechat_pay_app(user, dev.owner, product_agent, state, USER_AUTH_REDIRECT_URL.WECHAT_PAY_AUTH_BASE)
  525. if response:
  526. return response
  527. response = get_homepage_response(AppPlatformType.WECHAT, user, dev,
  528. state.chargeIndex if state.chargeIndex else '', product_agent)
  529. return response_with_login(request, user, response)
  530. except UserServerException as e:
  531. logger.error(e.message)
  532. return ErrorResponseRedirect(error = cn(e.message))
  533. except WechatOAuthDummyException as e:
  534. logger.error(e.message)
  535. return WechatAuthDummyRedirect()
  536. except Exception as e:
  537. logger.exception(e)
  538. return ErrorResponseRedirect(error = cn(u'网络开小差了,重新扫码试试喔'))
  539. @trace_call(logger = logger)
  540. @error_tolerate(nil=defaultErrorResponseRedirect)
  541. def wechatBaseAuthForUserCenter(request):
  542. # type: (WSGIRequest)->HttpResponse
  543. """
  544. 个人中心
  545. :param request:
  546. :return:
  547. """
  548. try:
  549. auth_code = request.GET.get('code', None)
  550. if auth_code is None:
  551. raise UserServerException(u'网络开小差了,重新扫码试试喔(%s)' % ErrorCode.AUTH_CODE_IS_NULL)
  552. state = parse_auth_payload(request) # type: UserAuthState
  553. assert state.by == UserAuthState.BY.AGENT, 'must be enter user center.'
  554. logger.info('return to wechatBaseAuthForUserCenter. code = %s; state = %s' % (auth_code, state))
  555. product_agent = Agent.objects(id = str(state.productAgentId)).get() # type: Agent
  556. groupId = MyUser.groupId.default
  557. auth_bridge = get_wechat_auth_bridge(source = product_agent, app_type = APP_TYPE.WECHAT_AUTH)
  558. logger.debug(
  559. 'wechat base auth for user center login. appid = {}, code = {}, state = {}, agent = {}, group_id = {}'.format(
  560. auth_bridge.appid, auth_code, str(state.encode()), str(product_agent.id), groupId))
  561. openId = auth_bridge.authorize(auth_code)
  562. if not openId:
  563. logger.error(
  564. 'auth error, app = %s; payload = %s' % (repr(auth_bridge.app), str(state.encode())))
  565. return ErrorResponseRedirect(error = u'系统错误,请重新扫码')
  566. payload = {
  567. 'authAppId': auth_bridge.app.appid,
  568. 'agentId': str(state.agentId),
  569. 'productAgentId': str(state.productAgentId),
  570. 'payOpenIdMap': {
  571. auth_bridge.bound_openid_key: BoundOpenInfo(openId = openId)
  572. }
  573. }
  574. user = MyUser.get_or_create(
  575. app_platform_type = AppPlatformType.WECHAT, open_id = openId, group_id = groupId, **payload)
  576. manager_auth_bridge = get_wechat_auth_bridge(
  577. source = product_agent, app_type = APP_TYPE.WECHAT_USER_MANAGER)
  578. manager_openid = user.get_bound_pay_openid(manager_auth_bridge.bound_openid_key)
  579. if manager_openid and (manager_openid != user.managerialOpenId):
  580. user.managerialOpenId = manager_openid
  581. user.managerialAppId = manager_auth_bridge.appid
  582. user.save()
  583. if (not manager_openid) or (not user.nickname):
  584. state.uid = str(user.id)
  585. return ExternalResponseRedirect(
  586. manager_auth_bridge.generate_auth_url_user_scope(
  587. redirect_uri = USER_AUTH_REDIRECT_URL.WECHAT_USER_CENTER_MANAGER_AUTH_USER,
  588. payload = state.encode()))
  589. else:
  590. logger.debug('redirect url is: {}'.format(state.href))
  591. response = FrontEndResponseRedirect(str(state.href))
  592. return response_with_login(request, user, response)
  593. except UserServerException as e:
  594. logger.error(e.message)
  595. return ErrorResponseRedirect(error = cn(e.message))
  596. except Exception as e:
  597. logger.exception(e)
  598. return ErrorResponseRedirect(error = cn(u'网络开小差了,重新扫码试试喔'))
  599. @trace_call(logger = logger)
  600. @error_tolerate(nil = defaultErrorResponseRedirect)
  601. def wechatUserAuthForUserCenter(request):
  602. # type: (WSGIRequest)->HttpResponse
  603. """
  604. 个人中心
  605. :param request:
  606. :return:
  607. """
  608. try:
  609. auth_code = request.GET.get('code', None)
  610. if auth_code is None:
  611. raise UserServerException(u'网络开小差了,重新扫码试试喔(%s)' % ErrorCode.AUTH_CODE_IS_NULL)
  612. state = parse_auth_payload(request) # type: UserAuthState
  613. assert state.by == UserAuthState.BY.AGENT, 'must be enter user center.'
  614. logger.info('return to wechatUserAuthForUserCenter. code = %s; state = %s' % (auth_code, state))
  615. product_agent = Agent.objects(id = str(state.productAgentId)).get() # type: Agent
  616. groupId = MyUser.groupId.default
  617. auth_bridge = get_wechat_auth_bridge(source = product_agent, app_type = APP_TYPE.WECHAT_AUTH)
  618. logger.debug(
  619. 'wechat user auth for user center login. appid = {}, code = {}, state = {}, agent = {}, group_id = {}'.format(
  620. auth_bridge.appid, auth_code, str(state.encode()), str(product_agent.id), groupId))
  621. userInfo = auth_bridge.get_user_info(auth_code = auth_code)
  622. openId = userInfo['openId']
  623. if openId is None:
  624. logger.error(
  625. 'manager auth error, app = %s; payload = %s' % (repr(auth_bridge.app), str(state.encode())))
  626. return ErrorResponseRedirect(error = u'系统错误, 请重新扫码')
  627. payload = {
  628. 'sex': userInfo.get('sex', 0),
  629. 'city': userInfo.get('city', ''),
  630. 'province': userInfo.get('province', ''),
  631. 'country': userInfo.get('country', ''),
  632. 'nickname': userInfo.get('nickname', ''),
  633. 'avatar': userInfo.get('avatar', ''),
  634. 'unionId': userInfo.get('unionid', ''),
  635. 'authAppId': auth_bridge.appid,
  636. 'payOpenIdMap': {
  637. auth_bridge.bound_openid_key: BoundOpenInfo(openId = openId)
  638. },
  639. 'agentId': str(state.agentId),
  640. 'productAgentId': str(state.productAgentId),
  641. 'managerialAppId': auth_bridge.appid,
  642. 'managerialOpenId': openId
  643. }
  644. user = MyUser.get_or_create(app_platform_type = AppPlatformType.WECHAT,
  645. open_id = openId, group_id = groupId, **payload)
  646. logger.debug('redirect url is: {}'.format(state.href))
  647. response = FrontEndResponseRedirect(str(state.href))
  648. return response_with_login(request, user, response)
  649. except UserServerException as e:
  650. logger.error(e.message)
  651. return ErrorResponseRedirect(error = cn(e.message))
  652. except WechatOAuthDummyException as e:
  653. logger.error(e.message)
  654. return WechatAuthDummyRedirect()
  655. except Exception as e:
  656. logger.exception(e)
  657. return ErrorResponseRedirect(error = cn(u'网络开小差了,重新扫码试试喔'))
  658. @trace_call(logger = logger)
  659. @error_tolerate(nil=ErrorResponseRedirect, logger=logger)
  660. def wechatManagerAuthForUserCenter(request):
  661. # type: (WSGIRequest)->HttpResponse
  662. """
  663. :param request:
  664. :return:
  665. """
  666. try:
  667. auth_code = request.GET.get(WechatAuthBridge.auth_code_key, None)
  668. if not auth_code:
  669. raise InvalidParameter(u'参数错误,请重新扫码({})'.format(ErrorCode.AUTH_CODE_IS_NULL))
  670. state = parse_auth_payload(request)
  671. assert state.by == UserAuthState.BY.AGENT, 'must enter in user center.'
  672. user = MyUser.objects.get(id=state.uid)
  673. product_agent = Agent.objects(id=str(state.productAgentId)).get()
  674. manager_auth_bridge = get_wechat_auth_bridge(
  675. source=product_agent, app_type=APP_TYPE.WECHAT_USER_MANAGER) # type: WechatAuthBridge
  676. userInfo = manager_auth_bridge.get_user_info(auth_code=auth_code)
  677. openId = userInfo['openId']
  678. if openId is None:
  679. logger.error(
  680. 'manager auth error, app = %s; payload = %s' % (repr(manager_auth_bridge.app), str(state.encode())))
  681. raise UserServerException(u'系统错误, 请重新扫码')
  682. user.sex = userInfo.get('sex', 0)
  683. user.city = userInfo.get('city', '')
  684. user.province = userInfo.get('province', '')
  685. user.country = userInfo.get('country', '')
  686. user.nickname = userInfo.get('nickname', '')
  687. user.avatar = userInfo.get('avatar', '')
  688. user.unionId = userInfo.get('unionid', '')
  689. user.set_bound_pay_openid(manager_auth_bridge.bound_openid_key, openId=openId)
  690. user.managerialAppId = manager_auth_bridge.appid
  691. user.managerialOpenId = openId
  692. user.save()
  693. logger.debug('redirect url is: {}'.format(state.href))
  694. response = FrontEndResponseRedirect(str(state.href))
  695. return response_with_login(request, user, response)
  696. except UserServerException as e:
  697. logger.error(e.message)
  698. return ErrorResponseRedirect(error=cn(e.message))
  699. except WechatOAuthDummyException as e:
  700. logger.error(e.message)
  701. return WechatAuthDummyRedirect()
  702. except Exception as e:
  703. logger.exception(e)
  704. return ErrorResponseRedirect(error=cn(u'网络开小差了,重新扫码试试喔'))
  705. @permission_required(ROLE.myuser)
  706. def baseMoniAccess(request):
  707. """
  708. moni app 的鉴权
  709. """
  710. code = request.GET.get("code", None)
  711. if code is None:
  712. raise UserServerException(u'网络开小差了,重新扫码试试喔(%s)' % ErrorCode.MONI_AUTH_IS_NULL)
  713. state = parse_auth_payload(request) # type: UserAuthState
  714. inhouseMoniApp = MoniApp.objects.filter(appid=state.appid).first() # type: MoniApp
  715. if not inhouseMoniApp:
  716. raise UserServerException(u'网络开小差了,重新扫码试试喔(%s)' % ErrorCode.MONI_APP_IS_NULL)
  717. user = MyUser.objects.filter(id=state.uid).first()
  718. if not user:
  719. raise UserServerException(u'网络开小差了,重新扫码试试喔(%s)' % ErrorCode.LOGIN_USER_IS_NULL)
  720. # 存在app 的情况下 使用app进行解码 写入数据
  721. moniAuthBridge = WechatAuthBridge(WechatAuthApp(appid=inhouseMoniApp.appid, secret=inhouseMoniApp.secret))
  722. openId = moniAuthBridge.authorize(code)
  723. user.set_bound_pay_openid(moniAuthBridge.bound_openid_key, openId=openId)
  724. user.save()
  725. productAgent = Agent.objects.get(id=state.productAgentId)
  726. dev = Device.get_dev(state.devNo)
  727. response = get_homepage_response(AppPlatformType.WECHAT, user, dev, state.chargeIndex, productAgent)
  728. return response_with_login(request, user, response)
  729. @error_tolerate(logger=logger, nil=JsonErrorResponse(description=u"系统繁忙,请稍后重试"))
  730. @permission_required(ROLE.myuser)
  731. @request_limit_by_user(operation='equipmentPara', logger=logger)
  732. def equipmentPara(request):
  733. # type: (WSGIRequest)->HttpResponse
  734. """
  735. 扫码后获取设备侧以及用户的相关信息
  736. """
  737. currentUser = request.user # type: MyUser
  738. logicalCode = request.GET.get("logicalCode")
  739. force = True if request.GET.get('refresh', 'false') == 'true' else False
  740. dev = Device.get_dev_by_l(logicalCode) # type: DeviceDict
  741. if not dev:
  742. logger.info('(%s) cannot find device, devNo = %s' % (request.user, logicalCode))
  743. return JsonErrorResponse(description=u"该设备尚未注册(1002)")
  744. if not dev.group:
  745. logger.info('can not find group. dev = %s' % dev)
  746. return JsonErrorResponse(description=u'该设备未注册,暂时无法使用支付宝或者微信支付, 请投币(1010)')
  747. if not dev.dealer:
  748. logger.info('can not find dealer. dev = %s; group = %s' % (str(dev), str(dev.group)))
  749. return JsonErrorResponse(description=u'该设备未注册,暂时无法使用支付宝或者微信支付, 请投币(1011)')
  750. if check_black_user(dealerId=dev.get("ownerId"), openId = request.user.openId):
  751. return JsonErrorResponse(u"该设备暂不对您开放,请联系经销商")
  752. agent = Agent.objects(id=str(dev.dealer['agentId'])).first() # type: Agent
  753. agentFeatures = set(agent.features) if agent is not None else set([])
  754. dealer_features = map(lambda x: x['key'], filter(lambda x: x['value'] is True, dev.dealer['featureList']))
  755. if 'mini_recharge' in dealer_features:
  756. agentFeatures.add('mini_recharge')
  757. if 'mini_card_recharge' in dealer_features:
  758. agentFeatures.add('mini_card_recharge')
  759. devType = deepcopy(dev.devType)
  760. try:
  761. portDict = dev.deviceAdapter.get_port_status(force)
  762. if not force:
  763. dev.deviceAdapter.async_update_portinfo_from_dev()
  764. if portDict:
  765. chargeIndex = {}
  766. for index, info in portDict.items():
  767. if info['status'] == Const.DEV_WORK_STATUS_IDLE:
  768. chargeIndex[index] = 'idle'
  769. elif info['status'] == Const.DEV_WORK_STATUS_WORKING:
  770. chargeIndex[index] = 'busy'
  771. elif info['status'] == Const.DEV_WORK_STATUS_FAULT:
  772. chargeIndex[index] = 'fault'
  773. elif info['status'] == Const.DEV_WORK_STATUS_FORBIDDEN:
  774. chargeIndex[index] = 'ban'
  775. elif info['status'] == Const.DEV_WORK_STATUS_CONNECTED:
  776. chargeIndex[index] = 'connected'
  777. elif info['status'] == Const.DEV_WORK_STATUS_FINISHED:
  778. chargeIndex[index] = 'finished'
  779. elif info['status'] == Const.DEV_WORK_STATUS_ESTOP:
  780. chargeIndex[index] = 'estop'
  781. elif info['status'] == Const.DEV_WORK_STATUS_READY:
  782. chargeIndex[index] = 'ready'
  783. else:
  784. chargeIndex[index] = 'busy'
  785. devType.update({"chargeIndex": chargeIndex})
  786. except ServiceException as e:
  787. return JsonErrorResponse(description=e.result.get('description'))
  788. except Exception as e:
  789. logger.exception('cannot get_port_status, error=%s' % (str(e),))
  790. return JsonErrorResponse(description=u'未知错误')
  791. data = {
  792. "devType": devType,
  793. "groupId": dev.groupId,
  794. "cityId": dev.group.get('districtId', ''),
  795. "inFreeGroup": dev.group.get('isFree', False),
  796. "lbs": dev.lbs,
  797. "instructions": dev.get('instructions', ''),
  798. "logicalCode": dev.logicalCode,
  799. "payAfterAd": dev.dealer['adShow'],
  800. "dealerId": dev.ownerId,
  801. "dealerDes": dev.dealer['description'],
  802. 'devNo': dev.devNo,
  803. 'channelType': dev.channelType,
  804. 'avatarUrl': currentUser.avatar,
  805. 'nickname': currentUser.nickname,
  806. 'openId': currentUser.openId,
  807. 'agentFeatures': list(agentFeatures),
  808. 'countDown': False,
  809. 'bottomAd': dev.dealer.get('bottomAd', {}),
  810. 'noRecharge': dev.dealer.get('noRecharge', False),
  811. 'favorite': True if dev.devNo in currentUser.collectedDeviceList else False,
  812. "payAfterUse": dev.get("otherConf", dict()).get("payAfterUse", False),
  813. 'majorDeviceType': dev.majorDeviceType,
  814. 'subTemplateId': agent.get_user_sub_template_id_list(),
  815. 'priceDescription': dev.priceDescription,
  816. 'popPriceDescriptionButton': dev.group.popPriceDescriptionButton
  817. }
  818. if "hasTempPackage" in dev.dealer:
  819. if dev.devTypeCode in [Const.DEVICE_TYPE_CODE_WEIFULE_POLICY_CLASSIC]:
  820. data["hasTempPackage"] = False
  821. data["displayTempPackage"] = False
  822. elif dev.devTypeCode in support_policy_weifule + support_policy_device:
  823. try:
  824. data["displayTempPackage"] = dev.dealer.get("displayTempPackage", True)
  825. packages = dev.deviceAdapter.user_show_package(isTemp=True)
  826. if packages:
  827. data["hasTempPackage"] = True
  828. else:
  829. data["hasTempPackage"] = False
  830. except Exception as e:
  831. logger.error("[equipmentPara] get hasTempPackage error = {}".format(e))
  832. data["hasTempPackage"] = False
  833. else:
  834. if dev.dealer.get("hasTempPackage", None) is True:
  835. data["hasTempPackage"] = dev.dealer.get("hasTempPackage")
  836. data["displayTempPackage"] = dev.dealer.get("displayTempPackage", True)
  837. if dev.need_fetch_online:
  838. data.update({'online': DeviceOnlineStatus.DEV_STATUS_ONLINE})
  839. else:
  840. data.update({'online': DeviceOnlineStatus.DEV_STATUS_OFFLINE})
  841. if "telVerify" in agent.features:
  842. needTelVerify = check_user_tel(request.user)
  843. data.update({
  844. "needTelVerify": needTelVerify
  845. })
  846. data.update({'countDown': dev.deviceAdapter.support_count_down()})
  847. if dev.devTypeCode == Const.DEVICE_TYPE_CODE_TIMESWITCH7:
  848. pricePerHour = dev.my_obj.otherConf.get('pricePerHour', 2.0)
  849. data.update({'pricePerHour': pricePerHour})
  850. elif dev.devTypeCode in [
  851. Const.DEVICE_TYPE_CODE_CAR_NENGPAI,
  852. Const.DEVICE_TYPE_CODE_CHARGE_WEIFULE_CAR,
  853. Const.DEVICE_TYPE_CODE_CAR_WEIFULE_CHARGING_DOUB,
  854. Const.DEVICE_TYPE_CODE_CAR_WEIFULE_21KW,
  855. Const.DEVICE_TYPE_CODE_CAR_WEIFILE_HOME_JFPG,
  856. Const.DEVICE_TYPE_CODE_CAR_WEIFILE_HOME_DOUB_JFPG,
  857. ]:
  858. infos = dev.deviceAdapter.get_policy_for_user()
  859. data.update({"policyInfos": infos})
  860. resultResponse = JsonResponse({'result': 1, 'description': '', 'payload': data})
  861. resultResponse = Agent.record_cookie(dev.dealer['agentId'], resultResponse)
  862. return resultResponse
  863. @error_tolerate(nil = defaultErrorResponseRedirect)
  864. @permission_required(ROLE.myuser)
  865. def deviceInfo(request):
  866. """
  867. 通过logicalCode获取 设备的一些基本信息, 功能上需要和equipment区分开
  868. :param request:
  869. :return:
  870. """
  871. logicalCode = request.GET.get("logicalCode")
  872. if not logicalCode:
  873. return JsonErrorResponse(description = u"无效的设备编号")
  874. dev = Device.get_dev_by_l(logicalCode)
  875. if not dev:
  876. return JsonErrorResponse(description = u"无效的设备编号")
  877. group = Group.get_group(dev.get("groupId", ""))
  878. # TODO zjl 目前只添加这些信息,后续有需要再添加 但是此接口定义为获取设备的简易信息 需要和equipment区分
  879. data = {
  880. "devNo": dev.get("devNo", ""),
  881. "logicalCode": dev.get("logicalCode", ""),
  882. "ownerId": dev.get("ownerId", ""),
  883. "groupId": dev.get("groupId", ""),
  884. "groupName": group.get("groupName", ""),
  885. "isFree": group.get("isFree", False)
  886. }
  887. return JsonOkResponse(payload = data)
  888. @permission_required(ROLE.myuser)
  889. def userBalance(request):
  890. # type: (WSGIRequest)->JsonResponse
  891. """
  892. 用户余额
  893. 用户余额是以地址为单位建立 但是由于地址可以设置通用 并且个人中心也需要显示总余额
  894. """
  895. logicalCode = request.GET.get("logicalCode")
  896. if not logicalCode:
  897. overallBalance = sum((u.balance for u in request.user.product_users), RMB(0))
  898. return JsonOkResponse(
  899. payload={
  900. 'balance': overallBalance,
  901. 'overallBalance': overallBalance,
  902. 'currencyCoins': overallBalance
  903. })
  904. dev = Device.get_dev_by_l(logicalCode) # type: DeviceDict
  905. if not dev:
  906. return JsonErrorResponse(description=u'设备没有注册,或者二维码错误,请联系客服处理')
  907. if not dev.is_registered:
  908. return JsonErrorResponse(description=u'设备没有注册,请联系客服处理')
  909. if dev.ownerId != dev.group.ownerId:
  910. return JsonErrorResponse(description=u'设备注册信息错误,请联系客服处理')
  911. if dev.group.groupId != request.user.groupId:
  912. product_agent = get_user_manager_agent(dev.owner) # type: Agent
  913. if str(product_agent.id) != request.user.productAgentId:
  914. return JsonErrorResponse(description=u'设备投放地址不属于该平台,请重新扫描设备二维码。')
  915. # 分别为用户总余额、用户经销商下的余额、用户的通用地址余额
  916. overall, dealer_balance, usable_balance = request.user.get_balance_in_dealer(dev.owner, dev.group)
  917. return JsonOkResponse(
  918. payload={
  919. 'balance': usable_balance,
  920. 'balanceInDealer': dealer_balance,
  921. 'overallBalance': overall
  922. })
  923. @permission_required(ROLE.myuser)
  924. def getBalanceList(request):
  925. # type: (WSGIRequest)->Union[HttpResponse,JsonResponse]
  926. """
  927. 用户账户详情
  928. :param request:
  929. :return:
  930. """
  931. pageIndex = int(request.GET.get('pageIndex', 1))
  932. pageSize = int(request.GET.get('pageSize', 10))
  933. currentGroupId = request.GET.get('groupId', None)
  934. if currentGroupId == '-1':
  935. currentGroupId = None
  936. if currentGroupId:
  937. current_group = Group.get_group(currentGroupId) # type: GroupDict
  938. else:
  939. current_group = None # type: None
  940. totalCharge, totalBestow, total, dataList = request.user.filter_my_balance(current_group)
  941. cmp_dealer = lambda x, y: 1 if x['dealerId'] > y['dealerId'] else -1
  942. dataList.sort(cmp = cmp_dealer)
  943. return JsonResponse(
  944. {
  945. 'result': 1,
  946. 'description': '',
  947. 'payload': {
  948. 'totalCharge': totalCharge,
  949. 'totalBestow': totalBestow,
  950. 'total': total,
  951. 'dataList': dataList[(pageIndex - 1) * pageSize:pageIndex * pageSize]
  952. }
  953. }
  954. )
  955. def asynDiscountList(request):
  956. # type: (WSGIRequest)->JsonResponse
  957. """
  958. 用户充值菜单
  959. :param request:
  960. :return:
  961. """
  962. devNo = Device.get_dev_no_from_request(request)
  963. dev = Device.get_dev(devNo)
  964. if dev is None:
  965. return JsonResponse({'result': 0, 'description': u'该设备未开通网络支付,请投币或者联系客服(1000)', 'payload': {}})
  966. group = Group.get_group(dev['groupId']) # type:GroupDict
  967. if not group:
  968. return JsonResponse({'result': 0, 'description': u'该设备未开通网络支付,请投币或者联系客服(1001)', 'payload': {}})
  969. return JsonResponse({
  970. 'result': 1,
  971. 'description': 'SUCCESS',
  972. 'payload': {
  973. 'discountList': group.recharge_rule_list
  974. }
  975. })
  976. @permission_required(ROLE.myuser)
  977. def getPackage(request):
  978. # type: (WSGIRequest)->JsonResponse
  979. """
  980. 获取设备套餐
  981. :param request:
  982. :return:
  983. """
  984. devNo = request.GET.get("devNo")
  985. device = Device.get_dev(devNo) # type: DeviceDict
  986. if device is None:
  987. return JsonResponse({'result': 0, 'description': u'无此设备', 'payload': {}})
  988. washConfig = device['washConfig']
  989. otherConf = device.get('otherConf')
  990. if "displaySwitchs" in otherConf:
  991. displaySwitchs = otherConf.get('displaySwitchs')
  992. displaySwitchs = dict(filter(lambda x: "display" in x[0], displaySwitchs.items()))
  993. else:
  994. displaySwitchs = {
  995. 'displayCoinsSwitch': True,
  996. 'displayTimeSwitch': True,
  997. 'displayPriceSwitch': True
  998. }
  999. if device.devTypeCode in support_policy_weifule + support_policy_device + [
  1000. Const.DEVICE_TYPE_CODE_CAR_CHANGING_JINQUE,
  1001. Const.DEVICE_TYPE_CODE_CAR_WEIFILE_HOME_JFPG,
  1002. Const.DEVICE_TYPE_CODE_CAR_WEIFILE_HOME_DOUB_JFPG,
  1003. Const.DEVICE_TYPE_CODE_CHARGE_XIAOKEDOU
  1004. ]:
  1005. try:
  1006. if device.deviceAdapter.support_device_package:
  1007. packages = device.deviceAdapter.user_show_package()
  1008. return JsonResponse({'result': 1, 'description': 'SUCCESS', 'payload': packages})
  1009. except Exception as e:
  1010. logger.exception(e)
  1011. return JsonResponse({'result': 0, 'description': '当前套餐参数有误, 请联系经销商重新配置', 'payload': []})
  1012. packages = []
  1013. for packageId, rule in washConfig.items():
  1014. # 没有启用的套餐 直接掠过
  1015. if not rule.get("switch", True):
  1016. continue
  1017. price = rule['price']
  1018. imgList = []
  1019. try:
  1020. for img in rule.get('imgList', []):
  1021. if img.startswith('/'):
  1022. imgList.append('{}{}'.format(settings.OSS_RESOURCE_URL, img))
  1023. else:
  1024. imgList.append(img)
  1025. except Exception as e:
  1026. logger.exception(e)
  1027. imgList = rule.get('imgList', [])
  1028. item = {
  1029. 'id': packageId,
  1030. 'name': rule['name'],
  1031. 'time': rule['time'],
  1032. 'price': price,
  1033. 'description': rule.get('description', ''),
  1034. 'imgList': imgList,
  1035. 'unit': rule.get('unit', u'分钟'),
  1036. }
  1037. if rule.get('basePrice'):
  1038. item.update({'basePrice': rule.get('basePrice')})
  1039. if rule.get('sn', None) is not None:
  1040. item.update({'sn': rule.get('sn')})
  1041. if rule['name'] == u'充满自停' and float(rule['coins']) == 0 and float(price) == 0:
  1042. item.update({'displayCoinsSwitch': False, 'displayTimeSwitch': False, 'displayPriceSwitch': False})
  1043. else:
  1044. item.update(displaySwitchs)
  1045. packages.append(item)
  1046. packages = sorted(packages, key=lambda x: (x.get('sn'), x.get('price')))
  1047. return JsonResponse({'result': 1, 'description': 'SUCCESS', 'payload': packages})
  1048. @permission_required(ROLE.myuser)
  1049. def getTempPackage(request):
  1050. # type: (WSGIRequest)->JsonResponse
  1051. """
  1052. 设备套餐
  1053. :param request:
  1054. :return:
  1055. """
  1056. def cmp_by_price(x, y):
  1057. if x['price'] < y['price']:
  1058. return -1
  1059. elif x['price'] > y['price']:
  1060. return 1
  1061. else:
  1062. return 0
  1063. devNo = Device.get_dev_no_from_request(request)
  1064. if not devNo:
  1065. return JsonResponse({'result': 0, 'description': u'获取数据失败,请重新扫码登录'})
  1066. device = Device.get_dev(devNo)
  1067. if device is None:
  1068. return JsonResponse({'result': 0, 'description': u'无此设备', 'payload': {}})
  1069. if device['devType']['code'] in support_policy_weifule + support_policy_device:
  1070. try:
  1071. if device.deviceAdapter.support_device_package:
  1072. packages = device.deviceAdapter.user_show_package(isTemp=True)
  1073. if not packages:
  1074. return JsonResponse({'result': 0, 'description': '当前设备未配置临时套餐, 请联系经销商去配置', 'payload': {}})
  1075. else:
  1076. return JsonResponse({'result': 1, 'description': 'SUCCESS', 'payload': packages})
  1077. else:
  1078. return JsonResponse({'result': 0, 'description': '当前套餐参数有误, 请联系经销商重新配置', 'payload': []})
  1079. except:
  1080. return JsonResponse({'result': 0, 'description': '当前套餐参数有误, 请联系经销商重新配置', 'payload': []})
  1081. elif device['devType']['code'] in [Const.DEVICE_TYPE_CODE_CAR_CHANGING_JINQUE, Const.DEVICE_TYPE_CODE_CAR_WEIFILE_HOME_JFPG,Const.DEVICE_TYPE_CODE_CAR_WEIFILE_HOME_DOUB_JFPG,]:
  1082. tempWashConfig = device['tempWashConfig']
  1083. if not tempWashConfig:
  1084. return JsonResponse({'result': 0, 'description': u'当前设备未配置临时套餐, 请联系经销商去配置', 'payload': {}})
  1085. packages = device.deviceAdapter.user_show_package(isTemp=True)
  1086. return JsonResponse({'result': 1, 'description': 'SUCCESS', 'payload': packages})
  1087. if device['tempWashConfig'] == {}:
  1088. Device.get_and_update_device_cache(device["devNo"], tempWashConfig = device['washConfig'])
  1089. device = Device.get_dev(devNo)
  1090. tempWashConfig = device['tempWashConfig']
  1091. otherConf = device.get('otherConf')
  1092. if "displayTempSwitchs" in otherConf:
  1093. displayTempSwitchs = otherConf.get('displayTempSwitchs')
  1094. displayTempSwitchs = dict(filter(lambda x: "display" in x[0], displayTempSwitchs.items()))
  1095. else:
  1096. displayTempSwitchs = {'displayCoinsSwitch': True,
  1097. 'displayTimeSwitch': True,
  1098. 'displayPriceSwitch': True,
  1099. }
  1100. group = Group.get_group(device['groupId'])
  1101. # 探测是否地址为免费活动组,默认为否
  1102. is_free_service = group.get('isFree', False)
  1103. appendix = u' 免费使用' if is_free_service else ''
  1104. packages = []
  1105. for packageId, rule in tempWashConfig.items():
  1106. item = {
  1107. 'id': packageId,
  1108. 'coins': rule['coins'],
  1109. 'name': rule['name'] + appendix,
  1110. 'time': rule['time'],
  1111. 'price': rule['price'],
  1112. 'description': rule.get('description', ''),
  1113. 'imgList': rule.get('imgList', []),
  1114. 'unit': rule.get('unit', u'分钟')
  1115. }
  1116. if rule.get('basePrice'):
  1117. item.update({'basePrice': rule.get('basePrice')})
  1118. if rule.get('sn', None) is not None:
  1119. item.update({'sn': rule.get('sn')})
  1120. item.update(displayTempSwitchs)
  1121. packages.append(item)
  1122. packages = sorted(packages, key = lambda x: (x.get('sn'), x.get('price')))
  1123. return JsonResponse({'result': 1, 'description': 'SUCCESS', 'payload': packages})
  1124. def authCallback(request, gateway):
  1125. try:
  1126. state = UserAuthState.decode(str(request.GET.get('payload'))) # type: UserAuthState
  1127. if not state.is_valid():
  1128. return ErrorResponseRedirect(error = cn(u'网络异常,请重新扫码(10000)'))
  1129. if state.by == UserAuthState.BY.AGENT:
  1130. source = Agent.objects(id = str(state.agentId)).get() # type: Agent
  1131. group_id = MyUser.groupId.default
  1132. dealer = None
  1133. else:
  1134. dev = Device.get_dev(state.devNo) # type: DeviceDict
  1135. if not dev:
  1136. return ErrorResponseRedirect(error = u'该设备未开通网络支付,请投币或者联系客服(1006)')
  1137. source = dealer = dev.owner
  1138. if not dealer:
  1139. return ErrorResponseRedirect(error = u'该设备未开通网络支付,请投币或者联系客服(1007)')
  1140. group_id = dev.groupId
  1141. # 配置平台的代理商ID必定配置自定义公众号, 否则扫码客户无法知道平台代理商是谁
  1142. product_agent = get_user_manager_agent(source)
  1143. if str(product_agent.id) != state.productAgentId:
  1144. return ErrorResponseRedirect(error = u'系统配置错误,请联系平台客服(10004)')
  1145. if gateway == AppPlatformType.ALIPAY:
  1146. auth_bridge = get_ali_auth_bridge(source = product_agent,
  1147. app_type = APP_TYPE.ALIPAY_AUTH) # type: AlipayAuthBridge
  1148. else:
  1149. return ErrorResponseRedirect(error = cn(u'参数错误,请重新扫码(10001)'))
  1150. auth_code = request.GET.get(auth_bridge.auth_code_key)
  1151. if not auth_code:
  1152. return ErrorResponseRedirect(error = cn(u'参数错误,请重新扫码(10002)'))
  1153. user_info = auth_bridge.get_user_info(auth_code = auth_code)
  1154. open_id = user_info.pop('openId')
  1155. user = MyUser.get_or_create(
  1156. app_platform_type = auth_bridge.gateway_type,
  1157. open_id = open_id,
  1158. group_id = group_id,
  1159. authAppId = auth_bridge.appid,
  1160. agentId = state.agentId,
  1161. productAgentId = state.productAgentId,
  1162. payOpenIdMap = {
  1163. auth_bridge.bound_openid_key: BoundOpenInfo(openId = open_id)
  1164. },
  1165. **user_info)
  1166. if state.by == UserAuthState.BY.AGENT:
  1167. response = FrontEndResponseRedirect(state.href)
  1168. else:
  1169. response = get_homepage_response(gateway, user, dev, state.chargeIndex if state.chargeIndex else '',
  1170. product_agent)
  1171. return response_with_login(request, user, response)
  1172. except AliException as e:
  1173. logger.error(repr(e))
  1174. return ErrorResponseRedirect(error = cn(e.errMsg))
  1175. @error_tolerate(nil = u"获取消费详情失败", logger = logger)
  1176. @permission_required(ROLE.myuser)
  1177. def getConsumeRecord(request):
  1178. """
  1179. 获取用户的单一的 消费订单记录
  1180. :param request:
  1181. :return:
  1182. """
  1183. recordId = request.GET.get("id", None)
  1184. cardTicketId = request.GET.get('cardTicketId', None)
  1185. # 这个接口是同时 查询虚拟卡消费记录 以及用户的直接消费记录 的入口
  1186. if not any([recordId, cardTicketId]):
  1187. return JsonErrorResponse(description = u'参数错误,请刷新后再试')
  1188. if recordId:
  1189. ownerId = request.GET.get('ownerId', None)
  1190. if ownerId:
  1191. record = ClientConsumeModelProxy.get_one(shard_filter = {'ownerId': ownerId},
  1192. id = recordId) # type: ConsumeRecord
  1193. else:
  1194. record = ConsumeRecord.objects(id = recordId).first()
  1195. else:
  1196. record = VCardConsumeRecord.objects(id = cardTicketId).first() # type: VCardConsumeRecord
  1197. if not record:
  1198. return JsonErrorResponse(description = u"未查询到相应订单,请刷新页面重试")
  1199. payload = record.to_user_detail()
  1200. try:
  1201. agentId = request.user.productAgentId
  1202. agent = Agent.objects.get(id = agentId)
  1203. except Exception as e:
  1204. logger.exception(e)
  1205. agent = None
  1206. if payload.get("actualNeedTime"):
  1207. elecKeys = [_key for _key in payload.keys() if _key.startswith("elec") or _key.endswith("elec")]
  1208. for _elecKey in elecKeys:
  1209. payload.pop(_elecKey, None)
  1210. if not agent or 'show_elec_data_for_user' not in agent.features:
  1211. payload.pop('elec', None)
  1212. payload.pop('needElec', None)
  1213. if agent and 'hide_time_data_for_user' in agent.features:
  1214. payload.pop("leftTime", None)
  1215. payload.pop("duration", None)
  1216. payload = UserConsumeFilter(record.owner, payload).filter()
  1217. return JsonOkResponse(payload = payload)
  1218. @permission_required(ROLE.myuser)
  1219. def asynTransactionRecord(request):
  1220. # type: (WSGIRequest)->JsonResponse
  1221. """
  1222. 用户消费记录
  1223. :param request:
  1224. :return: JsonResponse
  1225. """
  1226. pageIndex = int(request.GET.get('pageIndex', 1))
  1227. pageSize = int(request.GET.get('pageSize', 10))
  1228. startTime = request.GET.get('startTime', Const.QUERY_START_DATE)
  1229. endTime = request.GET.get('endTime', datetime.datetime.now().strftime('%Y-%m-%d'))
  1230. dataList = []
  1231. if 'cardTicketId' in request.GET and request.GET.get('cardTicketId'):
  1232. records = VCardConsumeRecord.objects.filter(cardId = request.GET.get('cardTicketId')).order_by('-dateTimeAdded')
  1233. total = records.count()
  1234. for rcd in records.paginate(pageIndex, pageSize):
  1235. dataList.append(rcd.summary)
  1236. else:
  1237. dealer_ids = MyUser.get_dealer_ids(openId = request.user.openId, productAgentId = request.user.productAgentId)
  1238. if len(dealer_ids) > 0:
  1239. records = ClientConsumeModelProxy.get_data_list(
  1240. ownerId__in = dealer_ids,
  1241. startTime = startTime,
  1242. endTime = endTime,
  1243. openId = request.user.openId,
  1244. isNormal = True,
  1245. hint = [('openId', 1), ('dateTimeAdded', -1)]) # type: CustomQuerySet
  1246. total = records.count()
  1247. for rcd in records.paginate(pageIndex, pageSize):
  1248. dataList.append(rcd.summary)
  1249. else:
  1250. total = 0
  1251. return JsonResponse(
  1252. {
  1253. 'result': 1,
  1254. 'description': '',
  1255. 'payload': {'total': total, 'dataList': dataList}
  1256. })
  1257. @permission_required(ROLE.myuser)
  1258. def getChargeRecordDetail(request):
  1259. # type: (WSGIRequest)->JsonResponse
  1260. """
  1261. 用户充值详细记录
  1262. :param request:
  1263. :return: JsonResponse
  1264. """
  1265. _id = str(request.GET.get('id'))
  1266. ownerId = request.GET.get('ownerId')
  1267. record = ClientRechargeModelProxy.get_one(shard_filter = {'ownerId': ownerId}, id = _id) # type: RechargeRecord
  1268. if not record:
  1269. return JsonResponse({'result': 1, 'description': '', 'payload': {}})
  1270. payload = {
  1271. 'createdTime': record.dateTimeAdded,
  1272. 'orderNo': record.orderNo,
  1273. 'amount': record.my_amount,
  1274. 'groupName': record.groupName,
  1275. 'groupNumber': record.groupNumber,
  1276. 'address': record.address,
  1277. 'logicalCode': record.logicalCode,
  1278. 'devTypeName': record.dev_type_name,
  1279. 'via': record.via,
  1280. 'ownerId': record.ownerId
  1281. }
  1282. payload.update(record.extra_detail_info)
  1283. return JsonResponse(
  1284. {
  1285. 'result': 1,
  1286. 'description': '',
  1287. 'payload': payload
  1288. }
  1289. )
  1290. @permission_required(ROLE.myuser)
  1291. def hybridStartAction(request):
  1292. """
  1293. 此处有红包链接, 可以判断出往下走的流程是拉起支付还是直接启动
  1294. """
  1295. payload = json.loads(request.body)
  1296. urlId = payload.get('urlId')
  1297. dev = Device.get_dev(payload['devNo'])
  1298. if not dev:
  1299. return JsonErrorResponse(description= '设备参数缺失, 请重试')
  1300. if not urlId:
  1301. return JsonErrorResponse(description='传入参数有误, 请重试')
  1302. url = payload.pop('url', None)
  1303. payload = {
  1304. "packageId": payload['packageId'],
  1305. "groupId": dev.groupId,
  1306. "devNo": dev['devNo'],
  1307. "logicalCode": dev['logicalCode'],
  1308. "openId": payload['openId'],
  1309. "attachParas": payload['attachParas']
  1310. }
  1311. serviceCache.set('urlId_{}'.format(urlId), payload)
  1312. return JsonResponse(
  1313. {
  1314. 'result': 1,
  1315. 'description': '',
  1316. 'payload': {'url': url}
  1317. }
  1318. )
  1319. @permission_required(ROLE.myuser)
  1320. def getHybridStartActionInfo(request):
  1321. """
  1322. 返回缓存的参数 直接拉起支付
  1323. """
  1324. payload = json.loads(request.body)
  1325. urlId = payload.get('mktId')
  1326. openId = request.user.openId
  1327. redpack = Redpack.objects.filter(openId=openId, urlId=urlId).first()
  1328. if redpack:
  1329. if redpack.taskStatus != redpack.Result.FINISHED:
  1330. try:
  1331. # 去查询
  1332. ApiRequest = json.loads(redpack.extra.get('ApiRequest', ''))
  1333. clicklink = ApiRequest['Seatbid'][0]['Bid'][0]['Ads'][0]['Trackers']['Imps'][0]
  1334. adid = ApiRequest['Seatbid'][0]['Bid'][0]['Ads'][0]['Id']
  1335. from apps.thirdparties.aliyun import AlipayYunMaV3
  1336. resp = AlipayYunMaV3().query_task_status(
  1337. clicklink=clicklink,
  1338. openId=openId,
  1339. adid=adid,
  1340. )
  1341. if resp.body.success and resp.body.result.success:
  1342. redpack = Redpack.take_effect(openId=openId, urlId=urlId,
  1343. **{'ApiResult': json.dumps(resp.body.result.to_map(),
  1344. ensure_ascii=False)})
  1345. RedpackBuilder._set_alipay_key(openId, redpack.factoryCode, urlId, redpack.money.mongo_amount,
  1346. showType=redpack.showType)
  1347. else:
  1348. pass
  1349. except:
  1350. import traceback
  1351. logger.error(traceback.format_exc())
  1352. else:
  1353. pass
  1354. if redpack.taskStatus == redpack.Result.FINISHED:
  1355. cacheInfo = serviceCache.get('urlId_{}'.format(urlId))
  1356. serviceCache.delete('urlId_{}'.format(urlId))
  1357. if urlId and cacheInfo:
  1358. logicalCode = cacheInfo['logicalCode']
  1359. attachParas = cacheInfo['attachParas']
  1360. device = Device.get_dev_by_l(logicalCode)
  1361. if "isTempPackage" in attachParas and attachParas['isTempPackage'] is True:
  1362. washConfig = device["tempWashConfig"]
  1363. else:
  1364. washConfig = device["washConfig"]
  1365. package = washConfig.get(cacheInfo['packageId'])
  1366. if not package:
  1367. payload = {
  1368. "startAction": False,
  1369. "logicalCode": logicalCode
  1370. }
  1371. else:
  1372. showInfo = {
  1373. 'goodsInfo': {
  1374. 'name': '{}, {}'.format(device.majorDeviceType, device.logicalCode),
  1375. 'port': attachParas.get('chargeIndex'),
  1376. },
  1377. 'packageInfo': {
  1378. 'name': '{}{}'.format(package.get('time', ''), package.get('unit', '')),
  1379. 'coins': package['coins'],
  1380. 'price': package['price']
  1381. },
  1382. 'redPackInfo': {
  1383. 'price': min(redpack.money.amount, package['price']),
  1384. # 'coins': Redpack.pre_deducted_coins(str(redpack.id), package),
  1385. },
  1386. # 'checkoutInfo': {
  1387. # 'price': (RMB(package['price']) - redpack.money).mongo_amount,
  1388. # 'coins': RMB(package['coins'] - Redpack.pre_deducted_coins(str(redpack.id), package)).mongo_amount,
  1389. # },
  1390. }
  1391. attachParas['redpackId'] = str(redpack.id)
  1392. payload = {
  1393. "packageId": cacheInfo['packageId'],
  1394. "groupId": cacheInfo['groupId'],
  1395. "devNo": cacheInfo['devNo'],
  1396. "logicalCode": logicalCode,
  1397. "openId": cacheInfo['openId'],
  1398. "attachParas": attachParas,
  1399. "startAction": True,
  1400. 'showInfo': showInfo
  1401. }
  1402. else:
  1403. payload = {
  1404. "startAction": False,
  1405. "logicalCode": redpack.logicalCode
  1406. }
  1407. return JsonResponse(
  1408. {
  1409. 'result': 1,
  1410. 'description': '',
  1411. 'payload': payload
  1412. }
  1413. )
  1414. else:
  1415. return JsonResponse(
  1416. {
  1417. 'result': 1,
  1418. 'description': '',
  1419. 'payload': {'startAction': False}
  1420. }
  1421. )
  1422. @error_tolerate(nil = JsonErrorResponse(description = u'系统错误'), logger = logger)
  1423. @permission_required(ROLE.myuser)
  1424. def submitFeedback(request):
  1425. # type: (WSGIRequest)->JsonResponse
  1426. """
  1427. 用户提交反馈
  1428. :param request:
  1429. :return:
  1430. """
  1431. openId = request.user.openId
  1432. with memcache_lock(key="{openId}.submitFeedBack".format(openId=openId), value='1', expire=60) as acquired:
  1433. if acquired:
  1434. try:
  1435. payload = feedbackSchema(json.loads(request.body))
  1436. except MultipleInvalid as e:
  1437. logger.exception(e)
  1438. return JsonErrorResponse(description = u"信息不完整,请补充信息或尝试重新扫码")
  1439. dev = Device.get_dev_by_logicalCode(payload['detailInfo']['logicalCode']) # type: DeviceDict
  1440. if not dev:
  1441. return JsonErrorResponse(description = u"当前设备不存在,请重新扫码")
  1442. if not dev.is_registered:
  1443. return JsonErrorResponse(description = u'当前设备已经被运营商解绑定(1001)')
  1444. group = dev.group # type: GroupDict
  1445. if group is None:
  1446. logger.error('[submitFeedback] failed to get group, device\'s logicalCode=%s groupId=%s'
  1447. % (dev['logicalCode'], dev['groupId']))
  1448. return JsonErrorResponse(description = u"当前设备已经被运营商解绑定(1002)")
  1449. feedbackPayload = {
  1450. 'openId': openId,
  1451. 'ownerId': dev.ownerId,
  1452. 'nickname': request.user.nickname,
  1453. 'description': payload['description'],
  1454. 'phone': payload['phone'],
  1455. 'feedType': payload['feedType'],
  1456. 'imgList': payload['imgList'],
  1457. 'isRead': True
  1458. }
  1459. detail_info = payload.pop('detailInfo')
  1460. if payload['feedType'] == 'netpay':
  1461. detail_info = {
  1462. 'orderNo': detail_info['orderNo']
  1463. }
  1464. detail_info.update(dev.identity_info)
  1465. feedbackPayload['detailInfo'] = detail_info
  1466. feedback = FeedBack(**feedbackPayload).save()
  1467. if bool(payload.get('orderNo')) and not feedbackPayload['feedType'] == 'fault':
  1468. order = ConsumeRecord.objects(
  1469. ownerId = dev.ownerId,
  1470. orderNo = feedbackPayload['consumeRecordOrderNo']
  1471. ).first() # type: ConsumeRecord
  1472. if not order:
  1473. return JsonErrorResponse(description = u'您选择的订单不存在,请重新选择。')
  1474. if order.feedbackId:
  1475. return JsonErrorResponse(description = u'您选择的订单已有投诉反馈,请等待设备运营商处理。')
  1476. updated = order.update(feedbackId = ObjectId(feedback.id))
  1477. if not updated:
  1478. logger.info('failed to update ConsumeRecord feedbackId = %s' % (str(feedback.id),))
  1479. dealer = Dealer.objects(id = str(dev['ownerId'])).first()
  1480. if dealer is None:
  1481. logger.error('[submitFeedback] cannot get dealer by id = %s' % (str(dev['ownerId']),))
  1482. return JsonOkResponse()
  1483. agent = Agent.objects(id = str(dealer.agentId)).first()
  1484. if agent is None:
  1485. logger.error('[submitFeedback] cannot get agent by id = %s' % (str(dealer.agentId),))
  1486. return JsonOkResponse()
  1487. if payload['feedType'] == 'fault':
  1488. msgType = u'设备故障'
  1489. else:
  1490. msgType = u'订单投诉'
  1491. msg = u'尊敬的%s用户%s,您的客户刚才给您报告了一条【%s】的信息,请您登录后台,从【用户反馈】查看详情' \
  1492. % (agent.productName, dealer.nickname, msgType)
  1493. task_caller('report_feedback_to_dealer_via_wechat', dealerId = str(dealer.id),
  1494. msg = msg,
  1495. nickname = request.user.nickname,
  1496. feedbackTime = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
  1497. return JsonOkResponse()
  1498. else:
  1499. return JsonErrorResponse(description = u'您已正在提交')
  1500. @error_tolerate(nil = JsonErrorResponse(description = u'获取反馈失败'), logger = logger)
  1501. @permission_required(ROLE.myuser)
  1502. def getFeedbackList(request):
  1503. # type: (WSGIRequest)->JsonResponse
  1504. """
  1505. 用户提交反馈
  1506. :param request:
  1507. :return:
  1508. """
  1509. openId = request.user.openId
  1510. pageIndex = int(request.GET.get('pageIndex', 1))
  1511. pageSize = int(request.GET.get('pageSize', 10))
  1512. dealerIds = MyUser.get_dealer_ids(openId, request.user.productAgentId)
  1513. feedbacks = FeedBack.objects(openId = openId, ownerId__in = dealerIds) \
  1514. .order_by('-createTime') \
  1515. .paginate(pageIndex, pageSize) # type: CustomQuerySet
  1516. total = feedbacks.count()
  1517. items = []
  1518. for item in feedbacks: # type: FeedBack
  1519. items.append(item.summary)
  1520. return JsonResponse(
  1521. {
  1522. 'result': 1,
  1523. 'description': "",
  1524. 'payload': {
  1525. 'total': total,
  1526. 'dataList': items
  1527. }
  1528. }
  1529. )
  1530. @error_tolerate(nil = JsonErrorResponse(description = u'系统错误'), logger = logger)
  1531. @permission_required(ROLE.myuser)
  1532. def getFeedbackDetail(request):
  1533. id_ = request.GET.get('id')
  1534. feedback = FeedBack.objects(id = id_).first() # type: FeedBack
  1535. if not feedback:
  1536. return JsonErrorResponse(description = u'没有找到反馈单,请刷新试试')
  1537. else:
  1538. if not feedback.isRead:
  1539. feedback.isRead = True
  1540. feedback.save()
  1541. return JsonResponse({'result': 1, 'description': '', 'payload': feedback.detail})
  1542. @error_tolerate(nil = JsonErrorResponse(description = u'系统错误'), logger = logger)
  1543. @permission_required(ROLE.myuser)
  1544. def getFeedbackConfigs(request):
  1545. # type: (WSGIRequest)->JsonResponse
  1546. """
  1547. :param request:
  1548. :return:
  1549. """
  1550. logicalCode = request.GET.get('logicalCode')
  1551. # if not logicalCode:
  1552. # return JsonErrorResponse(description = u'找不到设备编号')
  1553. dev = Device.get_dev_by_l(logicalCode) or dict()
  1554. #: 暂时只是显示充电桩的端口
  1555. devTypeName = dev.get("devType", dict()).get("name", "")
  1556. if re.match(ur"充电桩", devTypeName):
  1557. payload = {"port": [str(_) for _ in range(1, 21)]}
  1558. else:
  1559. payload = {}
  1560. return JsonResponse({'result': 1, 'description': '', 'payload': payload})
  1561. @error_tolerate(nil = JsonErrorResponse(description = u'系统错误'), logger = logger)
  1562. @permission_required(ROLE.myuser)
  1563. def getConsumeRecordsForFeedback(request):
  1564. # type: (WSGIRequest)->JsonResponse
  1565. """
  1566. :param request:
  1567. :return:
  1568. """
  1569. pageIndex = int(request.GET.get('pageIndex', 1))
  1570. pageSize = int(request.GET.get('pageSize', 10))
  1571. skip = (pageIndex - 1) * pageSize
  1572. logicalCode = request.GET.get('logicalCode', None)
  1573. if logicalCode:
  1574. device = Device.get_dev_by_logicalCode(logicalCode)
  1575. if not device:
  1576. return JsonErrorResponse(description = u'设备不存在,请重新扫码')
  1577. ownerIds = [device.ownerId]
  1578. else:
  1579. ownerIds = MyUser.get_dealer_ids(request.user.openId, request.user.productAgentId)
  1580. records = ConsumeRecord.objects(
  1581. ownerId__in = ownerIds,
  1582. openId = request.user.openId,
  1583. dateTimeAdded__gte = (datetime.datetime.now() - datetime.timedelta(days = 30)),
  1584. feedbackId__exists = 0).order_by("-dateTimeAdded") # type: CustomQuerySet
  1585. dataList = []
  1586. for record in records.skip(skip).limit(pageSize): # type: ConsumeRecord
  1587. dataList.append(record.info_for_feedback)
  1588. return JsonResponse(
  1589. {
  1590. 'result': 1,
  1591. 'description': '',
  1592. 'payload': {'total': records.count(), 'dataList': dataList}
  1593. })
  1594. def getNearbyDevicesFromDB(lng, lat, pageIndex, pageSize, maxDistance, agentId, devTypeName, groupId = None):
  1595. def hav(theta):
  1596. s = sin(theta / 2)
  1597. return s * s
  1598. def get_distance_hav(lat0, lng0, lat1, lng1):
  1599. if lat1 == 360 or lng1 == 360:
  1600. return -1
  1601. EARTH_RADIUS = 6371000
  1602. lat0 = radians(lat0)
  1603. lat1 = radians(lat1)
  1604. lng0 = radians(lng0)
  1605. lng1 = radians(lng1)
  1606. dlng = fabs(lng0 - lng1)
  1607. dlat = fabs(lat0 - lat1)
  1608. h = hav(dlat) + cos(lat0) * cos(lat1) * hav(dlng)
  1609. return int(2 * EARTH_RADIUS * asin(sqrt(h)))
  1610. def formatDeviceInfo(dev, devTypeName):
  1611. # type: (DeviceDict, basestring)->Optional[Dict]
  1612. logger.debug('try to format device<l={}, devNo={}> info.'.format(dev.logicalCode, dev.devNo))
  1613. distance = get_distance_hav(lat, lng, float(dev['lat']), float(dev['lng']))
  1614. group = Group.get_group(dev['groupId'])
  1615. if group is None:
  1616. return None
  1617. package = [
  1618. {
  1619. 'name': rule.get('name', ''),
  1620. 'coins': rule['coins'],
  1621. 'price': rule.get('price', rule['coins']),
  1622. 'time': rule.get('time', 20),
  1623. 'unit': rule.get('unit', u'分钟')
  1624. } for packageId, rule in dev['washConfig'].items()]
  1625. return {
  1626. 'devNo': dev.devNo,
  1627. 'type': devTypeName,
  1628. 'logicalCode': dev.logicalCode,
  1629. 'groupName': group['groupName'],
  1630. 'groupNumber': dev['groupNumber'],
  1631. 'groupId': dev.groupId,
  1632. 'address': group['address'],
  1633. 'online': dev.online,
  1634. 'status': dev.status,
  1635. 'signal': dev.signal,
  1636. 'remarks': dev['remarks'],
  1637. 'distance': distance,
  1638. 'lng': float(dev.lng),
  1639. 'lat': float(dev.lat),
  1640. 'often': False,
  1641. 'beingUsed': False,
  1642. 'package': package,
  1643. 'devTypeCode': dev.devType['code']
  1644. }
  1645. if not agentId:
  1646. logger.error('agent is null.')
  1647. return {
  1648. 'total': 0,
  1649. 'items': []
  1650. }
  1651. dealers = Dealer.get_dealers(agentId)
  1652. if not dealers:
  1653. return {
  1654. 'total': 0,
  1655. 'items': []
  1656. }
  1657. if groupId:
  1658. devices = Device.get_collection().find({'groupId': groupId})
  1659. else:
  1660. if devTypeName:
  1661. devices = Device.get_collection().find(
  1662. {
  1663. 'ownerId': {'$in': dealers},
  1664. '$where': 'this.devType != null && this.devType.name == "%s"' % devTypeName,
  1665. 'isFault': False,
  1666. 'location': {
  1667. '$near': {'$geometry': {'type': 'Point', 'coordinates': [lng, lat]},
  1668. '$maxDistance': maxDistance}}})
  1669. else:
  1670. devices = Device.get_collection().find(
  1671. {
  1672. 'ownerId': {'$in': dealers},
  1673. 'isFault': False,
  1674. 'location': {
  1675. '$near': {'$geometry': {'type': 'Point', 'coordinates': [lng, lat]},
  1676. '$maxDistance': maxDistance}}})
  1677. items = []
  1678. for dev in devices:
  1679. dev = DeviceDict(dev) # type: DeviceDict
  1680. if dev is None or not dev.lbs:
  1681. continue
  1682. try:
  1683. devInfo = formatDeviceInfo(dev, dev.devType.get('name', '')) # type: Dict
  1684. except Exception as e:
  1685. logger.exception(e)
  1686. continue
  1687. if devInfo is None:
  1688. continue
  1689. items.append(devInfo)
  1690. return_items = items[(pageIndex - 1) * pageSize:pageIndex * pageSize]
  1691. dev_ctrl_map = Device.get_many_dev_control_cache([item['devNo'] for item in return_items])
  1692. for item in return_items:
  1693. # 换电柜的端口显示可用电池数量
  1694. if item['devTypeCode'] in [Const.DEVICE_TYPE_CODE_CHARGING_AQKJ, Const.DEVICE_TYPE_CODE_CHARGING_AQKJ_NEW]:
  1695. dev_ctrl_info = dev_ctrl_map.get(device_control_cache_key(item['devNo']), {})
  1696. item["canUseBattery"] = dev_ctrl_info.get("canUseBattery", 0)
  1697. elif Const.DEVICE_TYPE_CODE_CHARGING_KYXN <= item['devTypeCode'] < Const.DEVICE_TYPE_CODE_WASHER_BASE:
  1698. dev_ctrl_info = dev_ctrl_map.get(device_control_cache_key(item['devNo']), {})
  1699. item['allPorts'] = dev_ctrl_info.get('allPorts', 10)
  1700. item['usedPorts'] = dev_ctrl_info.get('usedPorts', 0)
  1701. item['usePorts'] = dev_ctrl_info.get('usePorts', 10)
  1702. if 'power' in dev_ctrl_info:
  1703. item['power'] = dev_ctrl_info['power']
  1704. payload = {
  1705. 'total': len(items),
  1706. 'items': return_items
  1707. }
  1708. return payload
  1709. @permission_required(ROLE.myuser)
  1710. def getNearbyGroups(request):
  1711. # type: (WSGIRequest)->JsonResponse
  1712. try:
  1713. lng = float(request.GET.get('lng'))
  1714. lat = float(request.GET.get('lat'))
  1715. maxDistance = int(request.GET.get('distance', 3000))
  1716. logger.debug('now location. lat = %s; lng = %s' % (lat, lng))
  1717. if maxDistance > Const.NEAR_BY_MAX_DISTANCE:
  1718. maxDistance = Const.NEAR_BY_MAX_DISTANCE
  1719. if lng == 360 or lat == 360 or isnan(lng) or isnan(lat):
  1720. return JsonResponse({'result': 0, 'description': u'定位失败,请打开位置权限,刷新后重试'})
  1721. payload = getNearbyDevicesFromDB(lng, lat, 1, 1000, maxDistance, request.user.agentId,
  1722. request.GET.get('type', None))
  1723. groupDict = {}
  1724. for dev in payload['items']:
  1725. if groupDict.has_key(dev['groupId']):
  1726. groupDict[dev['groupId']]['allDevices'] += 1
  1727. if dev['status'] == Const.DEV_WORK_STATUS_IDLE:
  1728. groupDict[dev['groupId']]['idleDevices'] += 1
  1729. else:
  1730. newValue = {
  1731. 'distance': dev['distance'],
  1732. 'lng': float(dev['lng']),
  1733. 'lat': float(dev['lat']),
  1734. 'address': dev['address'],
  1735. 'groupName': dev['groupName'],
  1736. 'groupId': dev['groupId'],
  1737. 'allDevices': 1,
  1738. 'idleDevices': 1 if dev['status'] == Const.DEV_WORK_STATUS_IDLE else 0
  1739. }
  1740. groupDict[dev['groupId']] = newValue
  1741. payload = {'total': len(groupDict.values()), 'items': groupDict.values()}
  1742. return JsonResponse({'result': 1, 'description': '', 'payload': payload})
  1743. except Exception as e:
  1744. logger.exception(e)
  1745. return JsonResponse({'result': 0, 'description': u'获取附近设备失败'})
  1746. @permission_required(ROLE.myuser)
  1747. def getNearbyDevices(request):
  1748. # type: (WSGIRequest)->JsonResponse
  1749. try:
  1750. groupId = request.GET.get('groupId', None)
  1751. lng = float(request.GET.get('lng'))
  1752. lat = float(request.GET.get('lat'))
  1753. maxDistance = int(request.GET.get('distance', 3000))
  1754. logger.debug('now location. lat = %s; lng = %s' % (lat, lng))
  1755. if maxDistance > Const.NEAR_BY_MAX_DISTANCE:
  1756. maxDistance = Const.NEAR_BY_MAX_DISTANCE
  1757. if lng == 360 or lat == 360 or isnan(lng) or isnan(lat):
  1758. return JsonResponse({'result': 0, 'description': u'定位失败,请打开位置权限,刷新后重试'})
  1759. pageIndex = int(request.GET.get('pageIndex', 0))
  1760. pageSize = int(request.GET.get('pageSize', 10))
  1761. payload = getNearbyDevicesFromDB(lng, lat, pageIndex, pageSize, maxDistance,
  1762. getattr(request.user, 'productAgentId', ''),
  1763. request.GET.get('type', None), groupId)
  1764. return JsonResponse({'result': 1, 'description': '', 'payload': payload})
  1765. except Exception as e:
  1766. logger.exception(e)
  1767. return JsonResponse({'result': 0, 'description': u'获取附近设备失败'})
  1768. @permission_required(ROLE.manager)
  1769. def getEndUserDetailList(request):
  1770. # type: (WSGIRequest)->JsonResponse
  1771. """
  1772. :param request:
  1773. :return:
  1774. """
  1775. mid = str(request.user.id)
  1776. pageIndex = int(request.GET.get('pageIndex', 1))
  1777. pageSize = int(request.GET.get('pageSize', 10))
  1778. searchKey = request.GET.get('searchKey', None)
  1779. agentIds = [str(agent['_id']) for agent in Agent.get_collection().find({'managerId': mid}, {'_id': True})]
  1780. dealerIds = [str(dealer['_id']) for dealer in
  1781. Dealer.get_collection().find({'agentId': {'$in': agentIds}}, {'_id': True})]
  1782. groupIds = [str(group['_id']) for group in
  1783. Group.get_collection().find({'ownerId': {'$in': dealerIds}}, {'_id': True})]
  1784. skip = (pageIndex - 1) * pageSize
  1785. dataList = []
  1786. users = MyUser.search(searchKey).filter(groupId__in = groupIds)
  1787. for u in users.skip(skip).limit(pageSize):
  1788. item = {
  1789. 'id': str(u.id),
  1790. 'nickname': u.nickname,
  1791. 'openId': u.openId,
  1792. 'sex': u.sex,
  1793. 'country': u.country,
  1794. 'province': u.province,
  1795. 'city': u.city,
  1796. 'balance': u.balance,
  1797. 'groupName': '',
  1798. 'gateway': u.gateway
  1799. }
  1800. group = Group.get_group(u.groupId)
  1801. if group:
  1802. item.update({'groupName': group.get('groupName')})
  1803. dataList.append(item)
  1804. total = users.count()
  1805. return JsonResponse({
  1806. 'result': 1,
  1807. 'description': '',
  1808. 'payload': {
  1809. 'total': total,
  1810. 'dataList': dataList
  1811. }
  1812. })
  1813. @error_tolerate(nil = JsonErrorResponse(description = u'获取消费记录失败'), logger = logger)
  1814. @permission_required(ROLE.manager)
  1815. def getEndUserConsumeRecords(request):
  1816. # type: (WSGIRequest)->JsonResponse
  1817. """
  1818. :param request:
  1819. :return:
  1820. """
  1821. pageIndex = int(request.GET.get('pageIndex', 1))
  1822. pageSize = int(request.GET.get('pageSize', 10))
  1823. userId = request.GET.get('id', None)
  1824. if not userId:
  1825. return JsonErrorResponse(description = u'用户id为空')
  1826. else:
  1827. startTime = request.GET.get('startTime', Const.QUERY_START_DATE)
  1828. endTime = request.GET.get('endTime', datetime.datetime.now().strftime('%Y-%m-%d'))
  1829. user = MyUser.objects(id = str(userId)).get()
  1830. group = Group.get_group(user.groupId)
  1831. cursor = ClientConsumeModelProxy.get_data_list(
  1832. startTime = startTime,
  1833. endTime = endTime,
  1834. ownerId = group['ownerId'],
  1835. openId = user.openId,
  1836. groupId = user.groupId) # type: QuerySetProxy
  1837. total = cursor.count()
  1838. records = [
  1839. {
  1840. "orderNo": r.orderNo,
  1841. "time": r.time,
  1842. "coins": r.coin,
  1843. "devNo": r.devNo,
  1844. "devType": r.dev_type_name,
  1845. "groupName": r.groupName
  1846. }
  1847. for r in cursor.paginate(pageIndex, pageSize)
  1848. ]
  1849. return JsonResponse({'result': 1, 'description': '', 'payload': {'total': total, 'dataList': records}})
  1850. @error_tolerate(nil = JsonErrorResponse(description = u'获取充值记录失败'), logger = logger)
  1851. @permission_required(ROLE.manager)
  1852. def getEndUserRechargeRecords(request):
  1853. # type: (WSGIRequest)->JsonResponse
  1854. """
  1855. :param request:
  1856. :return:
  1857. """
  1858. pageIndex = int(request.GET.get('pageIndex', 1))
  1859. pageSize = int(request.GET.get('pageSize', 10))
  1860. userId = request.GET.get('id', None)
  1861. if not userId:
  1862. return JsonErrorResponse(description = u'用户id为空')
  1863. else:
  1864. startTime = request.GET.get('startTime', Const.QUERY_START_DATE)
  1865. endTime = request.GET.get('endTime', datetime.datetime.now().strftime('%Y-%m-%d'))
  1866. user = MyUser.objects(id = str(userId)).get()
  1867. group = Group.get_group(user.groupId)
  1868. cursor = ClientRechargeModelProxy.get_data_list(startTime = startTime,
  1869. endTime = endTime,
  1870. ownerId = group['ownerId'],
  1871. openId = user.openId,
  1872. groupId = user.groupId,
  1873. hint = [('openId', 1)]) # type: QuerySetProxy
  1874. total = cursor.count()
  1875. records = [
  1876. {
  1877. "orderNo": r.orderNo,
  1878. "time": r.to_js_timestamp(r.dateTimeAdded),
  1879. "money": r.money,
  1880. "coins": r.coins,
  1881. "devNo": r.devNo,
  1882. "devType": r.dev_type_name,
  1883. "groupName": r.groupName,
  1884. "gateway": r.gateway
  1885. } for r in cursor.paginate(pageIndex, pageSize)]
  1886. return JsonResponse({'result': 1, 'description': '', 'payload': {'total': total, 'dataList': records}})
  1887. def wxconfig(request):
  1888. url = request.GET.get('href')
  1889. if not url:
  1890. return JsonResponse({'result': 0, 'description': u'参数错误', 'payload': {}})
  1891. current_user = request.user # type: MyUser
  1892. wxconfig = get_wx_config(current_user, url)
  1893. return JsonOkResponse(payload = {'wxconfig': wxconfig})
  1894. # 用于前台界面时间计时用
  1895. @error_tolerate(nil = JsonErrorResponse(description = u'系统错误'), logger = logger)
  1896. @permission_required(ROLE.myuser)
  1897. def countDown(request):
  1898. # type: (WSGIRequest)->JsonResponse
  1899. openId = str(request.user.openId)
  1900. devNo = str(request.GET.get('devNo', ''))
  1901. portStr = request.GET.get('chargeIndex', None)
  1902. if portStr is not None:
  1903. port = int(portStr)
  1904. else:
  1905. port = None
  1906. dev = Device.get_dev(devNo)
  1907. logicalCode = dev['logicalCode']
  1908. group = Group.get_group(dev['groupId'])
  1909. devType = dev.get('devType')
  1910. dealer = Dealer.objects.get(id = dev['ownerId'])
  1911. agent = Agent.objects.get(id = dealer.agentId)
  1912. # 判断是否是摩丫丫的设备 判断是否是烘干机设备
  1913. if (agent.features != [] and 'moyaya666' in agent.features) or (
  1914. dealer.features != [] and 'dryer' in dealer.features):
  1915. last_time_cache = serviceCache.get(user_last_time_use_ended_cache(openId, logicalCode), '')
  1916. if last_time_cache == '':
  1917. serviceCache.set(user_last_time_use_ended_cache(openId, logicalCode), datetime.datetime.now(), 3600)
  1918. elif last_time_cache != '':
  1919. if datetime.datetime.now() > last_time_cache + datetime.timedelta(hours = 1):
  1920. serviceCache.set(user_last_time_use_ended_cache(openId, logicalCode), datetime.datetime.now(), 3600)
  1921. ctrInfo = Device.get_dev_control_cache(devNo)
  1922. if ctrInfo:
  1923. lastOpenId = ctrInfo.get('openId', '')
  1924. else:
  1925. lastOpenId = ''
  1926. box = ActionDeviceBuilder.create_action_device(dev)
  1927. try:
  1928. response = box.count_down(request, dev, agent, group, devType, lastOpenId, port)
  1929. if response is None:
  1930. return JsonErrorResponse(description = u'系统不支持此操作哦')
  1931. return response
  1932. except ServiceException as e:
  1933. logger.error('get count_down error=%s' % e.result['description'].encode('utf-8'))
  1934. return JsonErrorResponse(description = e.result['description'])
  1935. except Exception, e:
  1936. logger.error('device(%s) get count_down error=%s' % (devNo, e))
  1937. return JsonErrorResponse(description = u'系统异常,请重新刷新页面')
  1938. # 只要有回调过来,说明一定是登录成功了,就直接送金币,然后跳转到控制页面即可。暂时不考虑authCode的鉴定以防止伪造URL。
  1939. @error_tolerate(nil = ErrorResponseRedirect(error = cn(u'系统开小差了哦,真是抱歉呀,请您刷新页面试试哦')))
  1940. @permission_required(ROLE.myuser)
  1941. def huaweiAccess(request):
  1942. # type: (WSGIRequest)->HttpResponseRedirect
  1943. openId = request.user.openId
  1944. devNo = request.COOKIES.get('devNo', None)
  1945. groupId = request.COOKIES.get('groupId', None)
  1946. if openId is None or devNo is None or groupId is None:
  1947. return ErrorResponseRedirect(error = cn(u'系统开小差了哦,真是抱歉呀,请您重新扫码试试哦'))
  1948. dev = Device.get_dev(devNo)
  1949. ads = AdRecord.objects.filter(openId = openId, adId = 0)
  1950. if ads.count() > 0:
  1951. return NetDeviceResponseRedirect(l = dev.logicalCode)
  1952. newRcd = AdRecord(converted = True, adId = 0, openId = openId, groupId = groupId, devNo = devNo)
  1953. newRcd.save()
  1954. user = MyUser.objects.get(openId = openId, groupId = groupId)
  1955. user.balance += 1
  1956. user.save()
  1957. return NetDeviceResponseRedirect(l = dev.logicalCode)
  1958. @error_tolerate(nil = JsonErrorResponse(description = u'系统错误'), logger = logger)
  1959. def getCardStatus(request):
  1960. # type: (WSGIRequest)->JsonResponse
  1961. lc = request.GET.get('logicalCode')
  1962. devNo = Device.get_devNo_by_logicalCode(lc)
  1963. cardInfo = Card.get_dev_cur_card(devNo)
  1964. if cardInfo is None:
  1965. return JsonResponse(
  1966. {
  1967. "result": 0,
  1968. "description": u'刷卡区没有检测到卡,请您先把卡放到读卡区,这样才能开始充值哦',
  1969. "para": None
  1970. }
  1971. )
  1972. return JsonResponse(
  1973. {
  1974. "result": 1,
  1975. "description": None,
  1976. "para": {
  1977. "ready": True,
  1978. "cardId": cardInfo['cardNo'],
  1979. "money": cardInfo["money"]
  1980. }
  1981. }
  1982. )
  1983. @permission_required(ROLE.myuser)
  1984. def pollBtInfo(request):
  1985. # type: (WSGIRequest)->JsonResponse
  1986. payload = json.loads(request.body)
  1987. device = Device.get_dev_by_logicalCode(payload.get('logicalCode'))
  1988. if not device:
  1989. return JsonResponse({'result': 0, 'description': u'设备不存在', 'payload': {}})
  1990. code = Const.BT_DEVICE_TYPE_CODE_MAP[int(payload.get('code'))]
  1991. actionBox = ActionBtDeviceBuilder.create(code, device)
  1992. major = int(payload.get('major'))
  1993. minor = int(payload.get('minor'))
  1994. notify_payload = payload.get('payload', None)
  1995. if not notify_payload:
  1996. notify_payload = payload.get('advertisData', None)
  1997. if notify_payload:
  1998. result, description = actionBox.poll_notify(notify_payload, **{'major': major, 'minor': minor})
  1999. return JsonResponse({'result': result, 'description': description, 'payload': {}})
  2000. else:
  2001. return JsonResponse({'result': 1, 'description': 'empty', 'payload': {}})
  2002. @error_tolerate(nil=JsonErrorResponse(description=u'显示用户信息错误'), logger=logger)
  2003. @permission_required(ROLE.myuser)
  2004. @request_limit_by_user(operation='userInfo', limit=50, logger=logger)
  2005. def userInfo(request):
  2006. # type: (WSGIRequest)->JsonResponse
  2007. logger.info('receive userInfo')
  2008. user = request.user # type: MyUser
  2009. agentId = user.agentId
  2010. payload = {
  2011. 'nickname': user.nickname,
  2012. 'balance': user.total_balance,
  2013. 'agentId': agentId,
  2014. 'domain': settings.MY_DOMAIN,
  2015. 'avatarUrl': request.user.avatar if request.user.avatar else settings.DEFAULT_AVATAR_URL,
  2016. 'noVirtualCard': False,
  2017. 'noRechargeCard': False,
  2018. 'noRecharge': False,
  2019. 'userId': ''
  2020. }
  2021. agent = Agent.objects(id = agentId).first() # type: Optional[Agent]
  2022. if agent:
  2023. payload['agentFeatures'] = agent.features
  2024. if 'hideRechargeCardForUser' in agent.features:
  2025. payload.update({'noRechargeCard': True})
  2026. # if 'ledgerAfterFinished' in agent.features:
  2027. # payload.update({
  2028. # 'noVirtualCard': True,
  2029. # 'noRechargeCard': True,
  2030. # 'noRecharge': True
  2031. # })
  2032. # 校验是否要绑定用户的手机号码
  2033. if 'telVerify' in agent.features:
  2034. needTelVerify = check_user_tel(user)
  2035. payload.update({
  2036. "needTelVerify": needTelVerify
  2037. })
  2038. # 检查是否支持一卡多用
  2039. if 'card_multi_use' in agent.features:
  2040. payload.update({'card_multi_use': True})
  2041. user_id = user.user_id
  2042. if user_id:
  2043. payload.update({'userId': user_id})
  2044. return JsonResponse({'result': 1, 'description': '', 'payload': payload})
  2045. @error_tolerate(nil = JsonErrorResponse(description = u'获取组失败'), logger = logger)
  2046. @permission_required(ROLE.myuser)
  2047. def getRecentlyGroup(request):
  2048. # type: (WSGIRequest)->JsonResponse
  2049. my_product_agent_id = request.user.productAgentId
  2050. # 是否是查询卡卷
  2051. hasCoupon = request.GET.get('hasCoupon', False)
  2052. openId = request.user.openId
  2053. rcds = ConsumeRecord.objects.filter(openId = openId, isNormal = True).order_by('-dateTimeAdded')
  2054. devNoList = list(set([rcd.devNo for rcd in rcds[0:100]]))
  2055. dataList = []
  2056. groupIdList = []
  2057. dealerIdList = []
  2058. map_dealer_product = {}
  2059. for devNo in devNoList:
  2060. dev = Device.get_dev(devNo)
  2061. if (dev is None) or (not dev.has_key('groupId')):
  2062. continue
  2063. group = Group.get_group(dev['groupId'])
  2064. if not group:
  2065. continue
  2066. dealer_id = str(dev['ownerId'])
  2067. if not dealer_id:
  2068. logger.error('dealer is null. id = %s' % dealer_id)
  2069. continue
  2070. try:
  2071. dealer = Dealer.objects(id = dealer_id).first()
  2072. if not dealer:
  2073. logger.error('dealer is null. id = %s' % dealer_id)
  2074. continue
  2075. except Exception as e:
  2076. logger.error('dealerId = {}; exception = {}'.format(dealer_id, str(e)))
  2077. if dealer_id not in map_dealer_product:
  2078. try:
  2079. product_agent = get_user_manager_agent(dealer) # type:Agent
  2080. except Exception as e:
  2081. logger.exception(e)
  2082. product_agent = None
  2083. if not product_agent:
  2084. logger.error('get product agent failure. devNo = {}; dealer id = {}'.format(dev['devNo'], dealer_id))
  2085. continue
  2086. map_dealer_product[dealer_id] = str(product_agent.id)
  2087. if map_dealer_product[dealer_id] != my_product_agent_id:
  2088. logger.debug('{} is not equal agent({})'.format(repr(dev), my_product_agent_id))
  2089. continue
  2090. if dev['groupId'] not in groupIdList:
  2091. if (not group.has_key('address')) or (not group.has_key('groupName')):
  2092. continue
  2093. dataList.append({'address': group['address'],
  2094. 'groupName': group['groupName'],
  2095. 'groupId': dev['groupId'],
  2096. 'devType': dev.get('devType', {}).get('name', ''),
  2097. 'logicalCode': dev['logicalCode'],
  2098. 'ownerId': dev['ownerId']}
  2099. )
  2100. groupIdList.append(dev['groupId'])
  2101. dealerIdList.append(dev['ownerId'])
  2102. if not hasCoupon:
  2103. return JsonResponse({"result": 1, "description": "", "payload": {"total": len(dataList), "dataList": dataList}})
  2104. # 查询下地址下的已经发布的虚拟卡
  2105. dealerIdList = list(set(dealerIdList))
  2106. vCards = VirtualCard.objects.filter(ownerId__in = dealerIdList, status = 1)
  2107. dataList1 = []
  2108. for data in dataList:
  2109. match = False
  2110. for card in vCards:
  2111. if data['ownerId'] == card.ownerId and ('*' in card.groupIds or data['groupId'] in card.groupIds):
  2112. match = True
  2113. break
  2114. if match:
  2115. dataList1.append(data)
  2116. return JsonResponse({"result": 1, "description": "", "payload": {"total": len(dataList1), "dataList": dataList1}})
  2117. @error_tolerate(nil = JsonErrorResponse(description = u'获取卡列表失败'), logger = logger)
  2118. @permission_required(ROLE.myuser)
  2119. def getCardList(request):
  2120. # type: (WSGIRequest)->JsonResponse
  2121. """
  2122. :param request:
  2123. :return:
  2124. """
  2125. pageIndex = int(request.GET.get('pageIndex', 1))
  2126. pageSize = int(request.GET.get('pageSize', 10))
  2127. searchKey = request.GET.get('searchKey', None)
  2128. openId = request.user.openId
  2129. agentId = request.user.agentId # zjl user.agentId -> user.productAgentId
  2130. agent = Agent.objects.get(id = agentId)
  2131. manager = Manager.objects(id = agent.managerId).get() # zjl delete
  2132. agent_id_list = [str(item.id) for item in Agent.objects(managerId = str(manager.id))] # zjl delete
  2133. hideMenu = True if 'hideCardMenu' in agent.features else False
  2134. skip = (pageIndex - 1) * pageSize
  2135. cards = Card.objects.filter(openId = openId, # zjl delete
  2136. agentId__in = agent_id_list).search(searchKey) # zjl delete
  2137. # cards = Card.objects.filter(openId=openId, # zjl new
  2138. # agentId=agentId).search(searchKey) # zjl new
  2139. dataList = []
  2140. for card in cards.skip(skip).limit(pageSize):
  2141. hide = ['orderRecord', 'rechargeRecord', 'backRecord', 'frozen'] if (card.cardType == 'IC' and hideMenu) else []
  2142. if card.devNo:
  2143. dev = Device.get_dev(card.devNo) or dict()
  2144. devType = dev.get('devType', {})
  2145. if devType.has_key('id'):
  2146. try:
  2147. devType = DeviceType.objects.get(id = devType['id'])
  2148. if not devType.supportIcCardcharge:
  2149. hide.append('cardCharge')
  2150. except Exception, e:
  2151. pass
  2152. # 分以下三种情况处理
  2153. # 1 有groupId, 但是没有dealerId, 这个查数据目前没有。 这个情况下dealerId设置为group对应的, 如果没有dealer, 全部清空
  2154. # 2 有dealerId, 没有groupId, 这种情况下, 直接取dealer的第一个groupId, 没有全部取空
  2155. # 3 两个都没有的情况下, 直接取设备对应的group和dealerId
  2156. if not card.groupId:
  2157. if card.dealerId:
  2158. group = Group.get_default_group(card.dealerId) # type: GroupDict
  2159. if group:
  2160. card.groupId = group.groupId
  2161. else:
  2162. card.groupId = ''
  2163. card.dealerId = ''
  2164. card.save()
  2165. else:
  2166. # 不处理. 这个用户自己去绑定
  2167. pass
  2168. else:
  2169. if not card.dealerId:
  2170. group = Group.get_group(card.groupId) # type: GroupDict
  2171. if not group:
  2172. card.groupId = ''
  2173. card.dealerId = ''
  2174. else:
  2175. card.dealerId = group.ownerId
  2176. card.save()
  2177. group = Group.get_group(card.groupId) # type: GroupDict
  2178. dataList.append(
  2179. {
  2180. 'cardId': str(card.id),
  2181. 'cardNo': card.cardNo,
  2182. 'cardType': card.cardType,
  2183. 'cardName': card.cardName,
  2184. 'phone': card.phone,
  2185. 'groupId': card.groupId,
  2186. 'groupName': group.groupName if group else '',
  2187. 'dealerId': card.dealerId,
  2188. 'balance': card.balance,
  2189. 'isHaveBalance': card.isHaveBalance,
  2190. 'remarks': card.remarks,
  2191. 'status': card.status,
  2192. 'frozen': False if card.frozen is None else card.frozen,
  2193. 'hide': hide,
  2194. 'boundVirtualCardId': card.boundVirtualCardId
  2195. }
  2196. )
  2197. total = cards.count()
  2198. return JsonResponse(
  2199. {
  2200. 'result': 1,
  2201. 'description': '',
  2202. 'payload':
  2203. {
  2204. 'total': total, "dataList": dataList
  2205. }
  2206. }
  2207. )
  2208. @error_tolerate(nil = JsonOkResponse(description = u"获取卡信息失败"), logger = logger)
  2209. @permission_required(ROLE.myuser)
  2210. def getCard(request):
  2211. """
  2212. 获取单一的卡信息
  2213. :param request:
  2214. :return:
  2215. """
  2216. cardId = request.GET.get("cardId", "")
  2217. try:
  2218. card = Card.objects.get(id = cardId)
  2219. except DoesNotExist:
  2220. return JsonErrorResponse(description = u"获取卡信息失败,请刷新页面试试")
  2221. agentId = request.user.agentId
  2222. agent = Agent.objects.get(id = agentId)
  2223. hideMenu = True if 'hideCardMenu' in agent.features else False
  2224. hide = ['orderRecord', 'rechargeRecord', 'backRecord', 'frozen'] if (card.cardType == 'IC' and hideMenu) else []
  2225. if card.devNo:
  2226. dev = Device.get_dev(card.devNo) or dict()
  2227. devType = dev.get('devType', {})
  2228. if devType.has_key('id'):
  2229. try:
  2230. devType = DeviceType.objects.get(id = devType['id'])
  2231. if not devType.supportIcCardcharge:
  2232. hide.append('cardCharge')
  2233. except Exception as e:
  2234. logger.exception(e)
  2235. group = Group.get_group(card.groupId)
  2236. data = {
  2237. 'cardId': str(card.id),
  2238. 'cardNo': card.cardNo,
  2239. 'cardType': card.cardType,
  2240. 'cardName': card.cardName,
  2241. 'phone': card.phone,
  2242. 'groupId': card.groupId,
  2243. 'groupName': group.groupName if group else '',
  2244. 'dealerId': card.dealerId,
  2245. 'balance': card.balance,
  2246. 'isHaveBalance': card.isHaveBalance,
  2247. 'remarks': card.remarks,
  2248. 'status': card.status,
  2249. 'frozen': False if card.frozen is None else card.frozen,
  2250. 'hide': hide,
  2251. }
  2252. return JsonOkResponse(payload = data)
  2253. @error_tolerate(nil = JsonErrorResponse(description = u"查询卡信息失败"), logger = logger)
  2254. @permission_required(ROLE.myuser)
  2255. def queryCard(request):
  2256. """
  2257. 根据前台提供的cardNo 以及 groupId 返回该卡的所有信息
  2258. :param request:
  2259. :return:
  2260. """
  2261. # 获取参数 参数校验
  2262. cardNo = request.GET.get("cardNo")
  2263. groupId = request.GET.get("groupId")
  2264. if not all([cardNo, groupId]):
  2265. return JsonErrorResponse(description = u"参数不全,请输入卡号获取扫描设备获取绑定地址")
  2266. group = Group.get_group(groupId) # type: GroupDict
  2267. if not group:
  2268. return JsonErrorResponse(description = u"开卡地址不存在,请重新扫描设备获取绑定地址或联系发卡经销商(1001)")
  2269. dealer = Dealer.objects(id = str(group.ownerId)).first() # type: Dealer
  2270. if not dealer:
  2271. return JsonErrorResponse(description = u"开卡地址不存在,请重新扫描设备获取绑定地址或联系发卡经销商(1002)")
  2272. agent = Agent.objects(id = str(dealer.agentId)).first()
  2273. if not agent:
  2274. return JsonErrorResponse(description = u"代理商不存在,请刷新页面后重试(1001)")
  2275. productAgent = get_user_manager_agent(agent)
  2276. if str(productAgent.id) != request.user.productAgentId:
  2277. return JsonErrorResponse(description = u"不是该平台下的地址,请换个设备编号扫码试试(1001)")
  2278. # 鉴别卡相应信息
  2279. try:
  2280. card = Card.objects.get(cardNo=cardNo, agentId=str(agent.id))
  2281. except DoesNotExist:
  2282. # 没有找到卡的情况下 如果代理商规定了经销商必须要先录入卡
  2283. dealerBindCard = True if "dealerBindCard" in agent.features else False
  2284. if dealerBindCard:
  2285. return JsonErrorResponse(description=u"无效的卡号,该卡号未被录入,请联系发卡方")
  2286. return JsonResponse(
  2287. {
  2288. "result": 1,
  2289. "description": u"",
  2290. "payload": {
  2291. "cardNo": cardNo,
  2292. "groupId": group.groupId,
  2293. "groupName": group.groupName,
  2294. }
  2295. }
  2296. )
  2297. # 卡已经被被别人绑定了
  2298. if card.openId and card.openId != request.user.openId and card.openId != Const.DEFAULT_CARD_OPENID:
  2299. return JsonResponse(
  2300. {
  2301. "result": ErrorCode.CARD_BIND_BY_OTHER,
  2302. "description": u"{} 卡片已经被其他用户使用,请检查卡号是否正确或联系相应的经销商".format(cardNo),
  2303. "payload": {}
  2304. }
  2305. )
  2306. if group.groupId != card.groupId:
  2307. card_bind_group = Group.get_group(card.groupId)
  2308. else:
  2309. card_bind_group = group
  2310. if not card_bind_group:
  2311. card_bind_dealer = None
  2312. else:
  2313. card_bind_dealer = Dealer.objects(id = str(card_bind_group.ownerId)).first()
  2314. # 卡綁定的組和經銷商只要有一個無效, 就走增加的流程
  2315. if not card_bind_group or not card_bind_dealer:
  2316. return JsonResponse(
  2317. {
  2318. "result": 1,
  2319. "description": u"",
  2320. "payload": {
  2321. "cardNo": cardNo,
  2322. "groupId": group.groupId,
  2323. "groupName": group.groupName,
  2324. }
  2325. }
  2326. )
  2327. # 该卡已经被自己绑定
  2328. if card.openId and card.openId != Const.DEFAULT_CARD_OPENID:
  2329. return JsonResponse(
  2330. {
  2331. "result": ErrorCode.CARD_BIND_BY_SELF,
  2332. "description": u"{} 卡片已经存在于您的卡包中,是否进入编辑界面编辑该卡的相应信息".format(cardNo),
  2333. "payload": {
  2334. "cardId": str(card.id),
  2335. "cardNo": cardNo,
  2336. "cardName": card.cardName,
  2337. "groupId": card_bind_group.groupId,
  2338. "groupName": card_bind_group.groupName,
  2339. "phone": card.phone
  2340. }
  2341. }
  2342. )
  2343. # 该卡没有被绑定, 但是经销商信息已经绑定, 直接走绑定流程
  2344. if not card.openId or card.openId == Const.DEFAULT_CARD_OPENID:
  2345. return JsonResponse(
  2346. {
  2347. "result": ErrorCode.CARD_FORBID_CHARGE_GROUP,
  2348. "description": u"该卡已经被经销商录入,是否进入卡绑定界面绑定卡{}".format(cardNo),
  2349. "payload": {
  2350. "cardId": str(card.id),
  2351. "cardNo": cardNo,
  2352. "cardName": card.cardName,
  2353. "groupId": card_bind_group.groupId,
  2354. "groupName": card_bind_group.groupName,
  2355. "phone": card.phone
  2356. }
  2357. }
  2358. )
  2359. @error_tolerate(nil = JsonErrorResponse(description = u"添加卡失败"), logger = logger)
  2360. @permission_required(ROLE.myuser)
  2361. def addCard(request):
  2362. """
  2363. 添加卡 之前已经做过校验了
  2364. :param request:
  2365. :return:
  2366. """
  2367. payload = json.loads(request.body)
  2368. cardNo = payload.get("cardNo")
  2369. cardName = payload.get("cardName")
  2370. phone = payload.get("phone")
  2371. logicalCode = payload.get("logicalCode")
  2372. cardId = payload.get("cardId")
  2373. cardType = payload.get('cardType', '')
  2374. # 参数校验
  2375. if cardNo.isdigit():
  2376. cardNo = str(int(cardNo))
  2377. if not Card.check_card_no(cardNo):
  2378. return JsonErrorResponse(description = u"激活失败,无效的卡号,卡号长度不能超过32位")
  2379. if cardName and not check_entity_name(cardName):
  2380. return JsonErrorResponse(description = u"请输入正确的持卡人昵称(2-20位)")
  2381. if phone and not check_phone_number(phone):
  2382. return JsonErrorResponse(description = u"手机号码输入错误")
  2383. # 绑定设备和经销商的关系校验
  2384. device = Device.get_dev_by_l(logicalCode)
  2385. if not device:
  2386. return JsonErrorResponse(description = u"错误的设备二维码,请重新扫描设备二维码")
  2387. group = Group.get_group(device.get("groupId"))
  2388. if not group:
  2389. return JsonErrorResponse(description = u"未找到设备组,请刷新页面重试")
  2390. dealer = Dealer.objects.filter(id = group.get("ownerId")).first()
  2391. if not dealer:
  2392. return JsonErrorResponse(description = u"未找到经销商,请刷新页面重试")
  2393. agent = Agent.objects.filter(id = str(dealer.agentId)).first()
  2394. if not agent:
  2395. return JsonErrorResponse(description = u"未找到代理商,请刷新页面重试")
  2396. productAgent = get_user_manager_agent(agent)
  2397. if str(productAgent.id) != request.user.productAgentId:
  2398. return JsonErrorResponse(description = u"不是该平台下的用户,不能绑定该平台的实体卡")
  2399. if not cardId:
  2400. # 是否允许办理多张实体卡
  2401. onlyOneCard = True if "onlyOneCard" in agent.features and not request.user.many_cards else False
  2402. if onlyOneCard and request.user.cards_num > 0:
  2403. return JsonErrorResponse(description = u"您只能绑定一张实体卡,请联系经销商了解相应的规则")
  2404. # 卡存在校验
  2405. try:
  2406. card = Card.objects.get(Q(agentId=str(agent.id)) | Q(agentId=str(agent.id)), cardNo=cardNo)
  2407. except DoesNotExist:
  2408. # 没有找到卡的情况下 如果代理商规定了经销商必须要先录入卡
  2409. dealerBindCard = True if "dealerBindCard" in agent.features else False
  2410. if dealerBindCard:
  2411. return JsonErrorResponse(description=u"无效的卡号,该卡号未被录入,请联系发卡方")
  2412. card = Card(
  2413. cardNo = cardNo,
  2414. openId = request.user.openId,
  2415. cardName = cardName,
  2416. groupId = device.get("groupId"),
  2417. phone = phone,
  2418. nickName = request.user.nickname,
  2419. agentId = str(agent.id),
  2420. dealerId = str(dealer.id),
  2421. productAgentId = request.user.productAgentId,
  2422. managerialAppId = request.user.managerialAppId,
  2423. managerialOpenId = request.user.managerialOpenId,
  2424. cardType = cardType
  2425. )
  2426. card.save()
  2427. return JsonOkResponse(u"添加成功", payload = {"cardId": str(card.id)})
  2428. # 优先判断dealerId是否允许,在判断绑定关系
  2429. if card.dealerId and card.dealerId != device.get("ownerId"):
  2430. return JsonErrorResponse(description = u"该卡已被其他经销商录入,请确认卡号无误后联系您的发卡经销商")
  2431. if card.openId and card.openId != request.user.openId and card.openId != Const.DEFAULT_CARD_OPENID:
  2432. return JsonErrorResponse(description = u"该卡已被其他用户绑定,请确认卡号无误后联系您的发卡经销商")
  2433. card.openId = request.user.openId
  2434. card.cardName = cardName
  2435. card.phone = phone
  2436. card.nickName = request.user.nickname
  2437. card.groupId = device.get("groupId")
  2438. card.dealerId = str(dealer.id)
  2439. card.agentId = str(agent.id)
  2440. card.productAgentId = request.user.productAgentId
  2441. card.managerialAppId = request.user.managerialAppId
  2442. card.managerialOpenId = request.user.managerialOpenId
  2443. card.save()
  2444. return JsonOkResponse(u"添加成功", payload = {"cardId": str(card.id)})
  2445. # 1003 ErrorCode 过来的
  2446. else:
  2447. try:
  2448. card = Card.objects.get(id = cardId)
  2449. except DoesNotExist:
  2450. return JsonErrorResponse(description = u"未找到实体卡,请刷新页面后重试")
  2451. card.openId = request.user.openId
  2452. card.groupId = group.groupId
  2453. card.dealerId = group.ownerId
  2454. card.agentId = str(agent.id)
  2455. if cardName != card.cardName:
  2456. card.cardName = cardName
  2457. if phone != card.phone:
  2458. card.phone = phone
  2459. card.nickName = request.user.nickname
  2460. card.productAgentId = request.user.productAgentId
  2461. card.managerialAppId = request.user.managerialAppId
  2462. card.managerialOpenId = request.user.managerialOpenId
  2463. card.save()
  2464. return JsonOkResponse(u"添加成功", payload = {"cardId": str(card.id)})
  2465. @error_tolerate(nil = JsonErrorResponse(description = u"编辑卡失败"), logger = logger)
  2466. @permission_required(ROLE.myuser)
  2467. def editCard(request):
  2468. """
  2469. 卡编辑
  2470. :param request:
  2471. :return:
  2472. """
  2473. payload = json.loads(request.body)
  2474. cardName = payload.get("cardName")
  2475. if cardName and not check_entity_name(cardName):
  2476. return JsonErrorResponse(description = u"请输入正确的持卡人昵称(2-20位)")
  2477. phone = payload.get("phone")
  2478. if phone and not check_phone_number(phone):
  2479. return JsonErrorResponse(description = u"手机号码输入错误")
  2480. card = Card.objects(id = str(payload.get("cardId"))).first()
  2481. if not card:
  2482. return JsonErrorResponse(description = u"未找到可编辑的卡片,请刷新页面重试")
  2483. card.cardName = cardName
  2484. card.phone = phone
  2485. card.save()
  2486. return JsonOkResponse(description = u"修改成功")
  2487. @error_tolerate(nil = JsonErrorResponse(description = u"补卡失败"), logger = logger)
  2488. @permission_required(ROLE.myuser)
  2489. def swapCardNo(request):
  2490. """
  2491. 用户补卡 其实就是换个卡号
  2492. :param request:
  2493. :return:
  2494. """
  2495. payload = json.loads(request.body)
  2496. cardNo = payload.get("cardNo", "")
  2497. cardId = payload.get("cardId")
  2498. # 卡号前置去0
  2499. if cardNo.isdigit():
  2500. cardNo = str(int(cardNo))
  2501. openId = str(request.user.openId)
  2502. if not Card.check_card_no(cardNo):
  2503. return JsonErrorResponse(description = u"无效的卡号,卡号长度不能超过32位")
  2504. try:
  2505. oldCard = Card.objects.get(id = cardId)
  2506. except DoesNotExist:
  2507. return JsonErrorResponse(description = u"查询旧卡失败")
  2508. # 没有找到卡的情况下 如果代理商规定了经销商必须要先录入卡
  2509. agent = Agent.objects.get(id=oldCard.productAgentId)
  2510. dealerBindCard = True if "dealerBindCard" in agent.features else False
  2511. if dealerBindCard:
  2512. return JsonErrorResponse(description=u"无效的卡号,该卡号未被录入,请联系发卡方")
  2513. if oldCard.cardNo == cardNo:
  2514. return JsonErrorResponse(description = u"卡号一致无需修改")
  2515. if oldCard.openId != openId:
  2516. return JsonErrorResponse(description = u"不是您的卡号,无权修改")
  2517. checkStatus, checkMsg = Card.check_swap_card_no(cardNo, oldCard.dealerId, oldCard.agentId)
  2518. if not checkStatus:
  2519. return JsonErrorResponse(description = checkMsg)
  2520. # 直接将卡号更新掉,然后新建一条换卡记录
  2521. oldCard.update(cardNo = cardNo)
  2522. SwapCardRecord.add_record(oldCard.cardNo, cardNo, oldCard.agentId, str(request.user.id))
  2523. return JsonOkResponse(description = u"卡号修改成功")
  2524. @error_tolerate(nil = JsonErrorResponse(description = u"绑定失败"), logger = logger)
  2525. def bindCard(request):
  2526. """
  2527. 用户通过经销商分享的链接进来绑定实体卡
  2528. :param request:
  2529. :return:
  2530. """
  2531. openId = request.user.openId
  2532. payload = json.loads(request.body)
  2533. cardName = payload.get("cardName")
  2534. if not check_entity_name(cardName):
  2535. return JsonErrorResponse(description = u"请输入正确的持卡人昵称(2-20位)")
  2536. phone = payload.get("phone")
  2537. if not check_phone_number(phone):
  2538. return JsonErrorResponse(description = u"手机号码输入错误")
  2539. cardId = payload.get('cardId')
  2540. card = Card.objects(id = cardId).first() # type: Card
  2541. if not card:
  2542. return JsonErrorResponse(u"该实体卡不存在,请联系经销商获取正确的绑定二维码")
  2543. group = Group.get_group(card.groupId) # type: GroupDict
  2544. if not group:
  2545. return JsonErrorResponse(u'开卡地址无效,请联系经销商获取正确的绑定二维码(1001)')
  2546. dealer = Dealer.objects(id = str(group.ownerId)).first() # type: Dealer
  2547. if not dealer:
  2548. return JsonErrorResponse(u'开卡地址无效,请联系经销商获取正确的绑定二维码(1002)')
  2549. if str(dealer.id) != card.dealerId:
  2550. return JsonErrorResponse(u'开卡地址无效,请联系经销商获取正确的绑定二维码(1003)')
  2551. agent = Agent.objects(id = str(dealer.agentId)).first()
  2552. if not agent:
  2553. return JsonErrorResponse(description = u'代理商不存在,请刷新页面后重试(1002)')
  2554. productAgent = get_user_manager_agent(agent)
  2555. if str(productAgent.id) != request.user.productAgentId:
  2556. return JsonErrorResponse(description = u"不是该平台下的用户,不能绑定该平台的实体卡")
  2557. # 和卡相关的特性的获取
  2558. onlyOneCard = True if "onlyOneCard" in agent.features and not request.user.many_cards else False
  2559. if onlyOneCard and request.user.cards_num > 0:
  2560. return JsonErrorResponse(description = u"您只能绑定一张实体卡,请联系经销商了解相应的规则")
  2561. card.openId = openId
  2562. card.cardName = cardName
  2563. card.phone = phone
  2564. card.nickName = request.user.nickname
  2565. card.productAgentId = request.user.productAgentId
  2566. card.managerialAppId = request.user.managerialAppId
  2567. card.managerialOpenId = request.user.managerialOpenId
  2568. card.save()
  2569. return JsonOkResponse(description = u"添加成功", payload = {"cardId": str(card.id)})
  2570. @error_tolerate(nil = JsonErrorResponse(description = u'解绑卡失败'), logger = logger)
  2571. @record_operation_behavior()
  2572. @permission_required(ROLE.myuser)
  2573. def unbindCard(request):
  2574. # type: (WSGIRequest)->JsonResponse
  2575. openId = request.user.openId
  2576. payload = json.loads(request.body)
  2577. cardId = payload.get('id', None)
  2578. card = Card.objects(id = cardId, openId = openId).first()
  2579. if not card:
  2580. return JsonErrorResponse(description = u'找不到该卡')
  2581. updated = card.clear_card()
  2582. if not updated:
  2583. return JsonErrorResponse(description = u'变更状态失败')
  2584. return JsonResponse({"result": 1, "description": "", "payload": {}})
  2585. @error_tolerate(nil = JsonErrorResponse(description = u'获取正在使用失败'), logger = logger)
  2586. @permission_required(ROLE.myuser)
  2587. def getCurrentUse(request):
  2588. # type: (WSGIRequest)->JsonResponse
  2589. openId = request.user.openId
  2590. filters = {
  2591. "open_id": openId,
  2592. "isFinished": False,
  2593. "port": {"$ne": -1}
  2594. }
  2595. # 后付费流程中,扫码的时候会将 跳转到用户的正在服务 这个地方不要受其他设备类型的干扰
  2596. orderId = request.GET.get("orderId")
  2597. if orderId:
  2598. consumeOrder = ClientConsumeModelProxy.get_one(id=orderId)
  2599. device = Device.get_dev(consumeOrder.devNo)
  2600. if not device.owner: # 经销商此时解绑了
  2601. return JsonResponse({"result": 1, "description": "", "payload": {"total": 0, "dataList": []}})
  2602. # 下面的可以恢复正常流程
  2603. if device.devTypeCode in support_policy_device:
  2604. filters = {
  2605. "open_id": openId,
  2606. "device_imei": device.devNo,
  2607. "consumeOrder.consumeRecordId": orderId,
  2608. }
  2609. pageIndex = int(request.GET.get('pageIndex', 1))
  2610. pageSize = int(request.GET.get('pageSize', 10))
  2611. dataList = []
  2612. for item in ServiceProgress.get_collection().find(filters):
  2613. if int(time.time()) > item['finished_time']:
  2614. continue
  2615. else:
  2616. try:
  2617. devNo = item['device_imei']
  2618. device = Device.get_dev(devNo) # type: DeviceDict
  2619. smartBox = ActionDeviceBuilder.create_action_device(device)
  2620. group = Group.get_group(device['groupId'])
  2621. nowTime = int(time.time())
  2622. data = {
  2623. 'startTime': time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(item['start_time'])),
  2624. 'order': item['consumeOrder'],
  2625. 'address': group.get('address', ''),
  2626. 'groupName': group.get('groupName', ''),
  2627. 'devType': device['devType'].get('name'),
  2628. 'devTypeCode': device['devType'].get('code'),
  2629. 'logicalCode': device['logicalCode'],
  2630. 'status': Const.DEV_WORK_STATUS_WORKING,
  2631. 'devNo': devNo,
  2632. 'majorDeviceType': device.majorDeviceType
  2633. }
  2634. if 'show_PG_to_user' in device.owner.features and device.support_power_graph and item.get("port"):
  2635. data.update({'showPG': True, 'port': item.get("port")})
  2636. if device['devType']['code'] in support_policy_weifule:
  2637. orderInfoList = smartBox.get_current_use(base_data=data, spDict=item)
  2638. dataList.extend(orderInfoList)
  2639. continue
  2640. needTime = item.get('consumeOrder', {}).get('needTime', None)
  2641. unit = item.get('consumeOrder', {}).get('unit', None)
  2642. if needTime and unit in [u'分钟', u'小时', u'天',
  2643. u'秒']: # 数据库里面记录的都是归为分钟(建议后续全部统一为秒).这里计算的时间是以设备为准,不是以端口为准的,实际如果有端口,应该以端口为准
  2644. if needTime == 999: # 特殊表示充满自停
  2645. data.update({'needTime': u'充满自停'})
  2646. else:
  2647. data.update({'needTime': u'%s分钟' % needTime,
  2648. 'leftTime': round(int(item['finished_time'] - nowTime) / 60.0, 1)})
  2649. if item.get('port', -2) in [0, -1]:
  2650. dataList.append(data)
  2651. continue
  2652. else:
  2653. data.update({"port": item["port"]})
  2654. ctrInfo = Device.get_dev_control_cache(devNo)
  2655. _coin = data.get("order", dict()).get("coin")
  2656. if _coin:
  2657. data["order"].update({"coin": "{}{}".format(_coin, smartBox.show_pay_unit)})
  2658. try:
  2659. curInfo = device.deviceAdapter.get_port_using_detail(item['port'], ctrInfo)
  2660. if curInfo.has_key('startTime'): # 微付乐自己的单板会上报startTime上来,和这里的startTime有冲突,所以,需要以订单的startTime为准
  2661. curInfo.pop('startTime')
  2662. if device.devTypeCode == Const.DEVICE_TYPE_CODE_CHARGING_HAINIAO:
  2663. curInfo['port'] = str(int(curInfo['port']) + 1)
  2664. if 'orderNo' in curInfo:
  2665. if data['order']['orderNo'] == curInfo['orderNo']: # 说明此单正处于运行中,数据可以直接用
  2666. data.update(curInfo)
  2667. else:
  2668. data.update({
  2669. 'orderNo': data['order']['orderNo'],
  2670. 'desc': u'此订单已经下发到设备上,上一单运行完毕就会自动运行此订单',
  2671. })
  2672. data.pop('leftTime', None)
  2673. data.pop('leftElec', None)
  2674. else:
  2675. data.update(curInfo)
  2676. # 正在服务显示按钮
  2677. data.update(DeviceType.get_services_button(device['devType']['id']))
  2678. try:
  2679. data.update({'actualNeedTime': data['usedTime'] + data['leftTime']})
  2680. except Exception as e:
  2681. pass
  2682. dealer = Dealer.get_dealer(device.ownerId)
  2683. if dealer:
  2684. agent = Agent.objects(id = dealer['agentId']).first() # type: Agent
  2685. if agent:
  2686. agentFeatures = agent.features
  2687. if 'show_elec_data_for_user' not in agentFeatures:
  2688. data.pop('elec', None)
  2689. data.pop('needElec', None)
  2690. data.pop('power', None)
  2691. data.pop("leftElec", None)
  2692. data.pop("usedElec",None)
  2693. if not device.is_auto_refund and "hide_refund_data_for_user" in agentFeatures:
  2694. data.pop("consumeMoney", None)
  2695. data.pop("leftMoney", None)
  2696. data.pop("usedTime", None)
  2697. data.pop("leftTime", None)
  2698. if 'hide_consume_coin_data' in device.devTypeFeatures:
  2699. data.pop('consumeMoney', None)
  2700. data.pop('leftMoney', None)
  2701. if device.devTypeCode in [Const.DEVICE_TYPE_CODE_CHARGING_HONGZHUO]:
  2702. data.pop('actualNeedTime',None)
  2703. data['power'] = data['powerNow']
  2704. if device.devTypeCode in [Const.DEVICE_TYPE_CODE_CHANGING_BL_TEN,
  2705. Const.DEVICE_TYPE_CODE_CHANGING_BL_TWELVE]:
  2706. data.pop('actualNeedTime',None)
  2707. # 这里需要反过来做一次校验,因为网络不稳定,可能造成丢包,没有刷新状态。
  2708. # 如果出来的状态是空闲的,那就说明服务已经结束
  2709. # zjl 充电柜的临时跳过 下个版本会对这个function进行彻底的拆分
  2710. if device.devTypeCode not in [
  2711. Const.DEVICE_TYPE_CODE_CABINET_NEW,
  2712. Const.DEVICE_TYPE_CODE_CABINET,
  2713. Const.DEVICE_TYPE_CODE_CHANGING_DIANCHUANCARCHARGING,
  2714. Const.DEVICE_TYPE_CODE_CHANGING_BL_TEN,
  2715. Const.DEVICE_TYPE_CODE_CHANGING_BL_TWELVE,] + support_policy_device:
  2716. isFinished = False
  2717. if curInfo.has_key('power') and curInfo.has_key('leftTime'):
  2718. if curInfo['power'] == 0 and curInfo['leftTime'] in [0, u'(线路空载)']:
  2719. isFinished = True
  2720. else:
  2721. if (curInfo.has_key('power') and curInfo['power'] == 0) or (
  2722. curInfo.has_key('leftTime') and curInfo['leftTime'] in [0, u'(线路空载)']):
  2723. isFinished = True
  2724. if isFinished:
  2725. try:
  2726. ServiceProgress.get_collection().update_many(
  2727. {
  2728. 'open_id': openId,
  2729. 'isFinished': False,
  2730. 'device_imei': devNo,
  2731. 'port': item['port']
  2732. }, {
  2733. '$set':
  2734. {
  2735. 'isFinished': True,
  2736. 'expireAt': datetime.datetime.now()
  2737. }
  2738. })
  2739. data['leftTime'] = 0
  2740. except Exception as e:
  2741. logger.error('update service progress e=%s' % e)
  2742. except Exception as e:
  2743. logger.exception('get cur info=%s' % e)
  2744. dataList.append(data)
  2745. except Exception as e:
  2746. logger.exception(e)
  2747. # 返回数据之前 将数据再次过滤一遍
  2748. count = len(dataList)
  2749. dataList = dataList[(pageIndex - 1) * pageSize: pageIndex * pageSize]
  2750. newDataList = list()
  2751. for _consumeDict in dataList:
  2752. if "devNo" in _consumeDict:
  2753. dev = Device.get_dev(_consumeDict["devNo"])
  2754. newDataList.append(UserConsumeFilter(dev.owner, _consumeDict).filter())
  2755. else:
  2756. newDataList.append(_consumeDict)
  2757. return JsonResponse({
  2758. "result": 1,
  2759. "description": "",
  2760. "payload": {
  2761. "total": count,
  2762. "dataList": newDataList
  2763. }
  2764. })
  2765. @error_tolerate(nil=JsonErrorResponse(description = u'获取计数失败'), logger = logger)
  2766. @permission_required(ROLE.myuser)
  2767. def getUserCenterCount(request):
  2768. # type: (WSGIRequest)->JsonResponse
  2769. openId = request.user.openId
  2770. # 统计正在使用
  2771. currentUse = ConsumeRecord.objects.filter(
  2772. openId=openId,
  2773. status__in=[
  2774. ConsumeRecord.Status.RUNNING, ConsumeRecord.Status.END
  2775. ]
  2776. ).count()
  2777. # 统计反馈消息
  2778. dealerIds = MyUser.get_dealer_ids(openId, request.user.productAgentId)
  2779. newMessage = FeedBack.objects.filter(openId=openId, ownerId__in=dealerIds, isRead=False)
  2780. return JsonResponse(
  2781. {
  2782. "result": 1,
  2783. "description": "",
  2784. "payload": {
  2785. "currentUse": currentUse, "newMessage": newMessage.count()
  2786. }
  2787. })
  2788. @error_tolerate(nil = JsonErrorResponse(description = u'获取卡记录失败'), logger = logger)
  2789. @permission_required(ROLE.myuser)
  2790. def getUserCardRecord(request):
  2791. # type: (WSGIRequest)->JsonResponse
  2792. pageIndex = int(request.GET.get('pageIndex', 1))
  2793. pageSize = int(request.GET.get('pageSize', 10))
  2794. startTime = request.GET.get('startTime', 10)
  2795. endTime = request.GET.get('endTime', 10)
  2796. cardId = request.GET.get('cardId', None)
  2797. type = request.GET.get('type', None)
  2798. card = Card.objects.get(id = cardId)
  2799. if type == "chargeCard":
  2800. dataList = []
  2801. for item in CardRechargeRecord.get_collection().find(
  2802. {
  2803. 'cardId': cardId,
  2804. 'dateTimeAdded':
  2805. {
  2806. '$gte': to_datetime(startTime + " 00:00:00"),
  2807. '$lte': to_datetime(endTime + " 23:59:59")
  2808. },
  2809. "remarks": {
  2810. "$ne": u"退币"
  2811. }
  2812. }
  2813. ).sort("dateTimeAdded", -1):
  2814. data = {
  2815. "cardId": str(item['_id']),
  2816. "cardNo": card.cardNo,
  2817. "via": "chargeCard",
  2818. "amount": item['money'],
  2819. "coins": item.get('coins', item['money']),
  2820. "address": item['address'],
  2821. "groupName": item['groupName'],
  2822. "balance": item['balance'],
  2823. "createdTime": item['dateTimeAdded'].strftime('%Y-%m-%d %H:%M:%S')
  2824. }
  2825. if item.has_key('preBalance'):
  2826. data.update({'preBalance': item['preBalance']})
  2827. dataList.append(data)
  2828. elif type == "consume":
  2829. dataList = []
  2830. rcds = CardConsumeRecord.get_collection().find({'cardId': cardId,
  2831. 'dateTimeAdded': {
  2832. '$gte': to_datetime(startTime + " 00:00:00"),
  2833. '$lte': to_datetime(endTime + " 23:59:59")}}).sort(
  2834. "dateTimeAdded", -1)
  2835. for item in rcds:
  2836. newData = {
  2837. "cardId": str(cardId),
  2838. "cardNo": card.cardNo,
  2839. "via": "consume",
  2840. "devType": item['devType'],
  2841. "amount": item['money'],
  2842. "logicalCode": item['logicalCode'],
  2843. "address": item['address'],
  2844. "groupName": item['groupName'],
  2845. "createdTime": item['dateTimeAdded'].strftime('%Y-%m-%d %H:%M:%S')
  2846. }
  2847. newData.update(item.get('servicedInfo', {}))
  2848. dataList.append(newData)
  2849. elif type == 'order':
  2850. dataList = [
  2851. {
  2852. "via": "order",
  2853. "amount": item['money'],
  2854. "coins": item.get('coins', item['money']),
  2855. "createdTime": item['dateTimeAdded'].strftime('%Y-%m-%d %H:%M:%S'),
  2856. "status": u'等待刷卡充值' if item['status'] == 'finishedPay' else u'充值完成',
  2857. "desc": item['remarks']
  2858. }
  2859. for item in CardRechargeOrder.get_collection().find({
  2860. 'cardId': cardId,
  2861. 'dateTimeAdded': {'$gte': to_datetime(startTime + " 00:00:00"),
  2862. '$lte': to_datetime(endTime + " 23:59:59")}})
  2863. .sort("dateTimeAdded", -1)]
  2864. elif type == "refund":
  2865. dataList = []
  2866. for item in CardRechargeRecord.get_collection().find(
  2867. {
  2868. 'cardId': cardId,
  2869. 'dateTimeAdded':
  2870. {
  2871. '$gte': to_datetime(startTime + " 00:00:00"),
  2872. '$lte': to_datetime(endTime + " 23:59:59")
  2873. },
  2874. "remarks": u"退币"
  2875. }
  2876. ).sort("dateTimeAdded", -1):
  2877. data = {
  2878. "cardId": str(item['_id']),
  2879. "cardNo": card.cardNo,
  2880. "via": "refund",
  2881. "amount": item['money'],
  2882. "coins": item.get('coins', item['money']),
  2883. "address": item['address'],
  2884. "groupName": item['groupName'],
  2885. "balance": item['balance'],
  2886. "createdTime": item['dateTimeAdded'].strftime('%Y-%m-%d %H:%M:%S')
  2887. }
  2888. if item.has_key('preBalance'):
  2889. data.update({'preBalance': item['preBalance']})
  2890. dataList.append(data)
  2891. elif type == "frozen":
  2892. dataList = []
  2893. for item in getattr(card, 'ongoingList', []):
  2894. order = ConsumeRecord.objects.filter(id = item['transaction_id']).first()
  2895. data = {
  2896. "amount": order.coin.mongo_amount,
  2897. "createdTime": order.startTime.strftime(Const.DATETIME_FMT),
  2898. "via": "consume",
  2899. "devType": order.dev_type_name,
  2900. "chargeIndex": order.used_port,
  2901. "logicalCode": order.logicalCode,
  2902. "address": order.address,
  2903. "groupName": order.groupName,
  2904. "balance": card.balance.mongo_amount,
  2905. "spendMoney": order.coin.mongo_amount,
  2906. }
  2907. dataList.append(data)
  2908. else:
  2909. return JsonResponse({"result": 0, "description": u"查询类型错误", "payload": {}})
  2910. return JsonResponse({"result": 1, "description": "", "payload": {"total": len(dataList), "dataList": dataList[(pageIndex - 1) * pageSize: pageIndex * pageSize]}})
  2911. @permission_required(ROLE.myuser)
  2912. def freezeCard(request):
  2913. # type: (WSGIRequest)->JsonResponse
  2914. payload = json.loads(request.body)
  2915. isFrozen = payload.get('frozen')
  2916. cardId = payload.get('id', '')
  2917. try:
  2918. card = Card.objects.get(id = cardId)
  2919. card.frozen = isFrozen
  2920. card.status = 'deactive'
  2921. card.save()
  2922. except Exception as e:
  2923. logger.exception(e.message)
  2924. return JsonResponse({"result": 0, "description": u'系统错误', "payload": {}})
  2925. # 如果是淋浴器,如果卡正在使用,直接把设备停掉,发指令过去
  2926. return JsonResponse({"result": 1, "description": '', "payload": {}})
  2927. @permission_required(ROLE.myuser)
  2928. def bindVirtualCardToRechargeIDCard(request):
  2929. # type: (WSGIRequest)->JsonResponse
  2930. # TODO zjl 这个地方最好加上虚拟卡的绑定记录
  2931. payload = json.loads(request.body)
  2932. virtualCardId = payload.get('virtualCardId')
  2933. rechargeIDCardId = payload.get('rechargeIDCardId')
  2934. if virtualCardId is None:
  2935. return JsonErrorResponse(description = u'未找到虚拟卡ID')
  2936. if rechargeIDCardId is None:
  2937. return JsonErrorResponse(description = u'未找到ID实体卡')
  2938. card = Card.objects(id = rechargeIDCardId).first()
  2939. if card is None:
  2940. return JsonErrorResponse(description = u'未找到ID实体卡')
  2941. if card.cardType != RECHARGE_CARD_TYPE.ID:
  2942. return JsonErrorResponse(description = u'该卡不是ID卡')
  2943. virtualCard = UserVirtualCard.objects(id = virtualCardId).first()
  2944. if virtualCard is None:
  2945. return JsonErrorResponse(description = u'未找到虚拟卡')
  2946. updated = card.bind_virtual_card(virtualCard)
  2947. if updated:
  2948. return JsonOkResponse()
  2949. else:
  2950. return JsonErrorResponse(description = u'绑定失败')
  2951. def unbindVirtualCardToRechargeIDCard(request):
  2952. # type: (WSGIRequest)->JsonResponse
  2953. payload = json.loads(request.body)
  2954. virtualCardId = payload.get('virtualCardId')
  2955. rechargeIDCardId = payload.get('rechargeIDCardId')
  2956. if virtualCardId is None:
  2957. return JsonErrorResponse(description = u'未找到虚拟卡ID')
  2958. if rechargeIDCardId is None:
  2959. return JsonErrorResponse(description = u'未找到ID实体卡')
  2960. card = Card.objects(id = rechargeIDCardId).first()
  2961. if card is None:
  2962. return JsonErrorResponse(description = u'未找到ID实体卡')
  2963. if card.cardType != RECHARGE_CARD_TYPE.ID:
  2964. return JsonErrorResponse(description = u'该卡不是ID卡')
  2965. virtualCard = UserVirtualCard.objects(id = virtualCardId).first()
  2966. if virtualCard is None:
  2967. return JsonErrorResponse(description = u'未找到虚拟卡')
  2968. updated = card.unbind_virtual_card(virtualCard)
  2969. if updated:
  2970. return JsonOkResponse()
  2971. else:
  2972. return JsonErrorResponse(description = u'解绑失败')
  2973. @permission_required(ROLE.myuser)
  2974. def cardDiscountList(request):
  2975. # type: (WSGIRequest)->JsonResponse
  2976. """
  2977. 获取用户实体卡套餐.
  2978. 获取的方式有两种:
  2979. 1、实体卡管理里面,直接选择卡,进入套餐界面。传入cardId参数;
  2980. 2、在扫码的充卡界面,直接输入卡号,进入套餐界面,传入扫码的设备号;
  2981. :param request:
  2982. :return:
  2983. """
  2984. def user_center_recharge(card_id):
  2985. card = Card.objects(id = str(card_id)).first() # type: Card
  2986. if not card:
  2987. logger.error('can not find the cardId = %s' % request.GET.get('cardId'))
  2988. return JsonResponse({'result': 0, 'description': u'没有找到对应的卡,请您刷新页面重试', 'payload': {}})
  2989. if not card.dealerId or not card.groupId:
  2990. return JsonResponse({
  2991. 'result': ErrorCode.CARD_NEED_BIND_GROUP,
  2992. 'description': u'此卡没有绑定开卡地址',
  2993. 'payload': {
  2994. 'cardId': str(card.id),
  2995. 'cardNo': card.cardNo,
  2996. 'phone': card.phone,
  2997. 'cardName': card.cardName
  2998. }})
  2999. group = Group.get_group(card.groupId) # type: GroupDict
  3000. card_rule_list = group.card_rule_list
  3001. card_rule_list = filter(lambda x: (float(x["coins"]) + float(card.balance)) < 5000, card_rule_list)
  3002. return JsonResponse({
  3003. 'result': 1, 'description': 'SUCCESS', 'payload': {'groupId': card.groupId, 'ruleList': card_rule_list}})
  3004. def device_type_card_charge(devCache):
  3005. """
  3006. 从套餐页面的充卡按钮进入的卡充值页面。
  3007. 不同设备类型进入不同的判断,后续有新的设备类型特有的需求增加新的判断分支。
  3008. """
  3009. if devCache.devTypeCode == Const.DEVICE_TYPE_CODE_WASHCAR_LANGUANG:
  3010. box = ActionDeviceBuilder.create_action_device(devCache)
  3011. devStatus = box.get_dev_status()
  3012. if devStatus.get('xf_status') == '0x0001':
  3013. allowCardCharge = True
  3014. else:
  3015. allowCardCharge = False
  3016. return allowCardCharge
  3017. return True
  3018. if 'cardId' in request.GET:
  3019. return user_center_recharge(request.GET.get('cardId'))
  3020. else:
  3021. if 'devNo' in request.GET and request.GET.get('devNo'):
  3022. dev = Device.get_dev(request.GET.get('devNo')) # type: Optional[DeviceDict]
  3023. elif 'logicalCode' in request.GET and request.GET.get('logicalCode'):
  3024. dev = Device.get_dev_by_logicalCode(request.GET.get('logicalCode')) # type: Optional[DeviceDict]
  3025. else:
  3026. dev = None # type: Optional[DeviceDict]
  3027. if not dev:
  3028. return JsonErrorResponse(description = u'参数错误,请刷新重试(1001)')
  3029. if device_type_card_charge(dev) is False:
  3030. return JsonErrorResponse(description = u'暂不支持卡充值,请联系经销商检查设备或重试一下')
  3031. group = Group.get_group(dev.groupId) # type: GroupDict
  3032. return JsonResponse({'result': 1, 'description': 'SUCCESS',
  3033. 'payload': {'groupId': dev.groupId, 'ruleList': group.card_rule_list}})
  3034. @error_tolerate(nil = JsonErrorResponse(description = u'未知错误'))
  3035. def getAgentQRCode(request):
  3036. # type: (WSGIRequest)->JsonResponse
  3037. agentId = request.GET.get('agentId', None)
  3038. if agentId is None:
  3039. return JsonErrorResponse(description = u'页面过期,请您重新扫码重试')
  3040. try:
  3041. agent = Agent.objects.get(id = agentId)
  3042. if agent.gzhServiceQrcodeUrl == '':
  3043. return JsonErrorResponse(description = u'没有提供公众号的二维码,需要先配置好公众号的二维码')
  3044. else:
  3045. return JsonOkResponse(
  3046. payload = {'url': agent.gzhServiceQrcodeUrl, 'linkUrl': agent.gzhServiceLinkUrl, 'title': agent.title,
  3047. 'desc': agent.desc})
  3048. except DoesNotExist:
  3049. logger.exception('could not find agent by agentId={0}'.format(agentId))
  3050. return JsonErrorResponse(description = u'没有找到对应的代理商,请您检查数据是否正确')
  3051. @permission_required(ROLE.myuser)
  3052. def reportEndUserLocation(request):
  3053. # type: (WSGIRequest)->JsonResponse
  3054. """
  3055. 上报终端用户的地理信息
  3056. `sample request`
  3057. {
  3058. 'logicalCode': '111',
  3059. 'lng': 12323.23
  3060. 'lat': 1232123.22,
  3061. 'type': 'gcj02'
  3062. }
  3063. :param request:
  3064. :return:
  3065. """
  3066. currentUser = request.user # type: cast(MyUser)
  3067. payload = json.loads(request.body)
  3068. logger.debug('end user location is: %s' % payload)
  3069. try:
  3070. GPS_TYPE.lookupByValue(payload['type'])
  3071. except ValueError:
  3072. return JsonErrorResponse(u'无效的GPS类型')
  3073. pointPair = (float(payload.get('lng', 360)), float(payload.get('lat', 360))) # type: Tuple[float, float]
  3074. if any(map(lambda _: _ == 360 or isnan(_), pointPair)):
  3075. return JsonResponse({'result': 0, 'description': u'定位失败,请打开位置权限,刷新后重试'})
  3076. if pointPair in [_.coordinates for _ in currentUser.locations]:
  3077. logger.debug('user{0!r} location point{1} duplicates'.format(currentUser, pointPair))
  3078. return JsonResponse({'result': 1, 'description': ''})
  3079. location = EndUserLocation(logicalCode = payload['logicalCode'],
  3080. point = pointPair,
  3081. type = payload['type'])
  3082. updated = currentUser.update(add_to_set__locations = location)
  3083. if not updated:
  3084. logger.info(u'记录终端用户地址失败 user({0!r}) payload={1}'.format(currentUser, payload))
  3085. return JsonResponse({'result': 1, 'description': ''})
  3086. @permission_required(ROLE.myuser)
  3087. def getOnsale(request):
  3088. # type: (WSGIRequest)->JsonResponse
  3089. """
  3090. 用户侧 进入之前获取营销活动的流程
  3091. :param request:
  3092. :return:
  3093. """
  3094. lc = request.GET.get('logicalCode')
  3095. showSite = int(request.GET.get('showSite'))
  3096. dev = Device.get_dev_by_logicalCode(lc)
  3097. nowTime = datetime.datetime.now()
  3098. onsales = OnSale.objects.filter(status = 'start', showSite = showSite, dealerId = dev['ownerId'],
  3099. logicalCodeList = lc, startTime__lte = nowTime, endTime__gte = nowTime)
  3100. if onsales.count() <= 0:
  3101. return JsonOkResponse()
  3102. onsaleList = []
  3103. # 查询是否已经参加了活动, 如果已经参加 并且活动描述仅仅只能参加一次 不在展示该活动
  3104. for onsale in onsales:
  3105. if OnSaleRecord.objects.filter(onsaleId = str(onsale['id']), userId__in = [str(request.user.id),
  3106. request.user.openId]).count() and onsale.showType == "onlyOne":
  3107. continue
  3108. onsaleList.append(onsale)
  3109. if not onsaleList:
  3110. return JsonOkResponse()
  3111. # TODO 这个活动为什么是随机的 ??? 这个 shuffle 也很有问题
  3112. # random.shuffle(onsaleList)
  3113. # onsale = onsaleList[0]
  3114. onsale = random.choice(onsaleList)
  3115. return JsonResponse({
  3116. "result": 1, "description": '',
  3117. "payload": {
  3118. 'onsaleId': str(onsale.id),
  3119. 'img': onsale.img,
  3120. 'desc': onsale.desc,
  3121. 'onClickUrl': onsale.onClickUrl,
  3122. 'showType': onsale.showType
  3123. }
  3124. })
  3125. @permission_required(ROLE.myuser)
  3126. def getPromotionalCoins(request):
  3127. # type: (WSGIRequest)->JsonResponse
  3128. """
  3129. 营销活动,用户获币
  3130. :param request:
  3131. :return:
  3132. """
  3133. lc = request.GET.get('logicalCode')
  3134. onsaleId = request.GET.get('onsaleId')
  3135. # 先检查这个用户是否有领取过,如果领取过,就不允许领取
  3136. if not onsaleId:
  3137. return JsonErrorResponse(description = u'找不到营销活动ID')
  3138. if not lc:
  3139. return JsonErrorResponse(description = u'找不到设备')
  3140. user = request.user # type: MyUser
  3141. userId = str(user.id)
  3142. key = '{user}{onsale}-lock'.format(user = userId, onsale = onsaleId)
  3143. with memcache_lock(key = key, value = '1', expire = 60) as acquired:
  3144. if acquired:
  3145. count = OnSaleRecord.objects.filter(onsaleId = onsaleId, userId = userId).count()
  3146. if count > 0:
  3147. return JsonErrorResponse(description = u'您已经领取过金币了哦,不能再领了哦')
  3148. onsale = OnSale.objects(id = onsaleId).first() # type: Optional[OnSale]
  3149. if not onsale:
  3150. return JsonErrorResponse(description = u'推广活动不存在')
  3151. if onsale.status == 'stop':
  3152. return JsonErrorResponse(description = u'推广活动已经下架,无法领取了哦')
  3153. coins = int(onsale.detailDict.get('coins', 0))
  3154. updated = user.incr_balance(VirtualCoin(coins))
  3155. if not updated:
  3156. return JsonErrorResponse(description = u'获币失败')
  3157. # 添加一条充值记录
  3158. orderNo = str(uuid.uuid1())
  3159. dev = Device.get_dev_by_logicalCode(lc)
  3160. group = Group.get_group(dev['groupId'])
  3161. try:
  3162. newRcd = RechargeRecord(orderNo = orderNo,
  3163. coins = coins, money = 0.00, openId = request.user.openId,
  3164. groupId = dev['groupId'],
  3165. devNo = dev['devNo'], logicalCode = lc,
  3166. ownerId = dev['ownerId'], groupName = group['groupName'],
  3167. groupNumber = dev['groupNumber'], address = group['address'],
  3168. wxOrderNo = u'活动赠币',
  3169. devTypeName = dev.devTypeName, nickname = '',
  3170. result = 'success', via = 'onsaleSendCoins')
  3171. newRcd.save()
  3172. except Exception as e:
  3173. logger.exception('update record for feedback coins error=%s,orderNo=%s' % (e, orderNo))
  3174. # 增加一条活动
  3175. try:
  3176. newRcd = OnSaleRecord(
  3177. onsaleId = onsaleId,
  3178. userId = userId,
  3179. nickName = request.user.nickname,
  3180. addedTime = datetime.datetime.now(),
  3181. onsaleDetail = {'coins': coins}
  3182. )
  3183. newRcd.save()
  3184. except Exception as e:
  3185. logger.exception('update record for onsale record error=%s,orderNo=%s' % e)
  3186. return JsonOkResponse(description = u'赠送成功!您可以直接使用金币!')
  3187. else:
  3188. return JsonErrorResponse(description = u'您已正在领取')
  3189. @permission_required(ROLE.myuser)
  3190. def getPromotionalDuration(request):
  3191. # type: (WSGIRequest)->JsonResponse
  3192. """
  3193. :param request:
  3194. :return:
  3195. """
  3196. lc = request.GET.get('logicalCode')
  3197. onsaleId = request.GET.get('onsaleId')
  3198. # 先检查这个用户是否有领取过,如果领取过,就不允许领取
  3199. if not onsaleId:
  3200. return JsonErrorResponse(description = u'找不到营销活动ID')
  3201. if not lc:
  3202. return JsonErrorResponse(description = u'找不到设备')
  3203. userId = str(request.user.id)
  3204. key = '{user}{onsale}-lock'.format(user = userId, onsale = onsaleId)
  3205. with memcache_lock(key = key, value = '1', expire = 60) as acquired:
  3206. if acquired:
  3207. # 先检查这个用户是否有领取过,如果领取过,就不允许领取
  3208. count = OnSaleRecord.objects.filter(onsaleId = onsaleId, userId = userId).count()
  3209. if count > 0:
  3210. return JsonErrorResponse(description = u'您已经免费体验过了哦,不能再免费体验了哦,您可以试试充值消费哦')
  3211. onsale = OnSale.objects(id = onsaleId).first() # type: Optional[OnSale]
  3212. if not onsale:
  3213. return JsonErrorResponse(description = u'该活动不存在')
  3214. if onsale.status == 'stop':
  3215. return JsonErrorResponse(description = u'推广活动已经下架,无法体验了哦')
  3216. duration = int(onsale.detailDict.get('duration')) * 60
  3217. dev = Device.get_dev_by_logicalCode(lc) # type: DeviceDict
  3218. box = ActionDeviceBuilder.create_action_device(dev)
  3219. try:
  3220. box.send_dev_runtime(request.user.openId, duration)
  3221. except ServiceException, e:
  3222. return JsonErrorResponse(description = e.result.get('description'))
  3223. except Exception, e:
  3224. return JsonErrorResponse(description = u'系统异常,请您重试')
  3225. # 增加一条活动
  3226. try:
  3227. OnSaleRecord(
  3228. onsaleId = onsaleId,
  3229. userId = str(request.user.id),
  3230. nickName = request.user.nickname,
  3231. addedTime = datetime.datetime.now(),
  3232. onsaleDetail = {'duration': int(onsale.detailDict.get('duration'))}
  3233. ).save()
  3234. except Exception as e:
  3235. logger.exception('update record for onsale record error=%s' % (e,))
  3236. return JsonOkResponse(description = u'服务开始啦!您可以体验啦')
  3237. else:
  3238. return JsonErrorResponse(description = u'您已领取福利')
  3239. @permission_required(ROLE.myuser)
  3240. def getBannerList(request):
  3241. # type: (WSGIRequest)->JsonResponse
  3242. """
  3243. :param request:
  3244. :return:
  3245. """
  3246. lc = request.GET.get('logicalCode')
  3247. dev = Device.get_dev_by_logicalCode(lc)
  3248. dealer = Dealer.objects.get(id = dev['ownerId'])
  3249. agent = Agent.objects.get(id = dealer.agentId)
  3250. aBannerList = agent.bannerList
  3251. if not aBannerList or dealer.isShowBanner is False:
  3252. return JsonResponse({"result": 1, "description": '', "payload": {}})
  3253. return JsonResponse({"result": 1, "description": '', "payload": aBannerList})
  3254. @error_tolerate(nil = DefaultJsonErrorResponse, logger = logger)
  3255. @permission_required(ROLE.myuser)
  3256. def submitComment(request):
  3257. # type: (WSGIRequest)->JsonResponse
  3258. """
  3259. :param request:
  3260. :return:
  3261. """
  3262. payload = json.loads(request.body)
  3263. lc = payload.get('logicalCode')
  3264. desc = payload.get('description')
  3265. dev = Device.get_dev_by_logicalCode(lc)
  3266. group = Group.get_group(dev['groupId'])
  3267. Comment(
  3268. devNo = dev['devNo'],
  3269. logicalCode = lc,
  3270. groupId = dev['groupId'],
  3271. groupNumber = dev['groupNumber'],
  3272. groupName = group['groupName'],
  3273. address = group['address'],
  3274. ownerId = dev['ownerId'],
  3275. openId = request.user.openId,
  3276. nickname = request.user.nickname,
  3277. ratingList = payload['rating'],
  3278. description = desc
  3279. ).save()
  3280. return JsonResponse({"result": 1, "description": '', "payload": {}})
  3281. @permission_required(ROLE.myuser)
  3282. def onsaleRecharge(request):
  3283. # type: (WSGIRequest)->JsonResponse
  3284. """
  3285. :param request:
  3286. :return:
  3287. """
  3288. user = request.user # type: MyUser
  3289. lc = request.GET.get('logicalCode')
  3290. if not lc:
  3291. return JsonResponse({"result": 0, "description": u'设备不存在,请刷新后重试(1001)', "payload": {}})
  3292. device = Device.get_dev_by_logicalCode(lc) # type: DeviceDict
  3293. if not device:
  3294. return JsonResponse({"result": 0, "description": u'设备不存在,请刷新后重试(1002)', "payload": {}})
  3295. onsaleId = request.GET.get('onsaleId')
  3296. if not onsaleId:
  3297. return JsonResponse({"result": 0, "description": u'活动ID错误,请刷新后重试', "payload": {}})
  3298. if user.groupId != device.groupId:
  3299. return JsonResponse({"result": 0, "description": u'请在扫码后点击活动页面去充值。点击其他方式的活动链接无效。', "payload": {}})
  3300. jumpUrl = concat_user_recharge_url(l = lc)
  3301. # 增加一条活动
  3302. try:
  3303. OnSaleRecord(
  3304. onsaleId = onsaleId,
  3305. userId = str(request.user.id),
  3306. nickName = request.user.nickname,
  3307. addedTime = datetime.datetime.now(),
  3308. onsaleDetail = {}
  3309. ).save()
  3310. except Exception as e:
  3311. logger.exception(e)
  3312. return JsonResponse({"result": 0, "description": u'系统异常,请重试', "payload": {}})
  3313. return JsonResponse({"result": 1, "description": '', "payload": {'url': jumpUrl}})
  3314. @permission_required(ROLE.myuser)
  3315. def onsaleTicketList(request):
  3316. # type: (WSGIRequest)->JsonResponse
  3317. """
  3318. :param request:
  3319. :return:
  3320. """
  3321. user = request.user # type: MyUser
  3322. lc = request.GET.get('logicalCode')
  3323. onsaleId = request.GET.get('onsaleId')
  3324. agentId = user.productAgentId
  3325. if agentId is None:
  3326. return JsonResponse({"result": 0, "description": '获取代理商错误', "payload": {}})
  3327. encodeUrl = concat_user_cardTicketList_entry_url(agentId = agentId, l = lc)
  3328. # 增加一条活动
  3329. try:
  3330. OnSaleRecord(
  3331. onsaleId = onsaleId,
  3332. userId = str(request.user.id),
  3333. nickName = request.user.nickname,
  3334. addedTime = datetime.datetime.now(),
  3335. onsaleDetail = {}
  3336. ).save()
  3337. except Exception as e:
  3338. logger.exception(e)
  3339. return JsonResponse({"result": 0, "description": u'系统异常,请重试', "payload": {}})
  3340. return JsonResponse({"result": 1, "description": '', "payload": {'url': encodeUrl}})
  3341. @permission_required(ROLE.myuser)
  3342. def sendCodeForVerify(request):
  3343. # type: (WSGIRequest)->JsonResponse
  3344. """
  3345. :param request:
  3346. :return:
  3347. """
  3348. payload = json.loads(request.body)
  3349. lc = payload.get('logicalCode')
  3350. onsaleId = payload.get('onsaleId')
  3351. userId = str(request.user.id)
  3352. key = '{user}{onsale}-lock'.format(user = userId, onsale = onsaleId)
  3353. with memcache_lock(key = key, value = '1', expire = 60) as acquired:
  3354. if acquired:
  3355. count = OnSaleRecord.objects.filter(onsaleId = onsaleId, userId = userId).count()
  3356. if count > 0:
  3357. return JsonErrorResponse(description = u'您已经免费体验过了哦,不能再免费体验了哦,您可以试试充值消费哦')
  3358. dev = Device.get_dev_by_logicalCode(lc) # type: DeviceDict
  3359. phoneNumber = payload.get('phoneNumber')
  3360. dealer = Dealer.get_dealer(dev['ownerId'])
  3361. agent = Agent.objects.get(id = dealer['agentId'])
  3362. status, msg = userMobileVerifySMSProvider.get(phoneNumber = phoneNumber,
  3363. productName = agent.productName,
  3364. vendor = SysParas.get_sms_vendor(request.user.smsVendor))
  3365. if not status:
  3366. return JsonErrorResponse(description = msg)
  3367. else:
  3368. return JsonOkResponse()
  3369. else:
  3370. return JsonErrorResponse(description = u'您已正在领取')
  3371. @permission_required(ROLE.myuser)
  3372. def mobileVerify(request):
  3373. # type: (WSGIRequest)->JsonResponse
  3374. """
  3375. :param request:
  3376. :return:
  3377. """
  3378. payload = json.loads(request.body)
  3379. lc = payload.get('logicalCode')
  3380. onsaleId = payload.get('onsaleId')
  3381. phoneNumber = payload.get('phoneNumber')
  3382. code = payload.get('code')
  3383. userId = str(request.user.id)
  3384. key = '{user}{onsale}-lock'.format(user = userId, onsale = onsaleId)
  3385. with memcache_lock(key = key, value = '1', expire = 60) as acquired:
  3386. if acquired:
  3387. status, msg = userMobileVerifySMSProvider.verify(phoneNumber, code)
  3388. if not status:
  3389. return JsonErrorResponse(description = msg)
  3390. count = OnSaleRecord.objects.filter(onsaleId = onsaleId, userId = str(request.user.id)).count()
  3391. if count > 0:
  3392. return JsonResponse({"result": 0, "description": u'您已经免费体验过了哦,不能再免费体验了哦,您可以试试充值消费哦', "payload": {}})
  3393. try:
  3394. onsale = OnSale.objects.get(id = onsaleId)
  3395. except Exception as e:
  3396. logger.exception(e)
  3397. return JsonResponse({"result": 0, "description": u'推广活动已经下架,无法体验了哦', "payload": {}})
  3398. if onsale.status == 'stop':
  3399. return JsonResponse({"result": 0, "description": u'推广活动已经下架,无法体验了哦', "payload": {}})
  3400. duration = int(onsale.detailDict.get('duration')) * 60
  3401. dev = Device.get_dev_by_logicalCode(lc)
  3402. duration = int(onsale.detailDict.get('duration')) * 60
  3403. dev = Device.get_dev_by_logicalCode(lc) # type: DeviceDict
  3404. box = ActionDeviceBuilder.create_action_device(dev)
  3405. try:
  3406. box.send_dev_runtime(request.user.openId, duration)
  3407. except ServiceException, e:
  3408. return JsonErrorResponse(description = e.result.get('description'))
  3409. except Exception, e:
  3410. return JsonErrorResponse(description = u'系统异常,请您重试')
  3411. # 增加一条活动
  3412. try:
  3413. OnSaleRecord(
  3414. onsaleId = onsaleId,
  3415. userId = str(request.user.id),
  3416. nickName = request.user.nickname,
  3417. addedTime = datetime.datetime.now(),
  3418. onsaleDetail = {'duration': int(onsale.detailDict.get('duration')),
  3419. 'phoneNumber': phoneNumber}
  3420. ).save()
  3421. except Exception as e:
  3422. logger.exception('update record for onsale record error=%s' % (e,))
  3423. return JsonOkResponse(description = u'服务开始啦!您可以体验啦')
  3424. else:
  3425. return JsonErrorResponse(description = u'您已领取福利')
  3426. @error_tolerate(nil = DefaultJsonErrorResponse, logger = logger)
  3427. def test(request):
  3428. return JsonOkResponse()
  3429. @error_tolerate(nil = DefaultJsonErrorResponse, logger = logger)
  3430. def getCurrentOrder(request):
  3431. # type: (WSGIRequest)->JsonResponse
  3432. """
  3433. 获取目前用户目前订单的情况,给予用户下面操作的指示
  3434. :param request:
  3435. :return:
  3436. """
  3437. devNo = request.GET.get('devNo')
  3438. startKey = request.GET.get('startKey')
  3439. if not startKey:
  3440. return JsonErrorResponse(description = u'未找到启动key')
  3441. def get_response(orderProcessing, succeeded, desc = '', record = None):
  3442. record = {} if record is None else record
  3443. return JsonOkResponse(
  3444. payload = {
  3445. 'orderProcessing': orderProcessing,
  3446. 'succeeded': succeeded,
  3447. 'desc': desc,
  3448. 'record': record
  3449. }
  3450. )
  3451. #: 前台还需要发送请求轮询获取数据
  3452. not_yet = get_response(orderProcessing = True, succeeded = None)
  3453. #: 有错误或状态未知,前台可以停止轮询
  3454. stop_polling_unknown = get_response(orderProcessing = False, succeeded = False, desc = u'系统异常')
  3455. #: 确切知道启动成功
  3456. polling_finished_succeeded = lambda desc, record: get_response(orderProcessing = False,
  3457. succeeded = True,
  3458. desc = desc,
  3459. record = record)
  3460. #: 确切知道启动失败
  3461. polling_finished_failed = lambda desc, record: get_response(orderProcessing = False,
  3462. succeeded = False,
  3463. desc = desc,
  3464. record = record)
  3465. record = None
  3466. start_key_status = get_start_key_status(startKey) # type: dict
  3467. if start_key_status:
  3468. logger.debug('getCurrentOrder startKey = %s; status = %s; ts = %s' %
  3469. (startKey, start_key_status,
  3470. timestamp_to_dt(start_key_status['ts']).strftime(
  3471. '%Y-%m-%d %H:%M:%S') if 'ts' in start_key_status else ''))
  3472. state = start_key_status['state']
  3473. if state == START_DEVICE_STATUS.FAILURE or state == START_DEVICE_STATUS.TIMEOUT:
  3474. return polling_finished_failed(desc=start_key_status['reason'], record = None)
  3475. if state == START_DEVICE_STATUS.FINISHED:
  3476. if 'orderId' in start_key_status:
  3477. record = ConsumeRecord.objects(id = str(start_key_status['orderId'])).first() # type: ConsumeRecord
  3478. if not record:
  3479. logger.error('start key cache is not valid. value = {}'.format(str(start_key_status)))
  3480. return stop_polling_unknown
  3481. else:
  3482. logger.debug('start key status is {}'.format(state))
  3483. # 如果查过2分钟还没有结果,直接检查订单
  3484. exp = long(request.GET.get('exp', 0))
  3485. if exp < 2 * 60 * 1000:
  3486. return not_yet
  3487. else:
  3488. logger.debug('too long to get result. try to query record.')
  3489. if not record:
  3490. record = ConsumeRecord.objects(startKey = startKey).first() # type: Optional[ConsumeRecord]
  3491. if not record:
  3492. logger.error('cache and record are null, startKey = {}'.format(startKey))
  3493. return not_yet
  3494. if record.status in [ConsumeRecord.Status.WAITING, ConsumeRecord.Status.CREATED]:
  3495. return not_yet
  3496. dev = Device.get_dev(devNo) # type: DeviceDict
  3497. if not dev:
  3498. logger.error('cannot find device by devNo(%s))' % (devNo,))
  3499. return stop_polling_unknown
  3500. if record.isNormal:
  3501. #: 表明应用服务器并未发现异常,但是还是有可能实际场景失败,比如吃币,所以需要给用户良好的指导和要求其上传证据。并返回币数以便上分
  3502. return polling_finished_succeeded(
  3503. desc = u'您已成功启动设备。如果有疑问,请点击右下角"设备无反应"按钮',
  3504. record = {'coins': record.coin, 'detailLink': record.deail_link(dev), "isIns": record.insId}
  3505. )
  3506. else:
  3507. #: 设备服务器与设备连接失败(超时 etc,.)需要记录失败场景,同时保证用户不扣币,前台则给予提示其重试
  3508. return polling_finished_failed(
  3509. desc = record.errorDesc,
  3510. record = {'coins': record.coin, 'detailLink': record.deail_link(dev)}
  3511. )
  3512. @permission_required(ROLE.myuser)
  3513. def getOrderStatus(request):
  3514. # type: (WSGIRequest)->JsonResponse
  3515. """
  3516. 蓝牙获取订单状态
  3517. :param request:
  3518. :return:
  3519. """
  3520. payload = json.loads(request.body)
  3521. try:
  3522. order_id = str(payload.get('orderId'))
  3523. if OrderCacheMgr(order_id, cls_name = RechargeRecord.__name__).has_done():
  3524. record = RechargeRecord.objects(id = str(payload.get('orderId'))).first() # type: RechargeRecord
  3525. if record.is_success:
  3526. return JsonResponse({'result': 1, 'description': '', 'payload': {'status': 'success'}})
  3527. else:
  3528. return JsonResponse({'result': 1, 'description': '', 'payload': {'status': 'fail'}})
  3529. else:
  3530. return JsonResponse({'result': 1, 'description': '', 'payload': {'status': 'nop'}})
  3531. except Exception as e:
  3532. logger.exception(e)
  3533. return JsonResponse({'result': 1, 'description': '', 'payload': {'status': 'nop'}})
  3534. @permission_required(ROLE.myuser)
  3535. def pressButton(request):
  3536. # type: (WSGIRequest)->JsonResponse
  3537. payload = json.loads(request.body)
  3538. button_name = payload.get('button')
  3539. value = payload.get('value')
  3540. lc = payload.get('logicalCode')
  3541. dev = Device.get_dev_by_logicalCode(lc)
  3542. smartBox = ActionDeviceBuilder.create_action_device(dev)
  3543. try:
  3544. devInfo = smartBox.press_button(button_name, value)
  3545. except ServiceException as e:
  3546. return JsonErrorResponse(description = e.result.get('description'))
  3547. except Exception as e:
  3548. logger.exception('cannot get_port_status, error=%s' % (str(e),))
  3549. return JsonErrorResponse(description = u'未知错误')
  3550. return JsonResponse({"result": 1, "description": '', "payload": devInfo})
  3551. @permission_required(ROLE.myuser)
  3552. def changeVolume(request):
  3553. # type: (WSGIRequest)->JsonResponse
  3554. payload = json.loads(request.body)
  3555. logical_volume = payload.get('logicalCode')
  3556. volume = payload.get('value')
  3557. dev = Device.get_dev_by_logicalCode(logical_volume)
  3558. smart_box = ActionDeviceBuilder.create_action_device(dev)
  3559. try:
  3560. result = smart_box.changeVolume(volume)
  3561. return JsonResponse({"result": 1, "description": '', "payload": result})
  3562. except ServiceException as e:
  3563. return JsonErrorResponse(description = e.result.get('description'))
  3564. except AttributeError as e:
  3565. return JsonErrorResponse(description = u'暂时不支持该功能')
  3566. except Exception as e:
  3567. logger.exception('cannot changeVolume, error=%s' % (str(e),))
  3568. return JsonErrorResponse(description = u'未知错误')
  3569. @record_operation_behavior()
  3570. @permission_required(ROLE.myuser)
  3571. def stopCountDown(request):
  3572. # type: (WSGIRequest)->JsonResponse
  3573. openId = str(request.user.openId)
  3574. payload = json.loads(request.body)
  3575. port = payload.get('chargeIndex', None)
  3576. devNo = Device.get_devNo_by_logicalCode(logicalCode = payload['logicalCode'])
  3577. devCtrInfo = Device.get_dev_control_cache(devNo = devNo)
  3578. orderNo = payload.get("orderNo")
  3579. # 如果设备本身停止后,有停止时间上报,系统会在停止事件中处理退费、通知事宜。这里要做的就是直接停止而已.
  3580. dev = Device.get_dev(devNo = devNo) # type: DeviceDict
  3581. groupId = str(dev.get("groupId"))
  3582. group = Group.get_group(groupId)
  3583. box = ActionDeviceBuilder.create_action_device(dev)
  3584. if box.isHaveStopEvent:
  3585. try:
  3586. if dev.devType["code"] in [Const.DEVICE_TYPE_CODE_CHARGE_WEIFULE_CAR,
  3587. Const.DEVICE_TYPE_CODE_CAR_WEIFULE_CHARGING_DOUB,
  3588. Const.DEVICE_TYPE_CODE_CAR_WEIFULE_21KW,
  3589. Const.DEVICE_TYPE_CODE_CAR_WEIFILE_HOME_JFPG,
  3590. Const.DEVICE_TYPE_CODE_CAR_WEIFILE_HOME_DOUB_JFPG,
  3591. Const.DEVICE_TYPE_CODE_CHANGING_SOCKET,
  3592. Const.DEVICE_TYPE_CODE_WEIFULE_TOUCH_PAD,
  3593. Const.DEVICE_TYPE_CODE_WEIFULE_ANJIAN,
  3594. ] or dev.support_reliable:
  3595. box.stop_by_order(port, orderNo)
  3596. else:
  3597. box.stop(port)
  3598. except ServiceException, e:
  3599. return JsonResponse({'result': 0, 'description': e.result.get('description'), 'payload': {}})
  3600. return JsonResponse({'result': 1, 'description': '', 'payload': {}})
  3601. # 没有停止事件的,需要在这里处理退费事宜
  3602. if port is None:
  3603. for ii in range(10):
  3604. try:
  3605. portInfo = devCtrInfo.get(str(ii + 1), None)
  3606. if portInfo is None:
  3607. continue
  3608. if portInfo.has_key('openId') and portInfo['openId'] == openId and portInfo['status'] in [
  3609. Const.DEV_WORK_STATUS_WORKING, Const.DEV_WORK_STATUS_PAUSE]:
  3610. port = str(ii + 1)
  3611. break
  3612. except Exception, e:
  3613. continue
  3614. with memcache_lock(key = start_device_lock_key(openId = openId), value = '1', expire = 360) as acquired:
  3615. if acquired:
  3616. if port is not None:
  3617. devCtrInfo = devCtrInfo.get(str(port), {})
  3618. totalFee = devCtrInfo.get('coins', None)
  3619. if totalFee is None:
  3620. logger.error('feedback coins error devNo=%s, totalFee=%s' % (devNo, totalFee))
  3621. return JsonResponse({"result": 0, "description": u'获取订购金额失败', "payload": {}})
  3622. totalTime = devCtrInfo.get('needTime', None)
  3623. if totalTime is None:
  3624. for _ in dev['washConfig'].values():
  3625. if totalFee == _['price']:
  3626. totalTime = int(_['time'])
  3627. try:
  3628. devInfo = box.stop(port)
  3629. except ServiceException, e:
  3630. return JsonResponse({'result': 0, 'description': e.result.get('description'), 'payload': {}})
  3631. if 'remainder_time' not in devInfo: # 有些情况,是不需要根据时间退费的,比如云快充的充电桩,会根据事件,直接结算
  3632. return JsonResponse({"result": 1, "description": '', "payload": ''})
  3633. remainderTime = devInfo['remainder_time']
  3634. # 更新内存缓存状态
  3635. if port is None:
  3636. Device.invalid_device_control_cache(devNo)
  3637. else:
  3638. ctrInfo = Device.get_dev_control_cache(devNo)
  3639. ctrInfo.update({str(port): {}})
  3640. Device.update_dev_control_cache(devNo, ctrInfo)
  3641. refundFee = box.calc_stop_back_coins(totalFee, remainderTime, totalTime)
  3642. backCoins = VirtualCoin(refundFee)
  3643. desc = u'共付款:%s元,预定时间为:%s分钟,剩余时间:%s' % (
  3644. totalFee, totalTime, remainderTime)
  3645. # 通知完成
  3646. user = MyUser.objects(openId = openId, groupId = groupId).first()
  3647. task_caller('report_to_user_via_wechat', openId = user.managerialOpenId, dealerId = dev['ownerId'],
  3648. templateName = 'service_complete',
  3649. **{
  3650. 'title': u'订购总时间为:%s分钟,剩余时间:%s分钟' % (
  3651. totalTime,
  3652. remainderTime),
  3653. 'service': u'服务(设备编号:%s,地址:%s)' % (
  3654. payload['logicalCode'], group['address']),
  3655. 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
  3656. 'remark': u'谢谢您的支持'
  3657. })
  3658. # 如果需要退款,计算退款数据.
  3659. if not dev.is_auto_refund:
  3660. ServiceProgress.update_progress_and_consume_rcd(
  3661. dev['ownerId'],
  3662. {'open_id': openId, 'device_imei': devNo, 'isFinished': False},
  3663. {'leftTime': remainderTime,
  3664. 'needTime': u'扫码订购%s分钟' % totalTime,
  3665. 'duration': totalTime - remainderTime}
  3666. )
  3667. else:
  3668. # 扫码退钱, 退到个人账号
  3669. user.incr_balance(backCoins)
  3670. # 添加一条充值记录
  3671. orderNo = str(uuid.uuid4())
  3672. try:
  3673. newRcd = RechargeRecord(orderNo = orderNo,
  3674. coins = backCoins, openId = openId, groupId = str(request.user.groupId),
  3675. devNo = devNo, logicalCode = payload['logicalCode'],
  3676. ownerId = dev['ownerId'],
  3677. groupName = group['groupName'], groupNumber = dev['groupNumber'],
  3678. address = group['address'], wxOrderNo = u'设备退币',
  3679. devTypeName = dev.devTypeName, nickname = '',
  3680. result = 'success', via = 'refund')
  3681. newRcd.save()
  3682. except Exception as e:
  3683. logger.exception('update record for feedback coins error=%s,orderNo=%s' % (e, orderNo))
  3684. ServiceProgress.update_progress_and_consume_rcd(
  3685. dev['ownerId'],
  3686. {'open_id': openId, 'device_imei': devNo, 'isFinished': False},
  3687. {'leftTime': remainderTime,
  3688. 'needTime': u'扫码订购%s分钟' % totalTime,
  3689. 'duration': totalTime - remainderTime}
  3690. )
  3691. task_caller('report_to_user_via_wechat', openId = user.managerialOpenId, dealerId = dev['ownerId'],
  3692. templateName = 'refund_coins',
  3693. **{
  3694. 'title': desc,
  3695. 'backCount': u'金币:%s' % backCoins,
  3696. 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
  3697. })
  3698. return JsonResponse({"result": 1, "description": '', "payload": ''})
  3699. @error_tolerate(nil=JsonErrorResponse(u"获取虚拟卡列表失败"))
  3700. @permission_required(ROLE.myuser)
  3701. def getCardTicketList(request): # type: (WSGIRequest)->JsonResponse
  3702. """
  3703. 获取虚拟卡的列表
  3704. """
  3705. pageIndex = int(request.GET.get('pageIndex', 1))
  3706. pageSize = int(request.GET.get('pageSize', 10))
  3707. invalid = int(request.GET.get("invalid", 0))
  3708. openId = request.user.openId
  3709. now_time = datetime.datetime.now()
  3710. filters = {"openIds": openId}
  3711. if invalid:
  3712. filters.update({"expiredTime__lt": now_time})
  3713. else:
  3714. filters.update({"expiredTime__gte": now_time})
  3715. vCards = UserVirtualCard.objects.filter(**filters)
  3716. total = vCards.count()
  3717. dataList = list()
  3718. for _vcard in vCards.skip((pageIndex - 1) * pageSize).limit(pageSize):
  3719. data = _vcard.to_dict()
  3720. # 检查是否需要续费
  3721. isNeedRenew, days = is_need_renew(_vcard)
  3722. if isNeedRenew:
  3723. data.update({'needRenew': True})
  3724. # 添加是否是卡主
  3725. data.update({"isOwner": _vcard.isOwner(request.user.openId)})
  3726. dataList.append(data)
  3727. return JsonOkResponse(payload={
  3728. 'total': total, 'pageSize': pageSize, 'dataList': dataList
  3729. })
  3730. @error_tolerate(nil=JsonErrorResponse(u"获取虚拟卡详情失败"))
  3731. @permission_required(ROLE.myuser)
  3732. def getCardTicket(request):
  3733. cardId = request.GET.get("cardId")
  3734. try:
  3735. card = UserVirtualCard.objects.get(id=cardId)
  3736. except DoesNotExist:
  3737. return JsonErrorResponse(description=u"获取虚拟卡详情失败")
  3738. payload = card.to_detail()
  3739. isNeedRenew, days = is_need_renew(card)
  3740. if isNeedRenew:
  3741. payload.update({'needRenew': True})
  3742. payload.update({
  3743. "isOwner": card.isOwner(request.user.openId),
  3744. "agentId": request.user.productAgentId
  3745. })
  3746. return JsonOkResponse(payload=payload)
  3747. @error_tolerate(nil = DefaultJsonErrorResponse, logger = logger)
  3748. @permission_required(ROLE.myuser)
  3749. def getUserVirtualCardByGroup(request):
  3750. """
  3751. 通过groupId查询该地址下有没有购买过虚拟卡
  3752. :param request:
  3753. :return:
  3754. """
  3755. groupId = request.GET.get("groupId")
  3756. if not groupId:
  3757. return JsonErrorResponse(u"查询错误")
  3758. # 如果没有通过地址数量的检查 则直接提示不能开卡
  3759. if not Group.check_virtual_card_number(groupId):
  3760. return JsonErrorResponse(description = u"该地址虚拟卡数量已经达到上限,请联系发卡经销商")
  3761. vCards = UserVirtualCard.objects.filter(
  3762. openIds__in = [request.user.openId],
  3763. groupIds__in = ['*', groupId],
  3764. expiredTime__gt = datetime.datetime.now()
  3765. )
  3766. vCardList = [str(vCard.cardNo) for vCard in vCards]
  3767. return JsonOkResponse(payload = {"vCardList": vCardList})
  3768. @permission_required(ROLE.myuser)
  3769. def getCardTicketTypeList(request):
  3770. # type: (WSGIRequest)->JsonResponse
  3771. groupId = request.GET.get('groupId', None)
  3772. if groupId is None:
  3773. return JsonErrorResponse(u'没有找到您的充值地址哦')
  3774. if not Group.check_virtual_card_number(groupId):
  3775. return JsonErrorResponse(description=u"该地址虚拟卡数量已经达到上限,请联系发卡经销商")
  3776. group = Group.get_group(groupId)
  3777. onlineCards = VirtualCard.objects.filter(
  3778. ownerId=group['ownerId'],
  3779. status=1,
  3780. groupIds__in=['*', groupId],
  3781. expiredTime__gt=datetime.datetime.now()
  3782. )
  3783. dataList = []
  3784. for obj in onlineCards:
  3785. data = obj.to_dict()
  3786. if '*' in obj.groupIds:
  3787. groups = [{'groupName': grp['groupName'], 'address': grp['address']} for grp in
  3788. Group.get_groups_by_group_ids(Group.get_group_ids_of_dealer(obj.ownerId)).values()]
  3789. else:
  3790. groups = [{'groupName': grp['groupName'], 'address': grp['address']} for grp in
  3791. Group.get_groups_by_group_ids(obj.groupIds).values()]
  3792. data["groups"] = groups
  3793. dataList.append(data)
  3794. return JsonOkResponse(payload={'dataList': dataList})
  3795. # 分享卡卷的链接
  3796. @permission_required(ROLE.myuser)
  3797. def getShareCardTicket(request):
  3798. # type: (WSGIRequest)->JsonResponse
  3799. vCardId = request.GET.get('cardId', None)
  3800. if vCardId is None:
  3801. return JsonResponse({"result": 0, "description": u'没有找到卡卷,可能该卡卷已经被卡主注销,无法共享', "payload": None})
  3802. try:
  3803. vCard = UserVirtualCard.objects.get(id = vCardId)
  3804. except DoesNotExist as e:
  3805. return JsonResponse({"result": 0, "description": u'没有找到卡卷,可能该卡卷已经被卡主注销,无法共享', "payload": None})
  3806. if len(vCard.openIds) > vCard.userLimit - 1:
  3807. return JsonResponse({"result": 0, "description": u'共享的人数已经达到卡的限制,您无法共享哦', "payload": None})
  3808. agentId = Dealer.get_dealer(vCard.dealerId).get('agentId', None)
  3809. if agentId is None:
  3810. return JsonResponse({"result": 0, "description": u'非法卡,您无法共享哦', "payload": None})
  3811. if request.user.agentId != agentId:
  3812. return JsonResponse({"result": 0, "description": u'非法卡,您无法共享哦', "payload": None})
  3813. if request.user.openId in vCard.openIds:
  3814. return JsonResponse({"result": 0, "description": u'您已经共享了此卡', "payload": None})
  3815. vCard.openIds.append(request.user.openId)
  3816. try:
  3817. vCard.save()
  3818. except Exception as e:
  3819. logger.info('save sharing card error=%s' % e)
  3820. return JsonResponse({"result": 0, "description": u'保存卡的信息异常,请您重试', "payload": None})
  3821. data = vCard.to_detail()
  3822. data.update({
  3823. "isOwner": vCard.isOwner(request.user.openId),
  3824. "agentId": request.user.productAgentId
  3825. })
  3826. return JsonResponse({"result": 1, "description": '', "payload": data})
  3827. @permission_required(ROLE.myuser)
  3828. def removeCardSharedMembers(request):
  3829. # type: (WSGIRequest)->JsonResponse
  3830. payload = json.loads(request.body)
  3831. vCardId = payload.get('cardId')
  3832. openId = payload.get('userId')
  3833. if vCardId is None:
  3834. return JsonResponse({"result": 0, "description": u'没有找到卡卷,可能该卡卷已经被注销,请您刷新页面后再重试', "payload": None})
  3835. try:
  3836. vCard = UserVirtualCard.objects.get(id = vCardId)
  3837. except DoesNotExist:
  3838. return JsonResponse({"result": 0, "description": u'没有找到卡卷,可能该卡卷已经被注销,请您刷新页面后再重试', "payload": None})
  3839. vCard.openIds.remove(openId)
  3840. try:
  3841. vCard.save()
  3842. except Exception as e:
  3843. logger.info('save sharing card error=%s' % e)
  3844. return JsonResponse({"result": 0, "description": u'保存卡的信息异常,请您重试', "payload": None})
  3845. return JsonResponse({"result": 1, "description": '', "payload": None})
  3846. @permission_required(ROLE.myuser)
  3847. def stopService(request):
  3848. # type: (WSGIRequest)->JsonResponse
  3849. payload = json.loads(request.body)
  3850. logicalCode = payload.get('logicalCode')
  3851. port = payload.get('port', None)
  3852. dev = Device.get_dev_by_l(logicalCode)
  3853. box = ActionDeviceBuilder.create_action_device(dev)
  3854. try:
  3855. box.stop(port)
  3856. except ServiceException, e:
  3857. return JsonResponse({'result': 0, 'description': e.result.get('description'), 'payload': {}})
  3858. return JsonResponse({'result': 1, 'description': '', 'payload': {}})
  3859. @permission_required(ROLE.myuser)
  3860. def toggleDeviceStatus(request):
  3861. # type: (WSGIRequest)->JsonResponse
  3862. payload = json.loads(request.body)
  3863. logicalCode = payload.get('logicalCode')
  3864. port = payload.get('chargeIndex', None)
  3865. isContinue = False if payload.get('targetStatus', None) == 'pause' else True
  3866. dev = Device.get_dev_by_l(logicalCode)
  3867. box = ActionDeviceBuilder.create_action_device(dev)
  3868. try:
  3869. result = box.pause(request.user.openId, isContinue, port)
  3870. return JsonResponse({'result': 1, 'description': '', 'payload': result})
  3871. except ServiceException, e:
  3872. return JsonResponse({'result': 0, 'description': e.result.get('description'), 'payload': {}})
  3873. @permission_required(ROLE.myuser)
  3874. def getDeviceSellItems(request):
  3875. payload = json.loads(request.body)
  3876. logicalCode = payload.get('logicalCode')
  3877. objs = Cell.objects.filter(logicalCode = logicalCode, itemStatus = 'full')
  3878. dataList = [{
  3879. 'cellNo': obj.cellNo, 'boardNo': obj.boardNo,
  3880. 'lockNo': obj.lockNo, 'itemTitle': obj.itemTitle,
  3881. 'itemDesc': obj.itemDesc, 'itemPicUrl': obj.itemPicUrl,
  3882. 'itemPrice': obj.itemPrice
  3883. } for obj in objs]
  3884. return JsonResponse({'result': 1, 'description': '', 'payload': {'dataList': dataList}})
  3885. @permission_required(ROLE.myuser)
  3886. def getDeviceCells(request):
  3887. logicalCode = request.GET.get('logicalCode')
  3888. objs = Cell.objects.filter(logicalCode = logicalCode)
  3889. dev = Device.get_dev_by_logicalCode(logicalCode)
  3890. box = ActionDeviceBuilder.create_action_device(dev)
  3891. lockStatusDict = box.get_all_lock_status()
  3892. dataList = [{'id': str(obj.id), 'cellNo': obj.cellNo, 'boardNo': obj.boardNo,
  3893. 'lockNo': obj.lockNo, 'itemTitle': obj.itemTitle,
  3894. 'itemDesc': obj.itemDesc, 'itemPicUrl': obj.itemPicUrl,
  3895. 'itemPrice': round(obj.itemPrice / 100.0, 2), 'lockStatus': lockStatusDict.get(obj.cellNo, 'close')}
  3896. for obj in objs if (lockStatusDict.get(obj.cellNo, 'close') == 'close' and obj.itemStatus != 'empty')]
  3897. return JsonResponse({'result': 1, 'description': '', 'payload': {'dataList': dataList}})
  3898. @permission_required(ROLE.myuser)
  3899. def updateUserActiveInfo(request):
  3900. """
  3901. 安骑换电用户 的身份信息上传接口
  3902. 需要信息 手机验证码 手机号码 身份验证信息 推荐人信息(非必须)
  3903. 推荐人
  3904. # 新添加了字段 phoneNumber
  3905. """
  3906. user = request.user # type: MyUser
  3907. if user.is_product_user():
  3908. return JsonErrorResponse(u"请先扫描设备")
  3909. active_info = MyUser.get_active_info(user.openId, agentId = user.agentId)
  3910. if active_info and active_info.get("isMember"):
  3911. return JsonErrorResponse(u"您已经完成实名认证,请勿重复")
  3912. payload = json.loads(request.body)
  3913. code = payload.get("code", "")
  3914. phoneNumber = payload.get("phoneNumber", "")
  3915. imgList = payload.get("imgList", [])
  3916. recommender = payload.get("recommender", "")
  3917. if phoneNumber:
  3918. if MyUser.objects.filter(
  3919. Q(phoneNumber = phoneNumber),
  3920. Q(agentId = request.user.agentId) | Q(productAgentId = request.user.productAgentId)
  3921. ):
  3922. return JsonErrorResponse(description = u"手机号码已经被注册!")
  3923. # 推荐人如果填写必须有效 并且非本人 并且激活
  3924. if recommender:
  3925. if not MyUser.objects.filter(
  3926. Q(phoneNumber = recommender),
  3927. Q(agentId = request.user.agentId) | Q(productAgentId = request.user.productAgentId)
  3928. ) or recommender == phoneNumber:
  3929. return JsonErrorResponse(u"无效的推荐人")
  3930. status, msg = userMobileVerifySMSProvider.verify(phoneNumber, code)
  3931. if not status:
  3932. return JsonErrorResponse(msg)
  3933. MyUser.set_active_info(
  3934. {"phoneNumber": phoneNumber,
  3935. "imgList": imgList,
  3936. "recommender": recommender,
  3937. "status": 1,
  3938. "createdTime": datetime.datetime.strftime(datetime.datetime.now(), "%Y-%m-%d %H:%M:%S")
  3939. },
  3940. openId = user.openId,
  3941. agentId = user.agentId,
  3942. groupId = user.groupId
  3943. )
  3944. return JsonOkResponse()
  3945. @permission_required(ROLE.myuser)
  3946. def getUserActiveInfo(request):
  3947. user = request.user
  3948. active_info = MyUser.get_active_info(user.openId, agentId = user.agentId)
  3949. status = active_info.get("status", "")
  3950. payload = {
  3951. "id": user.id,
  3952. "identifyUrl": active_info.get("identifyUrl", ""),
  3953. "recommender": active_info.get("recommender", ""),
  3954. "phoneNumber": active_info.get("phoneNumber", ""),
  3955. "status": status if status else 0,
  3956. "remarks": active_info.get("remarks", "")
  3957. }
  3958. return JsonResponse({"result": 1, "description": '', "payload": payload})
  3959. @permission_required(ROLE.myuser)
  3960. def getTelVerifyInfo(request):
  3961. user = request.user
  3962. status = 1 if user.phone else 0
  3963. return JsonResponse({"result": 1, "description": "", "payload": {"status": status}})
  3964. @permission_required(ROLE.myuser)
  3965. def updateTelVerifyInfo(request):
  3966. """
  3967. 绑定手机号码. 手机号码只是做为属性, 谁能获取验证码, 手机号码就是谁的
  3968. """
  3969. user = request.user
  3970. jsonData = json.loads(request.body)
  3971. phoneNumber = jsonData.get("phoneNumber", "")
  3972. code = jsonData.get("code", "")
  3973. # 首先校验 短信验证码
  3974. status, msg = userMobileVerifySMSProvider.verify(phoneNumber, code)
  3975. if not status:
  3976. return JsonErrorResponse(msg)
  3977. try:
  3978. user.phone = phoneNumber
  3979. except Exception as e:
  3980. logger.exception(e)
  3981. return JsonErrorResponse(description=u"手机号码绑定失败,请刷新重试")
  3982. return JsonOkResponse(description=u"绑定成功")
  3983. @permission_required(ROLE.myuser)
  3984. def sendActiveSmsCode(request):
  3985. """
  3986. 安骑换电用户 获取手机验证码 手机号码
  3987. """
  3988. user = request.user
  3989. payload = json.loads(request.body)
  3990. phoneNumber = payload.get("phoneNumber", "")
  3991. # phoneNumber 唯一
  3992. checkUser = MyUser.objects.filter(
  3993. Q(phoneNumber = phoneNumber),
  3994. Q(agentId = request.user.agentId) | Q(productAgentId = request.user.productAgentId)
  3995. ).first()
  3996. if checkUser and checkUser.gateway == user.gateway:
  3997. return JsonErrorResponse(u"该号码已经被注册")
  3998. agent = Agent.objects.get(id = user.agentId)
  3999. status, msg = userMobileVerifySMSProvider.get(phoneNumber = phoneNumber,
  4000. productName = agent.productName,
  4001. vendor = SysParas.get_sms_vendor(request.user.smsVendor),
  4002. openId = user.openId)
  4003. if not status:
  4004. return JsonErrorResponse(description = msg)
  4005. else:
  4006. return JsonOkResponse()
  4007. @error_tolerate(logger = logger, nil = JsonErrorResponse(u'上传身份文件图片存储失败,请重新试试'))
  4008. @permission_required(ROLE.myuser)
  4009. def UploadIdentify(request):
  4010. """
  4011. 用户上传身份验证
  4012. """
  4013. files = request.FILES.getlist('file')
  4014. if not len(files):
  4015. return JsonResponse({'result': 0, 'description': u'未知的身份文件信息,请重新试试', 'payload': {}})
  4016. uploader = AliOssFileUploader(inputFile = request.FILES.getlist('file')[0], uploadType = 'identify')
  4017. logger.info('[uploadItemPic] %s is being used' % (repr(uploader),))
  4018. try:
  4019. outputUrl = uploader.upload()
  4020. return JsonResponse({'result': 1, 'description': '', 'payload': outputUrl})
  4021. except InvalidFileSize, e:
  4022. logger.info(
  4023. '%s(id=%s)\'s uploaded file reached limit' % (request.user.__class__.__name__, str(request.user.id),))
  4024. return JsonResponse({'result': 0, 'description': e.message, 'payload': {}})
  4025. except InvalidFileName, e:
  4026. logger.info(
  4027. '%s(id=%s)\'s uploaded file name is not legal' % (request.user.__class__.__name__, str(request.user.id),))
  4028. return JsonResponse({'result': 0, 'description': e.message, 'payload': {}})
  4029. @permission_required(ROLE.myuser)
  4030. def UserActiveIntercepter(request):
  4031. """
  4032. 安骑用户 拦截器 身份认证未通过的用户
  4033. """
  4034. user = request.user
  4035. active_info = MyUser.get_active_info(openId = user.openId, agentId = user.agentId)
  4036. isMember = active_info.get("isMember", False)
  4037. return JsonOkResponse(payload = {"isMember": int(isMember)})
  4038. @permission_required(ROLE.myuser)
  4039. def DeviceTrack(request):
  4040. """
  4041. 电池电压、位置信息 存在位置信息
  4042. """
  4043. # TODO 数据库分库整改
  4044. # 获取用户的最后一次serverProcess 从中获取用户电池的IMEI
  4045. # API查询电池信息
  4046. # 返回信息
  4047. user = request.user
  4048. active_info = MyUser.get_active_info(openId = user.openId, agentId = user.agentId)
  4049. status = active_info.get("status", 0)
  4050. if status != 2: # 完成身份认证的用户状态是2
  4051. return JsonErrorResponse(u"请先完成身份认证信息")
  4052. # 找出换电柜的使用记录 并且拿到的电池的编号不为-1
  4053. record = ConsumeRecord.objects.filter(
  4054. openId = user.openId,
  4055. servicedInfo__newBatteryImei__exists = True,
  4056. servicedInfo__newBatteryImei__ne = "-1"
  4057. ).order_by("-dateTimeAdded").first()
  4058. if not record:
  4059. return JsonErrorResponse(u"未获取到有效电池信息")
  4060. battery = record.servicedInfo.get("newBatteryImei")
  4061. try:
  4062. result = batteryInfo(battery)
  4063. except Exception as e:
  4064. logger.info("get battery info error ,reason is : %s" % e)
  4065. return JsonErrorResponse(u"网络故障,获取电池信息失败")
  4066. batInfo = result.get(battery)
  4067. if not batInfo:
  4068. return JsonErrorResponse(u"电池编号错误")
  4069. lng = batInfo.get("lng")
  4070. lat = batInfo.get("lat")
  4071. lng, lat = coordinateHandler(lng, lat)
  4072. payload = {
  4073. "total": 1,
  4074. "items": [
  4075. {
  4076. "lng": lng,
  4077. "lat": lat,
  4078. "remarks": u"当前电池电压信息是%s" % batInfo.get("voltage"),
  4079. }
  4080. ]
  4081. }
  4082. return JsonOkResponse(payload = payload)
  4083. @error_tolerate(logger=logger)
  4084. @permission_required(ROLE.myuser)
  4085. # @ServerSwitch.payment_switch('系统维护升级中,请稍后重试')
  4086. def payGateway(request):
  4087. # type: (WSGIRequest)->HttpResponse
  4088. """
  4089. 用户请求充值
  4090. 两层机制保证订单不被重复处理。
  4091. 1、用户订单创建后,在cache塞一个值为0的key;在收到回调或者查询到状态后,对这个key加1。如果返回新值为2则代表已经有处理过。
  4092. 2、如果cache失效,那么返回值为None。这个时候需要判断RechargeRecord的update结果,如果有修改,则代表没处理;否则已经处理过
  4093. :param request:
  4094. :return:
  4095. """
  4096. from apps.web.common.transaction.pay import PayPullUpFactoryIntf
  4097. class PayPullUpFactory(PayPullUpFactoryIntf):
  4098. @classmethod
  4099. def create_by_alipay(cls, payment_gateway, payParam, record):
  4100. current_user = payParam.curUser
  4101. open_id = current_user.get_bound_pay_openid(payment_gateway.bound_openid_key)
  4102. pull_up_cls = PayManager().get_pull_up(payment_gateway.pay_app_type)
  4103. return pull_up_cls(open_id, payment_gateway, record, **{
  4104. 'showAd': payParam.showAd,
  4105. 'notifyUrl': PAY_NOTIFY_URL.ALI_PAY_BACK
  4106. })
  4107. @classmethod
  4108. def create_by_wechat(cls, payment_gateway, payParam, record):
  4109. current_user = payParam.curUser
  4110. open_id = current_user.get_bound_pay_openid(payment_gateway.bound_openid_key)
  4111. pull_up_cls = PayManager().get_pull_up(payment_gateway.pay_app_type)
  4112. return pull_up_cls(open_id, payment_gateway, record, **{
  4113. 'showAd': payParam.showAd,
  4114. 'notifyUrl': PAY_NOTIFY_URL.WECHAT_PAY_BACK
  4115. })
  4116. @classmethod
  4117. def create(cls, payment_gateway, record, **payload):
  4118. payParam = payload.get('payParam')
  4119. if payment_gateway.pay_app_type == PayAppType.ALIPAY:
  4120. return cls.create_by_alipay(payment_gateway, payParam, record)
  4121. elif payment_gateway.pay_app_type == PayAppType.WECHAT:
  4122. return cls.create_by_wechat(payment_gateway, payParam, record)
  4123. else:
  4124. raise UserServerException(u'不支持的支付方式')
  4125. try:
  4126. logger.info('----{user} unified order----'.format(user=repr(request.user)))
  4127. payParam = PayParam(request) # type: PayParam
  4128. payParam.call_check()
  4129. payment_gateway = payParam.payGateway
  4130. if not payment_gateway:
  4131. raise UserServerException(u'第三方支付配置错误,请联系平台客服(1001)')
  4132. record = BUILDER_MAP.get(payParam.recordBuilderKey)(payParam) # type: RechargeRecord
  4133. from apps.web.common.transaction.pay import PayPullUp
  4134. pull_up = PayPullUp.create(PayPullUpFactory, payment_gateway, record, **{'payParam': payParam})
  4135. response = pull_up.do()
  4136. if 'startKey' in payParam.attachParas:
  4137. set_start_key_status(payParam.attachParas['startKey'], START_DEVICE_STATUS.PAYING)
  4138. return response
  4139. except InterceptException as e:
  4140. logger.debug(e.redirect)
  4141. return JsonResponse({
  4142. 'result': ErrorCode.LOGIN_VERIFY,
  4143. 'payload': {
  4144. 'redirect': e.redirect
  4145. }
  4146. })
  4147. except ServiceException as e:
  4148. logger.error(str(e))
  4149. return JsonResponse(e.result)
  4150. except UserServerException as e:
  4151. logger.error(e.message)
  4152. return JsonErrorResponse(e.message)
  4153. except AliException as e:
  4154. logger.error(str(e))
  4155. return JsonErrorResponse(description=e.message)
  4156. except Exception as e:
  4157. logger.exception(e)
  4158. return JsonErrorResponse(description=u'系统错误,请重试')
  4159. finally:
  4160. logger.info('----{user} unified order over----'.format(user=repr(request.user)))
  4161. @error_tolerate(logger = logger)
  4162. @permission_required(ROLE.myuser)
  4163. def setMyUserDetail(request):
  4164. user = request.user # type: MyUser
  4165. payload = json.loads(request.body)
  4166. ownerId = payload.pop('ownerId')
  4167. MyUserDetail.objects(openId = str(user.openId), dealerId = str(ownerId)).upsert_one(
  4168. openId = str(user.openId), dealerId = str(ownerId),
  4169. userName = payload.get('userName'), userPhone = payload.get('userPhone'),
  4170. userUnit = payload.get('userUnit'), userFloor = payload.get('userFloor'),
  4171. userRoom = payload.get('userRoom'))
  4172. return JsonResponse({'result': 1, 'description': 'SUCCESS', 'payload': {}})
  4173. @error_tolerate(logger = logger)
  4174. def payNotify(request, pay_app_type):
  4175. # type: (WSGIRequest, str)->JsonResponse
  4176. if pay_app_type == PayAppType.ALIPAY:
  4177. payload = request.POST.dict()
  4178. if 'refund_fee' in payload and 'gmt_refund' in payload:
  4179. notifier_cls = RefundManager().get_notifier(pay_app_type)
  4180. return notifier_cls(request, lambda filter: RefundMoneyRecord.get_record(**filter)).do(refund_post_pay)
  4181. recharge_cls_factory = lambda order_no: RechargeRecord
  4182. notifier_cls = PayManager().get_notifier(pay_app_type = pay_app_type)
  4183. return notifier_cls(request, recharge_cls_factory).do(post_pay)
  4184. @permission_required(ROLE.myuser)
  4185. def getFavoriteDevice(request):
  4186. pageIndex = int(request.GET.get('pageIndex', 1))
  4187. pageSize = int(request.GET.get('pageSize', 10))
  4188. devNoList = request.user.collectedDeviceList
  4189. devs = Device.get_dev_by_nos(devNoList, verbose = True)
  4190. dataList = []
  4191. for dev in devs.values():
  4192. dev.update({'type': dev['devType'].get('name', '')})
  4193. dataList.append(dev)
  4194. return JsonOkResponse(
  4195. payload = {'total': len(dataList), 'items': dataList[(pageIndex - 1) * pageSize:pageIndex * pageSize]})
  4196. @permission_required(ROLE.myuser)
  4197. def deleteFavoriteDevice(request):
  4198. payload = json.loads(request.body)
  4199. lcCodes = payload['logicalCodeList']
  4200. removeList = set()
  4201. for lcCode in lcCodes:
  4202. devNo = Device.get_devNo_by_logicalCode(lcCode)
  4203. removeList.add(devNo)
  4204. devNolist = set(request.user.collectedDeviceList)
  4205. request.user.collectedDeviceList = list(devNolist - removeList)
  4206. return JsonOkResponse()
  4207. @permission_required(ROLE.myuser)
  4208. def addFavoriteDevice(request):
  4209. payload = json.loads(request.body)
  4210. isFavorite = payload['favorite']
  4211. lcCode = payload['logicalCode']
  4212. devNo = Device.get_devNo_by_logicalCode(lcCode)
  4213. collectedDeviceList = request.user.collectedDeviceList
  4214. if isFavorite:
  4215. if devNo not in collectedDeviceList:
  4216. collectedDeviceList.append(devNo)
  4217. request.user.collectedDeviceList = collectedDeviceList
  4218. else:
  4219. return JsonOkResponse(description = u'该设备已经收藏啦')
  4220. else:
  4221. if devNo in collectedDeviceList:
  4222. collectedDeviceList.remove(devNo)
  4223. request.user.collectedDeviceList = collectedDeviceList
  4224. else:
  4225. return JsonOkResponse(description = u'该设备已经取消收藏啦')
  4226. return JsonOkResponse()
  4227. # 检查是否需要弹出加粉界面。1、需要获取监督号的openId。2、检查是否需要弹出加粉界面
  4228. # 监督号的入口也需要调用此函数,目的是找到客户应该登录的agentId。
  4229. @permission_required(ROLE.myuser)
  4230. def moniUserAccess(request):
  4231. logger.info('receive moniUserAccess')
  4232. # 目前只支持微信加粉
  4233. try:
  4234. href = request.GET.get('redirect')
  4235. moniAppId = request.GET.get('moniAppId', None)
  4236. if moniAppId is None:
  4237. agent = Agent.objects.get(id = request.user.agentId)
  4238. moniApp = agent.get_online_moni_app()
  4239. if not moniApp:
  4240. return ErrorResponseRedirect(error = cn(u'请您刷新下页面,重新点击试试'))
  4241. else:
  4242. try:
  4243. moniApp = MoniApp.get_collection().find({'appId': moniAppId})[0]
  4244. except Exception, e:
  4245. return ErrorResponseRedirect(error = cn(u'建议您从扫码页面关注公众号,这样才可以使用此公众号的服务哦'))
  4246. # 返回跳转页面
  4247. state = MoniUserAuthState(appId = moniApp['appId'], openId = request.user.openId, href = href)
  4248. wechatApp = WechatAuthApp(appid = moniApp['appId'], secret = moniApp['secret'])
  4249. bridge = WechatAuthBridge(wechatApp)
  4250. return ExternalResponseRedirect(
  4251. bridge.generate_auth_url_base_scope(redirect_uri = USER_AUTH_REDIRECT_URL.MONI_BASE,
  4252. payload = state.encode()))
  4253. except Exception, e:
  4254. logger.exception(e)
  4255. return ErrorResponseRedirect(error = cn(u'系统开小差了~~~,请您刷新下页面,重新点击试试'))
  4256. @permission_required(ROLE.myuser)
  4257. def checkPoint(request):
  4258. logger.info('checkPoint,receive,user openId=%s' % request.user.openId)
  4259. # 目前只支持微信加粉
  4260. if (not detect_wechat_client(request)):
  4261. logger.info('checkPoint,it is not wechat client')
  4262. return JsonOkResponse(payload = {'addFans': False, 'qrCode': ''})
  4263. try:
  4264. point = request.GET.get('point')
  4265. logicalCode = request.GET.get('logicalCode')
  4266. dev = Device.get_dev_by_logicalCode(logicalCode)
  4267. dealer = Dealer.objects(id = dev['ownerId']).get()
  4268. logger.info('checkPoint,user openId=%s,logicalCode=%s' % (request.user.openId, logicalCode))
  4269. # 检查经销商和代理商的开关
  4270. if dealer.moniAppCheckPointDict.has_key(point) and (not dealer.moniAppCheckPointDict[point]):
  4271. logger.info('checkPoint,moniappcheck point dealer is off,point')
  4272. return JsonOkResponse(payload = {'addFans': False, 'qrCode': ''})
  4273. agent = Agent.objects(id = dealer.agentId).get()
  4274. if agent.moniAppCheckPointDict.has_key(point) and (not agent.moniAppCheckPointDict[point]):
  4275. logger.info('checkPoint,moniappcheck point agent is off')
  4276. return JsonOkResponse(payload = {'addFans': False, 'qrCode': ''})
  4277. moniApp = agent.get_online_moni_app()
  4278. if not moniApp:
  4279. return JsonOkResponse(payload = {'addFans': False, 'qrCode': ''})
  4280. rcds = MoniUser.objects.filter(openId = request.user.openId, moniAppId = moniApp['appId'])
  4281. if rcds.count() == 0: # 一条记录都没有是,说明没有拿到对应数据
  4282. logger.info('checkPoint,can not find moniuser')
  4283. return JsonOkResponse(payload = {'addFans': False, 'qrCode': ''})
  4284. else:
  4285. moniUser = rcds.first()
  4286. if moniUser.isSubscribe:
  4287. return JsonOkResponse(payload = {'addFans': False, 'qrCode': ''})
  4288. else: # 如果没关注,可能存在用户通过其他手段提前关注了,要多重检查下
  4289. app = WechatAuthApp(appid = moniApp['appId'], secret = moniApp['secret'])
  4290. proxy = WechatClientProxy(app)
  4291. isSubGzh = proxy.is_subscribe_gzh(moniUser['moniOpenId'])
  4292. if isSubGzh:
  4293. moniUser.isSubscribe = True
  4294. moniUser.subPoint = point
  4295. moniUser.subLogicalCode = logicalCode
  4296. moniUser.subDealerId = str(dealer.id)
  4297. moniUser.subAgentId = str(agent.id)
  4298. moniUser.save()
  4299. return JsonOkResponse(payload = {'addFans': False, 'qrCode': ''})
  4300. else:
  4301. moniUser.subPoint = point
  4302. moniUser.subLogicalCode = logicalCode
  4303. moniUser.subDealerId = str(dealer.id)
  4304. moniUser.subAgentId = str(agent.id)
  4305. moniUser.save()
  4306. return JsonOkResponse(
  4307. payload = {'addFans': True, 'qrCode': moniApp['qrCode'], 'title': moniApp['title'],
  4308. 'desc': moniApp['desc']})
  4309. except Exception, e:
  4310. return JsonOkResponse(payload = {'addFans': False, 'qrCode': ''})
  4311. @permission_required(ROLE.myuser)
  4312. def isNeedAccessMoniApp(request):
  4313. logger.info('receive isNeedAccessMoniApp')
  4314. if (not detect_wechat_client(request)):
  4315. return JsonOkResponse(payload = {'isNeed': False})
  4316. try:
  4317. agent = Agent.objects(id = request.user.agentId).get()
  4318. # 如果代理商支持强制关注公众号,而且用户一天内才创建进来,为了体验好一点,这次就不要弹窗了
  4319. if agent.forceFollowGzh and (datetime.datetime.now() - request.user.dateTimeAdded).total_seconds() < 24 * 60 * 60:
  4320. return JsonOkResponse(payload = {'isNeed': False})
  4321. # 如果这个用户已经订阅了某个监督号,就直接返回
  4322. moniApp = agent.get_online_moni_app()
  4323. if not moniApp:
  4324. return JsonOkResponse(payload = {'isNeed': False})
  4325. moniUserCount = MoniUser.objects.filter(openId = request.user.openId, moniAppId = moniApp['appId']).count()
  4326. if moniUserCount == 0:
  4327. return JsonOkResponse(payload = {'isNeed': True})
  4328. return JsonOkResponse(payload = {'isNeed': False})
  4329. except Exception, e:
  4330. return JsonOkResponse(payload = {'isNeed': False})
  4331. @permission_required(ROLE.myuser)
  4332. def getComplaintList(request):
  4333. pageIndex = int(request.GET.get('pageIndex', 1))
  4334. pageSize = int(request.GET.get('pageSize', 10))
  4335. objs = Complaint.objects.filter(openId = request.user.openId)
  4336. dataList = []
  4337. total = objs.count()
  4338. for obj in objs.paginate(pageIndex = pageIndex, pageSize = pageSize):
  4339. dataList.append({
  4340. 'id': str(obj.id),
  4341. 'logicalCode': obj.logicalCode,
  4342. 'createdTime': obj.dateTimeAdded.strftime(Const.DATETIME_FMT),
  4343. 'handledTime': obj.handledTime.strftime(Const.DATETIME_FMT),
  4344. 'handledStatus': obj.handledStatus,
  4345. 'groupName': obj.groupName,
  4346. 'reason': obj.reason
  4347. })
  4348. return JsonOkResponse(payload = {'total': total, 'dataList': dataList})
  4349. def submitComplaint(request):
  4350. payload = json.loads(request.body)
  4351. # 首先产生一条投诉记录
  4352. logicalCode = payload.get('logicalCode')
  4353. orderNo = payload.get('orderNo')
  4354. reason = payload.get('reason')
  4355. order = ConsumeRecord.objects.get(orderNo = orderNo)
  4356. if order.logicalCode != logicalCode:
  4357. return JsonErrorResponse(description = u'设备的编码填写错误,请您检查下哦')
  4358. if Complaint.objects.filter(orderNo = orderNo).count() > 0:
  4359. return JsonErrorResponse(description = u'该订单已经投诉成功,不需要您重复投诉了哦')
  4360. newObj = Complaint(
  4361. openId = request.user.openId,
  4362. logicalCode = logicalCode,
  4363. groupName = order.groupName,
  4364. orderNo = orderNo,
  4365. reason = reason
  4366. )
  4367. newObj.save()
  4368. # 然后通知经销商
  4369. newMsg = DealerMessage(
  4370. ownerId = order.ownerId,
  4371. fromUser = u'系统平台',
  4372. messageType = 'complaint',
  4373. title = u'客户投诉',
  4374. desc = u'平台收到客户的投诉,请您尽快处理,如果收到投诉过多,系统会提醒设备用户,甚至禁用此设备。地址:%s,设备:%s,投诉原因:%s' % (
  4375. order.groupName, logicalCode, reason),
  4376. relatedInfo = {'complaintId': str(newObj.id)}
  4377. )
  4378. newMsg.save()
  4379. return JsonOkResponse()
  4380. @permission_required(ROLE.myuser)
  4381. @request_limit_by_user(operation='queryServicePhone', limit=10, period=2 * 60 * 60, logger=None)
  4382. def queryServicePhone(request):
  4383. """
  4384. 根据订单查询客服电话
  4385. :param request:
  4386. :return:
  4387. """
  4388. logicalCode = request.GET.get('logicalCode')
  4389. dealerIds = MyUser.get_dealer_ids(openId = request.user.openId, productAgentId = request.user.productAgentId)
  4390. device = Device.get_dev_by_logicalCode(logicalCode) # type: DeviceDict
  4391. if not device or device.ownerId not in dealerIds:
  4392. return JsonOkResponse(payload={})
  4393. if not device.owner:
  4394. logger.error('dealer<id={}> not exists.'.format(device.ownerId))
  4395. return JsonOkResponse(payload={})
  4396. return JsonOkResponse(payload=({'phone': device.owner.service_phone}))
  4397. @error_tolerate(nil = JsonErrorResponse(description = u'系统错误'), logger = logger)
  4398. @permission_required(ROLE.myuser)
  4399. def getAllFeature(request):
  4400. agent = Agent.objects.get(id = request.user.agentId)
  4401. if agent is None:
  4402. return JsonErrorResponse(description = u'代理商不存在')
  4403. else:
  4404. return JsonOkResponse(payload = {_: True for _ in agent.features})
  4405. @error_tolerate(nil = JsonErrorResponse(description = u'系统错误'), logger = logger)
  4406. @permission_required(ROLE.myuser)
  4407. def queryCardNo(request):
  4408. logicalCode = request.GET.get('logicalCode')
  4409. devNo = Device.get_devNo_by_logicalCode(logicalCode)
  4410. if devNo is None:
  4411. return JsonErrorResponse(description = u'未识别的设备编号')
  4412. cardNo = Card.get_dev_card_no(devNo)
  4413. if cardNo is None:
  4414. return JsonOkResponse(payload = {'cardNo': ''})
  4415. return JsonOkResponse(payload = {'cardNo': cardNo})
  4416. @error_tolerate(nil = JsonErrorResponse(description = u'系统错误'), logger = logger)
  4417. @permission_required(ROLE.myuser)
  4418. def prepareScanCard(request):
  4419. logicalCode = request.GET.get('logicalCode')
  4420. devNo = Device.get_devNo_by_logicalCode(logicalCode)
  4421. if devNo is None:
  4422. return JsonErrorResponse(description = u'未识别的设备编号')
  4423. Card.clear_dev_card_no(devNo)
  4424. return JsonOkResponse()
  4425. @error_tolerate(nil = JsonErrorResponse("系统错误"), logger = logger)
  4426. @permission_required(ROLE.myuser)
  4427. def checkUserConsumeOrder(request):
  4428. logicalCode = request.GET.get("logicalCode")
  4429. dev = Device.get_dev_by_logicalCode(logicalCode)
  4430. if not dev:
  4431. return JsonErrorResponse(u"未找到设备,请扫码重试")
  4432. box = ActionDeviceBuilder.create_action_device(dev)
  4433. if not hasattr(box, "check_user_consume_order"):
  4434. return JsonOkResponse()
  4435. status = box.check_user_consume_order()
  4436. return JsonResponse({"result": status})
  4437. @error_tolerate(nil = JsonErrorResponse("系统错误"), logger = logger)
  4438. @permission_required(ROLE.myuser)
  4439. def preJudgment(request):
  4440. """
  4441. 这个接口 无论如何不能抛出异常 前台规定
  4442. :param request:
  4443. :return:
  4444. """
  4445. logicalCode = request.GET.get("logicalCode")
  4446. dev = Device.get_dev_by_logicalCode(logicalCode)
  4447. if not dev:
  4448. return JsonErrorResponse(u"该设备不存在")
  4449. order = get_user_not_complete_order(request.user, dev.owner)
  4450. # 正常结果下的返回
  4451. if not order:
  4452. return JsonOkResponse()
  4453. if order.status == order.Status.RUNNING:
  4454. return JsonResponse({"result": ErrorCode.ORDER_RUNNING, "description": u"您有一笔正在进行的订单",
  4455. "payload": {'ownerId': order.ownerId, "orderId": str(order.id)}})
  4456. elif not order.isPaid:
  4457. return JsonResponse({"result": ErrorCode.ORDER_NEED_PAY, "description": u"你有一笔尚未支付的订单,请先完成支付,然后在使用设备",
  4458. "payload": {'ownerId': order.ownerId, "orderId": str(order.id)}})
  4459. # elif order.is_waitPay():
  4460. # return JsonResponse({"result": ErrorCode.ORDER_PAYING, "description": u"正在检查支付结果,请稍后",
  4461. # "payload": {'ownerId': order.ownerId, "orderId": str(order.id)}})
  4462. else:
  4463. return JsonResponse({"result": "2", "description": u"系统错误,请您稍后重试"})
  4464. @error_tolerate(nil = JsonErrorResponse("系统错误"), logger = logger)
  4465. @permission_required(ROLE.myuser)
  4466. def getCardBindUserStatus(request):
  4467. user = request.user
  4468. status = 1 if user.extra.get('campus_user_num', '') else 0
  4469. return JsonResponse({"result": 1, "description": "", "payload": {"status": status}})
  4470. @error_tolerate(nil = JsonErrorResponse("系统错误"), logger = logger)
  4471. @permission_required(ROLE.myuser)
  4472. def updateCardBindUserInfo(request):
  4473. user = request.user
  4474. jsonData = json.loads(request.body)
  4475. phoneNumber = str(jsonData.get("phoneNumber", "").strip())
  4476. code = jsonData.get("code", "")
  4477. campus_user_num = str(jsonData.get('userNo').strip())
  4478. userName = str(jsonData.get('userName').strip())
  4479. from apps.web.eventer.caiyi import config_dic
  4480. # 测试白名单
  4481. test_card = serviceCache.get('yc-num-{}'.format(campus_user_num))
  4482. if test_card:
  4483. userName = 'test'
  4484. campus_user_num = 'test001'
  4485. logger.debug('yc_test_card,to reg card!!!')
  4486. res = {'factoryFixId': '757996699'}
  4487. else:
  4488. # TODO 去服务器验证人员编号和手机号是否吻合
  4489. yc = YuChuanApi(**config_dic)
  4490. try:
  4491. res = yc.sql_get_user_info(campus_user_num)
  4492. user_phone = base64.encodestring(phoneNumber + '.00').strip()
  4493. if res['mobilePhone'] != user_phone or res['userName'] != userName:
  4494. return JsonErrorResponse(description = u'一卡通信息填写错误~,请您检查下哦')
  4495. except Exception as e:
  4496. return JsonErrorResponse(description = u'一卡通信息填写错误!!!,请您检查下哦')
  4497. card_no = str(res.get('factoryFixId')).replace('L', '')
  4498. if not card_no:
  4499. raise UserServerException(u'一卡通信息填写错误!!')
  4500. status, msg = userMobileVerifySMSProvider.verify(phoneNumber, code)
  4501. if not status:
  4502. return JsonErrorResponse(msg)
  4503. dic = {
  4504. "card_dealer": "宇川智能平台一卡通",
  4505. "campus_user_num": campus_user_num,
  4506. }
  4507. card = Card.objects.filter(cardNo = card_no, cardType = 'YuChuanCard').first() or Card.objects.create(
  4508. cardNo = card_no, agentId = user.agentId, phone = phoneNumber, remarks = '宇川一卡通',
  4509. productAgentId = user.productAgentId, cardName = userName, attachParas = dic, cardType = 'YuChuanCard',
  4510. nickName = user.nickname, openId = user.openId)
  4511. if card.openId == card_no or card.openId != user.openId: # 判断是否为刷卡注册入库,或则换微信绑定
  4512. card.openId = user.openId
  4513. card.nickName = user.nickname
  4514. card.phone = phoneNumber
  4515. card.save()
  4516. dic['card_no'] = card_no
  4517. user.phoneNumber = phoneNumber
  4518. user.extra = dic
  4519. user.save()
  4520. return JsonResponse({"result": 1, "description": "", "payload": {"status": 1}})
  4521. @error_tolerate(logger = logger, nil = JsonErrorResponse(description = u"获取卡金额失败"))
  4522. @permission_required(ROLE.myuser)
  4523. def getRemoteCardBalance(request):
  4524. """
  4525. 获取远程充值卡的金额
  4526. :param request:
  4527. :return:
  4528. """
  4529. logicalCode = request.GET.get("logicalCode")
  4530. dev = Device.get_dev_by_l(logicalCode)
  4531. if not dev:
  4532. return JsonErrorResponse(description = u"请先扫描设备")
  4533. box = ActionDeviceBuilder.create_action_device(dev)
  4534. if not hasattr(box, "get_remote_card_balance"):
  4535. return JsonErrorResponse(description = u"当前设备暂不支持充值卡")
  4536. try:
  4537. result = box.get_remote_card_balance()
  4538. except ServiceException as e:
  4539. return JsonErrorResponse(description = e.message.get("description"))
  4540. res = result.get("res")
  4541. if res == "02":
  4542. return JsonErrorResponse(description = u"请先将卡片置于设备上")
  4543. # 这个地方将用户的信息塞入进去
  4544. user = request.user
  4545. result.update({
  4546. "avatarUrl": user.avatar,
  4547. "openId": user.openId
  4548. })
  4549. # 然后再次塞入设备信息
  4550. result.update({
  4551. "devNo": dev.devNo,
  4552. "groupId": dev.groupId
  4553. })
  4554. packages = dev.get("washConfig", dict())
  4555. newPackages = list()
  4556. for _id, item in packages.items():
  4557. switch = item.get("switch", True)
  4558. if not switch:
  4559. continue
  4560. newPackages.append({
  4561. "id": _id,
  4562. "payAmount": item.get("price"),
  4563. "coins": item.get("coins")
  4564. })
  4565. result.update({"packages": newPackages})
  4566. return JsonOkResponse(payload = result)
  4567. @error_tolerate(logger = logger, nil = JsonOkResponse())
  4568. @permission_required(ROLE.myuser)
  4569. def getUserDisclaimer(request):
  4570. """
  4571. 获取用户的免责声明
  4572. 用户 用户进入系统第一次的时候需要阅读此协议并且 明确表示阅读 否则展示界面给用户
  4573. :param request:
  4574. :return:
  4575. """
  4576. productAgentId = request.user.productAgentId
  4577. disclaimer = Agent.get_disclaimer(productAgentId)
  4578. # 当用户阅读的声明版本与当前免责代理商的版本不一致 并且代理商的免责声明内容不为空的时候 前台需要展示免责声明
  4579. payload = {
  4580. "version": disclaimer.version,
  4581. "content": disclaimer.content
  4582. }
  4583. if not disclaimer.content:
  4584. payload = {}
  4585. return JsonOkResponse(payload = payload)
  4586. @error_tolerate(logger = logger, nil = JsonOkResponse())
  4587. @permission_required(ROLE.myuser)
  4588. def pauseUsingDevice(request):
  4589. payload = json.loads(request.body)
  4590. logicalCode = payload.get('logicalCode', '')
  4591. if logicalCode == '':
  4592. return JsonErrorResponse(description = u'参数错误(没有逻辑码)')
  4593. port = payload.get('chargeIndex', '')
  4594. if port == '':
  4595. return JsonErrorResponse(description = u'参数错误(没有端口号)')
  4596. dev = Device.get_dev_by_l(logicalCode)
  4597. portCache = Device.get_dev_control_cache(dev['devNo'])[str(port)]
  4598. if dev['devType']['code'] in ['1002121', '1002122']:
  4599. if portCache.get('pausePort', False) is True:
  4600. oper = '01'
  4601. else:
  4602. oper = '02'
  4603. else:
  4604. oper = '00'
  4605. smartBox = ActionDeviceBuilder.create_action_device(dev)
  4606. try:
  4607. smartBox.pauseToUseDevice(port, oper)
  4608. except Exception as e:
  4609. return JsonErrorResponse(description = u'操作失败')
  4610. return JsonOkResponse()
  4611. @error_tolerate(logger = logger, nil = ErrorResponseRedirect(error = u'微信授权失败,请刷新后重试'))
  4612. @permission_required(ROLE.myuser)
  4613. def gatewayEntry(request):
  4614. """
  4615. 再发起支付之前 获取一次用户的 payOpenId 然后重定向到用户的支付详情页面 并直接访问payGateway
  4616. :param request:
  4617. :return:
  4618. """
  4619. def get_pay_gateway_redirect(pp, adLink):
  4620. redirect = pp._request.GET.get("redirect")
  4621. info = {
  4622. 'params': pp._request.GET.get("params"),
  4623. 'goodsInfo': json.dumps(pp.goodsInfo)
  4624. }
  4625. if adLink:
  4626. info.update({'adLink': adLink})
  4627. url = before_frag_add_query(redirect, info)
  4628. logger.debug('redirect to client url is: {}'.format(url))
  4629. return FrontEndResponseRedirect(url)
  4630. def get_auth_redirect(pp, bridge, adLink):
  4631. authCode = pp._request.GET.get(bridge.auth_code_key)
  4632. if not authCode:
  4633. redirect_uri = concat_server_end_url(
  4634. uri = add_query('/user/pay/gatewayEntry', {
  4635. 'params': pp._request.GET.get("params"),
  4636. 'redirect': pp._request.GET.get("redirect")
  4637. })
  4638. )
  4639. logger.debug('base scope auth url is:{}'.format(redirect_uri))
  4640. return ExternalResponseRedirect(
  4641. bridge.generate_auth_url_base_scope(
  4642. redirect_uri = redirect_uri,
  4643. payload = {}
  4644. )
  4645. )
  4646. else:
  4647. userPayOpenId = bridge.authorize(authCode)
  4648. if not userPayOpenId:
  4649. return ErrorResponseRedirect(error = u'微信授权失败,请刷新后重试')
  4650. else:
  4651. pp.curUser.set_bound_pay_openid(bridge.bound_openid_key, openId = userPayOpenId)
  4652. pp.curUser.save()
  4653. return get_pay_gateway_redirect(pp, adLink)
  4654. def RCU_process(payParam):
  4655. code = request.GET.get('code')
  4656. if not code:
  4657. redirect = payParam._request.GET.get("redirect")
  4658. redirect_uri = concat_server_end_url(
  4659. uri = add_query('/user/pay/gatewayEntry', {
  4660. 'params': payParam._request.GET.get("params"),
  4661. 'redirect': redirect
  4662. })
  4663. )
  4664. url = add_query(pay_gateway.app.authCodeUrl, {'authCallBackUrl': redirect_uri})
  4665. logger.debug('base scope auth url is:{}'.format(redirect_uri))
  4666. return FrontEndResponseRedirect(url)
  4667. else:
  4668. redirect = payParam._request.GET.get("redirect")
  4669. info = {
  4670. 'params': payParam._request.GET.get("params"),
  4671. 'code': code,
  4672. 'goodsInfo': json.dumps(payParam.goodsInfo),
  4673. }
  4674. if adLink:
  4675. info.update({'adLink': adLink})
  4676. url = before_frag_add_query(redirect, info)
  4677. logger.debug('redirect to client url is: {}'.format(url))
  4678. return FrontEndResponseRedirect(url)
  4679. payParam = PayParam(request)
  4680. curUser = payParam.curUser
  4681. pay_gateway = payParam.payGateway
  4682. adLink = request.GET.get('adLink', None)
  4683. # 首先判断登录的平台 只有微信扫码的需要获取其支付的openId
  4684. if detect_wechat_client(request):
  4685. if pay_gateway.pay_app_type == PayAppType.WECHAT:
  4686. authBridge = WechatAuthBridge(pay_gateway.app)
  4687. payOpenId = curUser.get_bound_pay_openid(authBridge.bound_openid_key)
  4688. if payOpenId:
  4689. return get_pay_gateway_redirect(payParam, adLink)
  4690. else:
  4691. return get_auth_redirect(payParam, authBridge, adLink)
  4692. else:
  4693. return JsonErrorResponse(description = u"平台配置错误,请稍后再试")
  4694. # 支付宝平台登录
  4695. elif detect_alipay_client(request):
  4696. return get_pay_gateway_redirect(payParam, adLink)
  4697. # 其他平台暂时不支持
  4698. else:
  4699. return NotSupportedPlatformResponseRedirect()
  4700. @error_tolerate(logger = logger, nil = JsonErrorResponse(u"套餐获取失败"))
  4701. @permission_required(ROLE.myuser)
  4702. def getMonthlyPackage(request):
  4703. """
  4704. 获取包月的套餐
  4705. :param request:
  4706. :return:
  4707. """
  4708. devNo = Device.get_dev_no_from_request(request)
  4709. cardNo = request.GET.get("cardNo")
  4710. device = Device.get_dev(devNo)
  4711. card = Card.objects.filter(cardNo = cardNo, openId = request.user.openId,
  4712. productAgentId = request.user.productAgentId).first()
  4713. if device:
  4714. group = Group.get_dealer_group(dealerId = device.ownerId, id = device.groupId)
  4715. elif card:
  4716. group = Group.get_dealer_group(dealerId = card.dealerId, id = card.groupId)
  4717. else:
  4718. return JsonErrorResponse(description = u"获取套餐失败(1000),请刷新重试")
  4719. if not group:
  4720. return JsonErrorResponse(description = u"套餐获取失败(1001),请刷新重试")
  4721. monthPackage = group.monthlyRule
  4722. if not monthPackage:
  4723. return JsonOkResponse()
  4724. return JsonOkResponse(payload = {"dataList": [monthPackage.to_dict()]})
  4725. @error_tolerate(nil = JsonErrorResponse(u"续费失败,请重新尝试"), logger = logger)
  4726. @permission_required(ROLE.myuser)
  4727. def checkVirtualCardRenew(request):
  4728. """
  4729. 检查当前的虚拟卡是否可以续费
  4730. :param request:
  4731. :return:
  4732. """
  4733. cardId = request.GET.get("cardId")
  4734. if not cardId:
  4735. return JsonErrorResponse(description = u"未找到相应虚拟卡,请重试")
  4736. vCard = UserVirtualCard.objects.get(id = cardId)
  4737. if not Group.check_virtual_card_number(groupId = vCard.groupId):
  4738. return JsonErrorResponse(description = u"该地址虚拟卡数量已经达到上限,请联系发卡经销商")
  4739. return JsonOkResponse()
  4740. @error_tolerate(nil = JsonErrorResponse(u"获取失败,请重试"), logger = logger)
  4741. @permission_required(ROLE.myuser)
  4742. def getUserMonthlyPackage(request):
  4743. """
  4744. 获取用户的 包月套餐
  4745. :param request:
  4746. :return:
  4747. """
  4748. openId = request.user.openId
  4749. monthlyPackages = MonthlyPackage.get_user_all(openId)
  4750. dataList = [_package.to_dict() for _package in monthlyPackages]
  4751. return JsonOkResponse(payload = {"dataList": dataList})
  4752. @error_tolerate(nil = JsonErrorResponse(u"获取失败,请重试"), logger = logger)
  4753. @permission_required(ROLE.myuser)
  4754. def getMonthlyPackageUseDetail(request):
  4755. """
  4756. 获取 用户的使用详情
  4757. :param request:
  4758. :return:
  4759. """
  4760. monthlyPackageId = request.GET.get("monthlyPackageId")
  4761. pageIndex = int(request.GET.get("pageIndex", 1))
  4762. pageSize = int(request.GET.get("pageSize", 10))
  4763. monthlyPackage = MonthlyPackage.objects.get(id = monthlyPackageId)
  4764. useDetail = monthlyPackage.get_used_detail()
  4765. # 获取使用的总的数量 添加上订单的ID 方便前台跳转
  4766. total = len(useDetail)
  4767. result = useDetail[pageSize * (pageIndex - 1): pageSize * pageIndex]
  4768. orderNos = [_item.get("orderNo") for _item in result]
  4769. consumeRecords = ConsumeRecord.objects.filter(openId = request.user.openId, orderNo__in = orderNos).only("openId",
  4770. "orderNo",
  4771. "id",
  4772. "dateTimeAdded")
  4773. dataList = [
  4774. {"id": consume.id, "orderNo": consume.orderNo, "orderTime": consume.dateTimeAdded.strftime("%Y-%m-%d %H:%M:%S")}
  4775. for consume in consumeRecords
  4776. ]
  4777. return JsonOkResponse(payload = {"total": total, "dataList": dataList})
  4778. @error_tolerate(nil = JsonErrorResponse(u"获取失败,请重试"), logger = logger)
  4779. @permission_required(ROLE.myuser)
  4780. def supportPayment(request):
  4781. def get_dealer(request):
  4782. logicalCode = request.GET.get('logicalCode', None)
  4783. if logicalCode:
  4784. device = Device.get_dev_by_logicalCode(logicalCode)
  4785. if not device:
  4786. logger.info('can not find device. logicalCode={}'.format(logicalCode))
  4787. return None
  4788. else:
  4789. return device.owner
  4790. else:
  4791. groupId = request.GET.get('groupId', None)
  4792. if not groupId:
  4793. logger.info('can not find group. groupId={}'.format(groupId))
  4794. return None
  4795. else:
  4796. group = Group.get_group(groupId) # type: GroupDict
  4797. if not group:
  4798. logger.info('can not find group. groupId={}'.format(groupId))
  4799. return None
  4800. else:
  4801. return group.owner
  4802. dealer = get_dealer(request)
  4803. if dealer is None:
  4804. return JsonErrorResponse(description = u'该设备未注册,暂时无法使用支付宝或者微信支付, 请投币(1013)')
  4805. return JsonOkResponse(description = u'无商户配置')
  4806. @permission_required(ROLE.myuser)
  4807. def getAlipayAd(request):
  4808. """
  4809. 领取红包福利任务
  4810. :param request:
  4811. :return:
  4812. """
  4813. try:
  4814. user = request.user # type: MyUser
  4815. logicalCode = request.GET.get('logicalCode', '')
  4816. pageIndex = int(request.GET.get('pageIndex', 0))
  4817. pageSize = int(request.GET.get('pageSize', 10))
  4818. chargeIndex = request.GET.get('chargeIndex', '')
  4819. dev = Device.get_dev_by_l(logicalCode) # Type:DeviceDict
  4820. from apps.web.core.models import SystemSettings
  4821. if user.gateway != AppPlatformType.ALIPAY:
  4822. return JsonOkResponse(payload = {})
  4823. if not dev:
  4824. return JsonOkResponse(payload = {})
  4825. if not Redpack.can_use(dealer = dev.owner, devTypeCode = dev.devTypeCode):
  4826. return JsonOkResponse(payload = {})
  4827. if not DevRegToAli.objects.filter(logicalCode = logicalCode).first():
  4828. reg_result = DevRegToAli.reg_to_aliyun_v3(dev)
  4829. if not reg_result:
  4830. return JsonOkResponse()
  4831. if 'disable_alipay_ruhui' in dev.owner.features:
  4832. ruhui = {}
  4833. elif SystemSettings.disable_alipay_ruhui():
  4834. ruhui = {}
  4835. else:
  4836. # 判断是否为蓝牙. 蓝牙为老流程 串口充电桩为新流程
  4837. if dev.channelType == DeviceChannelType.Channel_BT:
  4838. showType = 'pop'
  4839. else:
  4840. # 1 确认显示方式
  4841. showType = 'footerTopRedpack'
  4842. group = dev.group
  4843. if group.get('beforeCharge'):
  4844. showType = 'pop'
  4845. if 'show_pop_ruhui' in dev.owner.features:
  4846. showType = 'pop'
  4847. elif 'show_top_ruhui' in dev.owner.features:
  4848. showType = 'top'
  4849. elif 'show_buttun_ruhui' in dev.owner.features:
  4850. showType = 'buttun'
  4851. # 2 请求 请求权益 创建红报
  4852. ruhui = RedpackBuilder.get_alipay_cpa_by_ruhui_v3(openId = user.openId, logicalCode = logicalCode,
  4853. chargeIndex = chargeIndex, showType = showType)
  4854. if ruhui:
  4855. # 地址组启动强制充值, 后面的页面需要弹窗 比较复杂直接改为弹窗流程
  4856. group = dev.group
  4857. if group.get('beforeCharge'):
  4858. ruhui = {'url': ruhui['url'], 'money': ruhui['money'], 'showType': ruhui['showType'],
  4859. 'urlId': ruhui['urlId']}
  4860. else:
  4861. pass
  4862. if 'disable_alipay_laxin' in dev.owner.features:
  4863. laxin = {}
  4864. elif SystemSettings.disable_alipay_laxin():
  4865. laxin = {}
  4866. else:
  4867. # 拉新
  4868. dataList = RedpackBuilder.get_alipay_cpa_by_laxin(openId = user.openId)
  4869. total = len(dataList)
  4870. if dataList:
  4871. dataList = dataList[(pageIndex - 1) * pageSize: pageIndex * pageSize]
  4872. laxin = {'dataList': dataList, 'total': total}
  4873. return JsonOkResponse(payload = {'laxin': laxin, 'ruhui': ruhui})
  4874. except Exception as e:
  4875. logger.exception(e)
  4876. return JsonOkResponse()
  4877. @error_tolerate(u"获取权益失败", logger=logger)
  4878. @permission_required(ROLE.myuser)
  4879. def getAlipayAdResult(request):
  4880. """
  4881. 领取红包福利任务
  4882. :param request:
  4883. :return:
  4884. """
  4885. alipayOpenId = request.GET.get('alipayOpenId')
  4886. taskId = request.GET.get('taskId')
  4887. taskType = request.GET.get('taskType')
  4888. openId = request.GET.get('alipayOpenId')
  4889. logicalCode = request.GET.get('logicalCode')
  4890. dev = Device.get_dev_by_logicalCode(logicalCode)
  4891. # 拉新结果处理
  4892. if taskId and alipayOpenId:
  4893. if RedpackBuilder.query_cpa_laxin_task_status(taskId, alipayOpenId):
  4894. redpack = RedpackBuilder.create_cpa_laxin_redpack(dev, taskId, openId, taskType)
  4895. if redpack:
  4896. return JsonOkResponse(payload={'showAmount': redpack.money.mongo_amount})
  4897. # 入会结果处理
  4898. redpackInfo = RedpackBuilder._pop_alipay_key(request.user.openId)
  4899. if redpackInfo:
  4900. showType = redpackInfo.get('showType')
  4901. if showType == 'pop':
  4902. return JsonOkResponse(payload={'showAmount': redpackInfo.get('money')})
  4903. return JsonResponse({'payload': {}})
  4904. @error_tolerate(u"获取权益失败", logger=logger)
  4905. @permission_required(ROLE.myuser)
  4906. def getMyRedpackList(request):
  4907. user = request.user # type: MyUser
  4908. pageIndex = int(request.GET.get('pageIndex', 0))
  4909. pageSize = int(request.GET.get('pageSize', 10))
  4910. dataList = Redpack.show_redpack(openId=user.openId)
  4911. total = len(dataList)
  4912. dataList = dataList[(pageIndex-1) * pageSize: pageIndex * pageSize]
  4913. return JsonOkResponse(payload={'dataList':dataList, 'total':total})
  4914. @error_tolerate(nil = JsonErrorResponse(description = u'显示用户信息错误'), logger = logger)
  4915. @permission_required(ROLE.myuser)
  4916. def getCurrentFeePara(request):
  4917. devNo = request.GET.get('devNo', None)
  4918. devObj = Device.objects.get(devNo = devNo)
  4919. feeMode = devObj.otherConf.get('feeMode',{})
  4920. timeRateList = []
  4921. shiduan = feeMode.get('shiduan','000000000000000000000000000000000000000000000000')
  4922. nowTime = datetime.datetime.now().strftime('%H:%M')
  4923. curFeeIndex = 0
  4924. for ii in range(48):
  4925. startHour = 0 + ii/2
  4926. startMin = '00' if ii%2==0 else '30'
  4927. endHour = startHour if ii%2==0 else startHour + 1
  4928. endMin = '30' if ii%2==0 else '00'
  4929. startTime = '%02d:%s' % (startHour,startMin)
  4930. endTime = '%02d:%s' % (endHour,endMin)
  4931. timeRateList.append({'startTime':startTime,'endTime':endTime,'rate':shiduan[ii]})
  4932. if nowTime >= startTime and nowTime <= endTime:
  4933. curFeeIndex = shiduan[ii]
  4934. result = {'top_price_rate':feeMode.get('jianFee',0),
  4935. 'top_price_service_rate':feeMode.get('jianServe',0),
  4936. 'peak_price_rate':feeMode.get('fengFee',0),
  4937. 'peak_price_service_rate':feeMode.get('fengServe',0),
  4938. 'normal_price_rate':feeMode.get('pingFee',0),
  4939. 'normal_price_service_rate':feeMode.get('pingServe',0),
  4940. 'valley_price_rate':feeMode.get('guFee',0),
  4941. 'valley_price_service_rate':feeMode.get('guServe',0),
  4942. 'jishunScale':feeMode.get('jishunScale',0),
  4943. 'timeRateList':timeRateList,
  4944. 'curFeeIndex':curFeeIndex}
  4945. return JsonOkResponse( payload = result )
  4946. @permission_required(ROLE.myuser)
  4947. def getNearbyCarStation(request):
  4948. # type: (WSGIRequest)->JsonResponse
  4949. try:
  4950. lng = float(request.GET.get('lng'))
  4951. lat = float(request.GET.get('lat'))
  4952. pageIndex = int(request.GET.get('pageIndex',1))
  4953. pageSize = int(request.GET.get('pageSize',10))
  4954. maxDistance = int(request.GET.get('distance', 5000))
  4955. logger.debug('now location. lat = %s; lng = %s' % (lat, lng))
  4956. if maxDistance > Const.NEAR_BY_MAX_DISTANCE:
  4957. maxDistance = Const.NEAR_BY_MAX_DISTANCE
  4958. if lng == 360 or lat == 360 or isnan(lng) or isnan(lat):
  4959. return JsonResponse({'result': 0, 'description': u'定位失败,请打开位置权限,刷新后重试'})
  4960. payload = getNearbyGroupsFromDB(lng, lat, pageIndex, pageSize, maxDistance, request.user.agentId,
  4961. request.GET.get('chargeType', 0))
  4962. return JsonResponse({'result': 1, 'description': '', 'payload': payload})
  4963. except Exception as e:
  4964. logger.exception(e)
  4965. return JsonResponse({'result': 0, 'description': u'获取附近设备失败'})
  4966. def getNearbyGroupsFromDB(lng, lat, pageIndex, pageSize, maxDistance, agentId, chargeType):
  4967. def hav(theta):
  4968. s = sin(theta / 2)
  4969. return s * s
  4970. def get_distance_hav(lat0, lng0, lat1, lng1):
  4971. if lat1 == 360 or lng1 == 360:
  4972. return -1
  4973. EARTH_RADIUS = 6371000
  4974. lat0 = radians(lat0)
  4975. lat1 = radians(lat1)
  4976. lng0 = radians(lng0)
  4977. lng1 = radians(lng1)
  4978. dlng = fabs(lng0 - lng1)
  4979. dlat = fabs(lat0 - lat1)
  4980. h = hav(dlat) + cos(lat0) * cos(lat1) * hav(dlng)
  4981. return int(2 * EARTH_RADIUS * asin(sqrt(h)))
  4982. if not agentId:
  4983. logger.error('agent is null.')
  4984. return {
  4985. 'total': 0,
  4986. 'items': []
  4987. }
  4988. dealers = Dealer.get_dealers(agentId)
  4989. if not dealers:
  4990. return {
  4991. 'total': 0,
  4992. 'items': []
  4993. }
  4994. queryDict = {
  4995. 'ownerId': {'$in': dealers},
  4996. 'StationStatus':50,# 站点状态必须是正常使用中的
  4997. 'location': {
  4998. '$near': {'$geometry': {'type': 'Point', 'coordinates': [lng, lat]},
  4999. '$maxDistance': maxDistance}}}
  5000. if chargeType != '0':
  5001. queryDict.update({'chargeType':int(chargeType)})
  5002. groups = SwapGroup.get_collection().find(queryDict)
  5003. items = []
  5004. for swapInfo in groups[(pageIndex - 1) * pageSize:pageIndex * pageSize]:
  5005. groupId = swapInfo['groupId']
  5006. group = Group.get_group(groupId)
  5007. if group is None:
  5008. continue
  5009. swaplng = float(swapInfo['location']['coordinates'][0])
  5010. swaplat = float(swapInfo['location']['coordinates'][1])
  5011. distance = get_distance_hav(lat, lng, swaplat, swaplng)
  5012. curFee = SwapGroup.get_cur_fee(swapInfo['PriceChargingInfo'])
  5013. if curFee is None:
  5014. continue
  5015. # 统计交流、直流端口的情况
  5016. statsDict = SwapGroup.get_stats(groupId)
  5017. info = {
  5018. 'lng': swaplng,
  5019. 'lat': swaplat,
  5020. 'Pictures':[{'IsCover':pic['IsCover'],'PicID':pic['PicID'],'Url':pic['Url'],'Title':pic['Title']} for pic in swapInfo.get('Pictures',[])],
  5021. 'PriceChargingInfo':[{'FeeTime':info['FeeTime'],'ElectricityFee':info['ElectricityFee'],'ServiceFee':info['ServiceFee']} for info in swapInfo['PriceChargingInfo']],
  5022. 'StationName':group['groupName'] if u'充电站' in group['groupName'] else u'%s充电站' % group['groupName'],
  5023. 'Address':group['address'],
  5024. 'Distance':distance,
  5025. 'BusineHours':swapInfo['BusineHours'],
  5026. 'acPortsSum':{'allPorts':statsDict['acAllPorts'],'usedPorts':statsDict['acUsedPorts'],'usePorts':statsDict['acUsePorts']},
  5027. 'dcPortsSum':{'allPorts':statsDict['dcAllPorts'],'usedPorts':statsDict['dcUsedPorts'],'usePorts':statsDict['dcUsePorts']},
  5028. 'exceptSum':{'offline':statsDict['offline'],'fault':statsDict['fault']},
  5029. 'curFee':{"curElecFee": curFee['curElecFee'], "curServiceFee": curFee['curServiceFee']},
  5030. 'ParkFee':swapInfo['ParkFee'],
  5031. 'tagDescList':SwapGroup.get_tag_desc_list_for_dict(swapInfo)
  5032. }
  5033. items.append(info)
  5034. payload = {
  5035. 'total': groups.count(),
  5036. 'items': items
  5037. }
  5038. return payload
  5039. @error_tolerate(logger = logger)
  5040. def refundOrderNotifier(request, pay_app_type):
  5041. """
  5042. 退款回调接口.
  5043. 微信和京东聚合单独指定回调
  5044. 支付宝支付和退款回调是一个
  5045. :param request:
  5046. :param pay_app_type:
  5047. :return:
  5048. """
  5049. assert pay_app_type in PayAppType.choices(), 'not support this pay app type({})'.format(pay_app_type)
  5050. notifier_cls = RefundManager().get_notifier(pay_app_type)
  5051. response = notifier_cls(request, lambda filter: RefundMoneyRecord.get_record(**filter)).do(refund_post_pay)
  5052. return response
  5053. @error_tolerate(logger=logger)
  5054. @permission_required(ROLE.myuser)
  5055. def cancelWaitPay(request):
  5056. """
  5057. 后支付用户拉起支付后, 没有输入密码 点击恢复到end状态 用于再次支付
  5058. """
  5059. payload = json.loads(request.body)
  5060. ownerId = payload.get('ownerId')
  5061. consumeRecordId = payload.get('consumeRecordId')
  5062. if not ownerId or not consumeRecordId:
  5063. return JsonErrorResponse(description='参数缺失, 请刷新后重试..')
  5064. order = ConsumeRecord.objects.filter(
  5065. id=consumeRecordId,
  5066. ownerId=ownerId
  5067. ).first() # type: ConsumeRecord
  5068. if not order:
  5069. return JsonErrorResponse(description='没有找到该订单')
  5070. try:
  5071. if order.status == order.Status.WAIT_PAY and not order.isPaid:
  5072. order.status = order.Status.END
  5073. order.save()
  5074. except Exception as e:
  5075. logger.exception("[cancelWaitPay] error = {}".format(e))
  5076. return JsonErrorResponse(description='参数错误')
  5077. return JsonOkResponse(payload={})
  5078. @permission_required(ROLE.myuser)
  5079. def cancelRechargeRecord(request):
  5080. """
  5081. 用户取消订单
  5082. """
  5083. try:
  5084. payload = json.loads(request.body)
  5085. orderNo = payload.get('orderNo')
  5086. record = RechargeRecord.objects(orderNo = orderNo).first() # type: RechargeRecord
  5087. if not record:
  5088. logger.warning('has no recharge record<orderNo={}>'.format(orderNo))
  5089. else:
  5090. record.cancel()
  5091. except Exception as e:
  5092. logger.exception(e)
  5093. finally:
  5094. return JsonOkResponse()