views.py 257 KB

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