
    iJ                     r   d dl mZmZmZmZ d dlmZmZ d dlZd dl	Z	d dl
Z
d dlZd dlZd dlZd dlmZmZ d dlmZmZmZmZ  ede      Zej.                  j1                  dd      Zej.                  j1                  d	d
      Zej.                  j1                  d      ej.                  j1                  d      dddddZd Zd,dZd-dZd ZejA                  ddg      d        Z!ejA                  ddg      d        Z"ejA                  ddg      d        Z#ejA                  ddg      d        Z$ejA                  d d!g      d"        Z%d# Z&ejA                  d$dg      d%        Z'ejA                  d&dg      d'        Z(ejA                  d(d!g      d)        Z)ejA                  d*d!g      d+        Z*y).    )	Blueprintrequestjsonifycurrent_app)login_requiredcurrent_userN)datetime	timedelta)dbSubscriptionPaymentMethodPaymentStatuspayments_v2	FRONT_URLzhttp://localhost:3001BACK_URLzhttp://localhost:8010TOSS_API_KEYTOSS_SECRET_KEYz#https://pay.toss.im/api/v2/paymentsz"https://pay.toss.im/api/v2/refundsz!https://pay.toss.im/api/v2/status"https://pay.toss.im/api/v2/execute)api_key
secret_keybase_url
refund_url
status_urlexecute_urlc                    	 |s t         j                  j                  d       yt        j                  |j                  d      | j                  d      t        j                        j                         }t        j                  ||      }|s%t         j                  j                  d| d|        |S # t        $ r5}t         j                  j                  dt        |              Y d}~yd}~ww xY w)	u    토스페이먼츠 서명 검증u@   TOSS_SECRET_KEY가 설정되지 않음 - 서명 검증 건너뜀Tzutf-8u2   토스페이먼츠 서명 검증 실패: expected=z, received=u)   토스페이먼츠 서명 검증 오류: NF)r   loggerwarninghmacnewencodehashlibsha256	hexdigestcompare_digesterror	Exceptionstr)payload	signaturer   expected_signatureis_valides         K/home/kdj-ubuntu1/mlink_AI_Server/mlink-backend/./src/routes/payments_v2.pyverify_toss_signaturer.      s    &&'ij "XXg&NN7#NN
 )+	 	 &&y2DE$$'YZlYmmx  zC  yD  &E  F   #LSQRVH!UVs   !B4 BB4 4	C2=+C--C2c                    	 | s|syt        j                  t        d   ddit        d   | |dd      }|j                  d	k(  r6|j	                         }t
        j                  j                  d
|        |dfS d|j                   d|j                   }t
        j                  j                  |       d|fS # t        $ r;}dt        |       }t
        j                  j                  |       d|fcY d}~S d}~ww xY w)u5   토스페이먼츠 결제 상태 조회 공통 함수)Nu*   payToken 또는 orderNo가 필요합니다r   Content-Typeapplication/jsonr   )apiKeypayTokenorderNo
   headersjsontimeout   u)   토스페이먼츠 상태 조회 성공: Nu)   토스페이먼츠 상태 조회 실패:  - u-   토스페이먼츠 상태 조회 중 오류: )requestspostTOSS_CONFIGstatus_coder8   r   r   infotextr%   r&   r'   )	pay_tokenorder_nostatus_responsestatus_data	error_msgr,   s         r-   fetch_toss_statusrG   7   s
   E"--%#%78%i0%#
 	
 &&#-)..0K##&OP[}$]^$$COD_D_C``cdsdxdxcyzI$$Y/?" CCF8L	  +Ys)   B8 A1B8 9>B8 8	C<0C71C<7C<c                    	 t        |       \  }}|rd|fS |j                  d      xs |j                  d      }t        |j                  d      xs |j                  d      xs d      }t        j                  j                  d| d	|        |d
k(  rA|dkD  r|n|}| ||dd}t        |      }	|	r#t        j                  j                  d|        yyt        j                  j                  d|        dd| fS # t        $ r;}
dt        |
       }t        j                  j                  |       d|fcY d}
~
S d}
~
ww xY w)u5   토스페이먼츠 결제 성공 처리 공통 함수rB   F	payStatusstatusamount	payAmountr   u%   토스페이먼츠 상태: payStatus=	, amount=PAY_COMPLETEDONE
paymentKeyorderIdrL   rK   u0   토스페이먼츠 결제 성공 처리 완료: )TN)Fu   구독 생성 실패u5   토스페이먼츠 상태가 PAY_COMPLETE가 아님: u   결제 미완료: u4   토스페이먼츠 결제 성공 처리 중 오류: N)rG   getintr   r   r@   create_toss_subscriptionr   r&   r'   r%   )rB   order_idrL   rE   r%   
pay_statuspaid_amountactual_amountpayment_resultsuccessr,   rF   s               r-   process_toss_payment_successr]   V   sZ   % .CU%< !__[1N[__X5N
+//(3X{{7SXWXY"G
|S\]h\i jk'+6?KM (#' 	N /~>G""''*Z[cZd(ef!4&&)^_i^j'kl.zl;;;  J3q6(S	  +i s)   D  B>D  (D   	E	0D?9E?Ec                     t        j                         }| dk(  r|t        d      z   S | dk(  r|t        d      z   S |t        d      z   S )u8   결제 주기에 따른 종료일 계산 (오늘 제외)monthly   daysyearlyil  )r	   nowr
   )billing_cyclerd   s     r-   calculate_end_daterf      sM    
,,.C	!YB'''	(	"YC(((YB'''    z/api/v2/payments/toss/preparePOST)methodsc                  	   	 t        j                         } | j                  d      }| j                  d      }| j                  d      }| j                  d      }| j                  di       }t        ||||g      st	        ddi      dfS t        |t              r|d	k  rt	        dd
i      dfS t        t        dd      }d| dt        j                         j                  dd  d| d| dt        t        j                         j                                
}ddi}t        |dz        }	||	z
  }
||d	|	|
|t        d   dddt          d| dt"         d| d}	 t%        j&                  t        d   ||d      }t(        j*                  j-                  d|j.                   d |j0                          |j.                  d!k(  rt|j3                         }|j                  d"      }t(        j*                  j-                  d#| d$|        t(        j*                  j-                  d%| d&|	 d'|
 d(       	 d	d)lm} d	d*lm} d+}|r2d|v r.	 |j=                  d      }t?        |      d,k\  rt        |d+         } ||d|||t@        jB                  d-||||t        j                         .      }tD        jF                  jI                  |       tD        jF                  jK                          t(        j*                  j-                  d/|jL                   d$|        t	        |||||j                  d1d2      d3d4      S t(        j*                  jU                  d5|j.                   d |j0                          t	        d6| |||d2dd4      S #  d+}Y xY w# tN        $ r5}t(        j*                  jQ                  d0tS        |              Y d}~d}~ww xY w# t$        jV                  jX                  $ rI}t(        j*                  jU                  d7tS        |              t	        d6| |||dd8      cY d}~S d}~ww xY w# tN        $ rD}t(        j*                  jQ                  d9tS        |              t	        dd:i      d;fcY d}~S d}~ww xY w)<u4   토스페이먼츠 결제 준비 - 결제 키 생성
product_idproduct_namerL   re   customer_infor%   u'   필수 정보가 누락되었습니다.  r   u$   유효하지 않은 금액입니다.id	test_usermlink__N   r0   r1   皙?r   Tz*https://pay.toss.im/payfront/demo/callbackV2z&/api/v2/payments/toss/success?orderno=z&status=PAY_COMPLETEuX   /payment/fail?code=PAY_PROCESS_CANCELED&message=결제가 취소되었습니다&orderId=)r4   rL   amountTaxFreeamountTaxable	amountVatproductDescr2   autoExecuteresultCallbackcallbackVersionretUrlretCancelUrlr   r5   r6   u   토스페이먼츠 API 응답: r;   r:   r3   u)   토스페이먼츠 결제 준비 완료: z - payToken: u   세금 정보 - 총액:    원, 과세:    원, 부가세:    원PaymentHistorySubscriptionStatus      toss_payments)user_idsubscription_idpayment_keyrW   rL   rK   payment_methodrk   rl   product_pricere   
created_atu&   임시 payment_history 생성 완료: u&   임시 payment_history 생성 실패: checkoutPage F)rR   rS   rL   	orderNamepayUrl
simulationuB   토스페이먼츠 API 오류 - 시뮬레이션 모드로 동작: sim_payment_key_uI   토스페이먼츠 API 호출 실패 - 시뮬레이션 모드로 동작: )rR   rS   rL   r   r   u)   토스페이먼츠 결제 준비 실패: u/   결제 준비 중 오류가 발생했습니다.  )-r   get_jsonrT   allr   
isinstancerU   getattrr   uuiduuid4hexr	   rd   	timestampr>   r   r   r<   r=   r   r   r@   r?   rA   r8   src.models.paymentr   src.models.subscriptionr   splitlenr   PENDINGr   sessionaddcommitro   r&   r%   r'   r   
exceptionsRequestException)datark   rl   rL   re   rm   r   rW   r7   amount_taxable
amount_vatpayment_dataresponseresultrB   r   r   partstemp_payment_historyr,   s                       r-   prepare_toss_paymentr      s   BZ!XXl+
xx/(#1"5JfmDEG%NOPRUUU &#&&A+G%KLMsRR ,k:G9Adjjl&6&6r&:%;1VHAm_TUVYZbZfZfZhZrZrZtVuUvw .

 Vc\*n,
  +#'!),J#!
"H
Rfg(k  *B  CK  BL  M
 R	}}J'!	H ##&EhFZFZE[[^_g_l_l^m$no##s*!"JJz2	""''*ST\S]]jktju(vw""''*B6(-XfWggw  yC  xD  DG  )H  I"`AJ  GH$8($,NN3$7E"5zQ*-eAh-
 ,: '(,$-!)%,44'6#-%1&,&3#+<<>,( JJNN#78JJ%%'&&++.TUiUlUlTmmz  |E  {F  -G  H "+'$!-$jj<"'    ""**-opx  qE  qE  pF  FI  JR  JW  JW  IX  ,Y  Z$4XJ"?'$!- "&   K(&'G* ! `&&,,/UVYZ[V\U]-^__`0 ""33 	&&)rsvwxsyrz'{| 0
;# )"  	  Z  #LSQRVH!UV!RSTVYYYZs   BP8 
#P8 .B*P8 CO 2N -N 4B N !O 6AO NN 	O+OO OO P5,>P0*P5+P8 0P55P8 8	R9R :R Rz/api/v2/payments/toss/callbackc                  `   	 t         j                  j                  d      xs t         j                  j                  d      } | rxt        j                  d      }t	        || t
        d         s.t        j                  j                  d       t        ddi      d	fS t        j                  j                  d
       nt        j                  j                  d       t        j                         }t        j                  j                  d|        |j                  d      }|j                  d      }|j                  d      }|j                  d      }|dk(  r|rt        |||      \  }}|r0t        j                  j                  d|        t        ddd      S t        j                  j                  d|        	 t        |||dd       t        ddd      S t        j                  j                  d|        t        ddd      S # t        $ rE}	t        j                  j                  dt!        |	              t        d|d      dfcY d}	~	S d}	~	ww xY w# t        $ rD}
t        j                  j                  dt!        |
              t        dd i      dfcY d}
~
S d}
~
ww xY w)!u.   토스페이먼츠 결제 완료 콜백 처리X-Toss-SignatureX-SignatureTas_textr   u.   토스페이먼츠 콜백 서명 검증 실패r%   Invalid signature  u.   토스페이먼츠 콜백 서명 검증 성공u=   토스페이먼츠 콜백 서명이 없음 - 검증 건너뜀u"   토스페이먼츠 콜백 수신: r4   rK   r3   rL   rO   u)   토스페이먼츠 콜백 처리 완료: u   결제 완료 처리됨)r\   messageu)   토스페이먼츠 콜백 처리 실패: rP   rQ   u"   결제 완료 처리됨 (fallback)u   콜백 fallback 처리 실패: Fr\   r%   r   Nu    결제 미완료 또는 오류: u   결제 미완료u/   콜백 처리 중 오류가 발생했습니다.)r   r7   rT   get_datar.   r>   r   r   r%   r   r@   r   r   r]   rV   r&   r'   )r)   r(   r   rW   rK   rB   rL   r\   r%   fallback_errorr,   s              r-   toss_payment_callbackr     ss   0ZOO''(:;aw?R?RS`?a	&&t4G()[=VW""(()YZ)<=>CC##$TU&&'fg!"DTF KL 88I&(#HHZ(	(#^#9)XvVNGU""''*ST\S](^_4<UVWW""((+TUZT[)\]
L,&/#+"("(	.  #t@d#eff
 &&)I$'PQu9KLMM ! L&&,,/NsSaObNc-de"uu#EFKKL  Z  #LSQRVH!UV!RSTVYYYZs[   BI  DI  "I  H /I  	I:III  II   	J-)9J("J-(J-z/api/v2/payments/toss/webhookc                     	 t         j                  j                  d      xs t         j                  j                  d      } | s.t        j                  j                  d       t        ddi      dfS t        j                  d      }t        || t        d	         s.t        j                  j                  d
       t        ddi      dfS t        j                  j                  d       t        j                         }t        j                  j                  d|        |j                  d      }|j                  d      }|j                  d      }|j                  d      }|dk(  rv|rtt        |||      \  }}|r1t        j                  j                  d|        t        ddi      dfS t        j                  j                  d|        t        d|i      dfS t        j                  j                  d| d|        t        ddi      dfS # t        $ rD}	t        j                  j                  dt        |	              t        ddi      dfcY d}	~	S d}	~	ww xY w)u7   토스페이먼츠 웹훅 처리 (서명 검증 포함)r   r   u*   토스페이먼츠 웹훅 서명이 없음r%   zMissing signaturer   Tr   r   u.   토스페이먼츠 웹훅 서명 검증 실패r   u.   토스페이먼츠 웹훅 서명 검증 성공u"   토스페이먼츠 웹훅 수신: r4   rK   r3   rL   rO   u)   토스페이먼츠 웹훅 처리 완료: r\   r:   u)   토스페이먼츠 웹훅 처리 실패: r   u)   토스페이먼츠 웹훅 무시: status=z, order_id=ignoredu-   토스페이먼츠 웹훅 처리 중 오류: zWebhook processing errorN)r   r7   rT   r   r   r%   r   r   r.   r>   r@   r   r]   r&   r'   )
r)   r(   r   rW   rK   rB   rL   r\   r%   r,   s
             r-   toss_payment_webhookr   J  s3   'COO''(:;aw?R?RS`?a	$$%QRG%89:C?? ""40$Wi\9RS$$%UVG%89:C?? PQ!"DTF KL 88I&(#HHZ(	(#^#9)XvVNGU""''*ST\S](^_)45s::""((+TUZT[)\]/0#55##&OPVxWbckbl$mnHi01366 C  #PQTUVQWPX!YZ!;<=sBBCs8   A/H 2AH 
C"H -0H 3H 	I9IIIz)/api/v2/payments/toss/create-subscriptionc                  &   	 t        j                         } | j                  d      }| j                  d      }t        j                  j                  d| d|        |r|st        ddi      dfS t        ||      \  }}|rt        dd	||d
      S t        j                  j                  d|        t        d|d      dfS # t        $ rD}t        j                  j                  dt        |              t        ddi      dfcY d}~S d}~ww xY w)u6   토스페이먼츠 결제 완료 후 구독 생성 APIr3   rS   u2   토스페이먼츠 구독 생성 요청: payToken=z
, orderId=r%   u'   payToken과 orderId가 필요합니다.rn   Tu0   구독이 성공적으로 생성되었습니다.)r\   r   r3   rS   u   구독 생성 실패: Fr   )   토스페이먼츠 구독 생성 실패: u/   구독 생성 중 오류가 발생했습니다.r   N)r   r   rT   r   r   r@   r   r]   r%   r&   r'   )r   rB   rW   r\   r%   r,   s         r-   create_toss_subscription_apir   v  s4   Z!HHZ(	88I&"TU^T__ijris tuG%NOPRUUU 6iJM%#	   $$'=eW%EF    
  Z  #LSQRVH!UV!RSTVYYYZs*   A-C 0 C 1C 	D9DDDz/api/v2/payments/toss/successGETc                  z	   	 t         j                  j                  d      } t         j                  j                  d      }t         j                  j                  d      }t        j                  j                  d|  d| d|        t        |       xr | j                  d      xs d| v }|s	 d	d
lm	} |j                  j                  | d      j                         }|r;|j                  r/|j                  }t        j                  j                  d|        n&t        j                  j                  d|         	 	 d.S 	 t#        |      \  }}|r1t%        |j                  d      xs |j                  d      xs d	      nd	}	|r"	 d	dlm	}m}
 |j                  j                  | |
j(                        j                         }|rx|
j*                  |_        t/        j0                         |_        t4        j6                  j9                          t        j                  j                  d|j:                   d|	        n"t        j                  j=                  d|         	 d	dlm }  || ||	       t        j                  j                  d       d|	dd |  d!| d"|	 d#tB         d$S tE        ||       \  }}|rd	}	 d	dlm	}m}
 |j                  j                  | |
j(                        j                         }|r1tG        |d%      r%|jH                  rt%        |jH                  xs d	      }d'|	dd(|  d!| d"|	 d)| d#tB         d$S t        j                  j                  d*|        d+| d,dfS # t        $ r9}t        j                  j                  dt!        |              	 	 d/cY d}~S d}~ww xY w# t        $ r-}t        j                  j                  d|        Y d}~Ud}~ww xY w# t        $ r6}t        j                  j                  dt!        |              Y d}~d}~ww xY w# t        $ r8}t        j                  j                  d&t!        |              d	}Y d}~@d}~ww xY w# t        $ r9}t        j                  j                  d-t!        |              	 	 d0cY d}~S d}~ww xY w)1uN   토스페이먼츠 결제 성공 페이지 - payToken 조회 후 구독 생성ordernor3   rK   u<   토스페이먼츠 결제 성공 페이지 접근: order_id=z, payToken=z	, status=mlink_usage__usage_r   r   pending)rW   rK   u)   payment_histories에서 payToken 조회: u*   payToken을 찾을 수 없음 - order_id: u   payToken 조회 실패: r   NrI   rL   rM   r   r   u1   [Settlement] PENDING → COMPLETED 갱신: ph_id=rN   u,   [Settlement] PENDING PH 미발견: order_id=)finish_settlement_then_refund)rW   rB   rL   uC   [Settlement] 사가 트리거 완료: finish_settlement_then_refundu&   [Settlement] 사가 트리거 실패: u   [Settlement] 처리 실패: u   
            <!DOCTYPE html>
            <html>
            <head><title>정산 결제 완료</title></head>
            <body>
                <h1>정산 결제가 완료되었습니다.</h1>
                <p>결제 금액: ₩,u   원</p>
                <script>
                    if (window.opener) {
                        window.opener.postMessage({
                            type: 'SETTLEMENT_SUCCESS',
                            orderId: 'z*',
                            payToken: 'z'',
                            amount: z
                        }, '*');
                        window.close();
                    } else {
                        window.location.href = 'zn/mypage';
                    }
                </script>
            </body>
            </html>
            carryover_credit_dayszcarryover days lookup failed: u   
            <!DOCTYPE html>
            <html>
            <head>
                <title>결제 완료</title>
            </head>
            <body>
                <h1>결제가 완료되었습니다.</h1>
                <p>결제 금액: ₩u   원</p>
                <script>
                    if (window.opener) {
                        window.opener.postMessage({
                            type: 'PAYMENT_SUCCESS',
                            orderId: 'z*,
                            creditDays: u   결제 성공 처리 실패: u   
            <!DOCTYPE html>
            <html>
            <head>
                <title>결제 오류</title>
            </head>
            <body>
                <h1>결제 처리 중 오류가 발생했습니다.</h1>
                <p>오류: ut   </p>
                <p>고객센터에 문의해주세요.</p>
            </body>
            </html>
            u:   토스페이먼츠 결제 성공 페이지 처리 실패: )u  
                    <!DOCTYPE html>
                    <html>
                    <head>
                        <title>결제 오류</title>
                    </head>
                    <body>
                        <h1>결제 정보를 찾을 수 없습니다.</h1>
                        <p>고객센터에 문의해주세요.</p>
                    </body>
                    </html>
                    rn   )u{  
                <!DOCTYPE html>
                <html>
                <head>
                    <title>결제 오류</title>
                </head>
                <body>
                    <h1>결제 처리 중 오류가 발생했습니다.</h1>
                    <p>고객센터에 문의해주세요.</p>
                </body>
                </html>
                r   )u#  
        <!DOCTYPE html>
        <html>
        <head>
            <title>결제 오류</title>
        </head>
        <body>
            <h1>결제 처리 중 오류가 발생했습니다.</h1>
            <p>고객센터에 문의해주세요.</p>
        </body>
        </html>
        r   )%r   argsrT   r   r   r@   bool
startswithr   r   query	filter_byfirstr   r%   r&   r'   rG   rU   r   r   	COMPLETEDrK   r	   rd   
updated_atr   r   r   ro   r    src.services.cancel_orchestratorr   r   r]   hasattrr   )rW   rB   rK   is_settlementr   payment_historyr,   rE   rr   rY   PHStatusphr   saga_errr\   r%   carryover_daystemp_phs                     r-   toss_payment_successr     s   p<<##I.LL$$Z0	!!(+"^_g^hhst}s~  H  IO  HP  !Q  	R XiH,?,?,O,hS\`hSh &="0"6"6"@"@%$ #A # %'  
 #'B'B / ; ;I&&++.WXaWb,cd&&,,/YZbYc-de    e@ +Y?Q]hc+//(3X{{7SXWXYno RX#))33XhN^N^3_eeg ( 2 2BI$,LLNBMJJ%%'&&++._`b`e`e_ffop{o|,}~&&..1]^f]g/hib^18yalm&&++,qr& '2!_ 5'
 (0j 1((1{ 3%%0M 21 2; <# 2 6iJN#X(..88(S[ScSc8djjlww0GHWMjMj%()F)F)K!%LN
& '2!_ 5'
 (0j 1((1{ 3%%0M 2))7(8 91 2; <) 6 $$'DUG%LM "7 #  _  ""((+CCF8)LM  J ! b&&,,/UV^U_-`aab  R""((+GAx)PQQRN  #""((+I#a&)RS!"#\    #]^abc^d]e!fg	  	s   B+Q8 .BM4 AQ8 CO2 %0N9 Q8 ,Q8  A0P4 0Q8 
)Q8 4	N6=.N1+N6,Q8 1N66Q8 9	O/"O*$O2 *O//O2 2	P1;+P,&Q8 ,P11Q8 4	Q5=-Q0*Q8 0Q55Q8 8	R:.R5/R:5R:c                 X   	 ddl m}m} ddlm} t
        j                  j                  d|         | j                  d      }| j                  d      }| j                  d      }| j                  dd	      }d
}|r2d|v r.	 |j                  d      }	t        |	      dk\  rt        |	d
         }t        j                  j                  |j                   |j"                  |j$                  |j&                  |j(                  |j*                        j-                  |j.                  |k(  |j0                  |j2                  k(        j5                         }
d}	 t        j                  j                  |j*                        j-                  |j.                  |k(  |j0                  |j2                  k(        j5                         }|r|d   rt        |d   xs d      }|
r8|
\  }}}}}}t
        j                  j                  d| d| d| d| d| 
       n+d}d}|}d}d}d}t
        j                  j7                  d       |r|}n3d}|r/d|v r+	 |j                  d      }	t        |	      dk\  r|	d   }|dv r|}t:        j                  j=                  ||j>                        j5                         }d }|rTt
        j                  j                  d|j@                          |dkD  rt
        j                  j                  d |        tC        jD                         }||_#        ||_$        |} ||tK        d
!      z
  |      }|tK        |!      z   }t
        j                  j                  d"|jF                   d#| d$|        nPt
        j                  j                  d%|j@                          |jF                  }|tK        d
!      z   } |||      }|dkD  rt||_        tL        jN                  |_(        ||_)        tU        |      |_+        t9        |      |_        ||_,        ||_#        ||_-        tC        jD                         |_$        |}n0||_        ||_#        ||_-        tC        jD                         |_$        |}|dk(  rd&nd'} |dAi d(|d)|j@                  d*|d+|d|d|j\                  d,d-d.|d/|d0|d1|d2||z   d3|d4|d5|d6|d7tC        jD                         }t        j                  j_                  |       ntC        jD                         } ||tK        d
!      z
  |      } |dkD  r| tK        |!      z   } t;        |||j>                  tL        jN                  |tU        |      t9        |      || | tC        jD                         tC        jD                         8      }t        j                  j_                  |       |dk(  rd&nd'} |dAi d(|d)dd*|d+|d|d|j\                  d,d-d.|d/|d0|d1|d2||z   d3|d4| d5|d6|d7tC        jD                         }t        j                  j_                  |       t        j                  ja                          |j@                  |_1        	 dd9l2m3}! |!j                  j                  |      }"|"rd:|"_4        t        j                  jk                          t
        j                  j                  d<|j@                   d=| d|        y># t        $ r d
}Y Tw xY w# t        $ r8}t
        j                  j7                  dt9        |              d}Y d}~kd}~ww xY w# t        $ r6}t
        j                  j7                  dt9        |              Y d}~d}~ww xY w# t        $ r6}t
        j                  j7                  d;t9        |              Y d}~#d}~ww xY w# t        $ rS}t
        j                  jm                  d?t9        |              t        j                  jo                          Y d}~y@d}~ww xY w)Bu9   토스페이먼츠 결제 성공 시 구독 생성/연장r   r   r   u)   토스페이먼츠 구독 생성 시작: rR   rS   rL   rK   rP   r   rq   rr   r   u   carryover days 조회 스킵: Nu   PENDING PH 추출: product_id=z, name=z, price=z, cycle=z, carryover_days=M   Basicu2   PENDING PaymentHistory 없음 — 기본값 사용r_      )r_   rc   u-   주문 ID에서 billing_cycle 추출 실패: )r   rK   c                 2    |dk(  rdnd}| t        |      z   S )Nr_      m  ra   )r
   )base_dtcyclerb   s      r-   _add_cycle_daysz1create_toss_subscription.<locals>._add_cycle_days  s     )+2DYD111rg   u$   기존 활성 구독 처리: sub_id=u%   플랜 변경 감지: carryover_days=ra   u'   플랜 변경: 기존 구독 종료일=u   , 새 플랜 시작일=u   , 새 플랜 종료일=u   기간 연장: sub_id=r   r   r   r   r   rW   r   r   rk   rl   r   re   subscription_dayssubscription_start_datesubscription_end_dater   carryover_credit_amountr   )r   rk   rK   r   
payment_idrL   re   
start_dateend_datenext_billing_dater   r   )Userrole_prou$   역할 업데이트 실패(무시): u$   구독 생성/연장 완료: sub_id=z
, user_id=Tr   F )8r   r   r   r   r   r   r   r@   rT   r   r   rU   r&   r   r   r   rk   rl   r   re   r   r   filterrW   rK   r   r   r   r'   r   r   ACTIVEro   r	   rd   r   r   r
   r   TOSS_PAYMENTSr   r   floatrL   r   r   r   r   flushr   src.models.userr   roler   r%   rollback)#r[   r   r   r   r   rW   rL   rK   r   r   ph_rowr   	carry_rowr,   rk   rl   r   ph_cycler   r   re   maybe_cycleexistingr   todaynew_start_datenew_end_datecurrent_endsubscriptionr   r   r   r   r   us#                                      r-   rV   rV   M  s   hP> 	"KNK[ \] %((6$((3$((2$((6: H, s+u:?!%(mG **"""--"//"00"00"::"88 6.11X=(//83C3CCE57 	 
	)).*N*NO &!8!8H!D!/!6!6(:J:J!JL%'  Yq\!$Yq\%6Q!7 pvmJmX?VXm##0GL>QYZgYhhpqypz  {L  Mb  Lc  d
 J"L"MH$%!&'#&&'[\ $M%MH0i$NN3/E5zQ&+Dk&*??,7M
  %%//%,, 0 
 %' 		2
 ##&J8;;-$XY!""''*OP^O_(`a  %*!&+# "'.uya7H/H-X  ,i^.LL""''*QRZRcRcQdd{  }K  |L  Lc  dp  cq  )r  s ""''*@(NO&//!,ya/@!@.{MJ !&0#*7*E*E'&1#"'-),]);&&4#$0!-9*&.lln#' '1#$0!-9*&.lln#' '4y&@c  , ( "	
   ))  / & * , , #4n"D )7 '3 '<  )@!" $<<>#B& JJNN2 "J(iQ6G)GWH!#i^&DD'%)00,::&V}!-0%!"*#<<>#<<>L JJNN<( '4y&@c  $ ( "	
   ))  / & * , , #4n"D )3 '/ '<  )@!" $<<>#B& JJNN2JJ!-B\0JJNN7+'AF
 	

"F|FWWabiajj{  }K  |L  !M  	N]  4  	&&)GAx'PQN	@ ! i&&..1^_bcd_e^f/ghhi\  \""**-QRUVWRXQY+Z[[\    #LSQRVH!UV


s   A=_  -[3 -B$_ B\ A2_ 	*]	 3P_ 8*^ "A_ 3\>_ \_ 	]-];_ ]_ 		^+^=_ ^_ 	_
+_?_ _

_ 	`)A	`$$`)z/api/v2/payments/refundc            
         	 t        j                         } | j                  d      }| j                  d      }| j                  dd      }|r|st        ddd      dfS d	d
l}d |j
                         j                  d
d  }t        |dz        }||z
  }t        d   |||d	||d	|d	}t        j                  t        d   ddi|      }	|	j                  dk(  rm|	j                         }
t        j                  j                  d|
        t        j                  j                  d| d| d| d       t        d||||dd      S t        j                  j!                  d|	j                   d|	j"                          t        dd|	j"                   d      dfS # t$        $ rE}t        j                  j!                  d t'        |              t        dd!d      d"fcY d
}~S d
}~ww xY w)#u    토스페이먼츠 환불 처리r3   rL   reasonu   반품 취소Fu-   payToken과 환불 금액이 필요합니다.r   rn   r   Nrefund_   rt   r   )	r2   r3   refundNorL   rv   rw   rx   amountServiceFeer	  r   r0   r1   )r7   r8   r:   u"   토스페이먼츠 환불 성공: u   환불 세금 정보 - 총액: r   r   r   Tu0   환불이 성공적으로 처리되었습니다.)r\   	refund_norL   r   r   r   u"   토스페이먼츠 환불 실패: r;   u   환불 처리 실패: u)   토스페이먼츠 환불 처리 실패: u/   환불 처리 중 오류가 발생했습니다.r   )r   r   rT   r   r   r   r   rU   r>   r<   r=   r?   r8   r   r   r@   r%   rA   r&   r'   )r   rB   refund_amountr	  r   r  refund_amount_taxablerefund_amount_vatrefund_datar   r   r,   s               r-   refund_paymentr  <  sS   A!HHZ(	*(O4 H    	jdjjl..s345	 !$MC$7 8),AA "),!!#2* !

 ==%#%78
 3&]]_F##&H$QR##&Em_Tabwax  yI  J[  I\  \_  %`  a&'"7/M   $$'I(J^J^I__bckcpcpbq%rs 1(--A   
    #LSQRVH!UVF
   	s,   AF C'F AF 	G*%:G%G*%G*z/api/v2/payments/toss/executec                     t        j                         } | j                  d      }|st        ddi      dfS t	        j
                  dddit        d   |d	d
      }t        j                  j                  d|j                   d|j                          |j                  dk7  rt        d|j                  d      dfS |j                         }t        d|d      S )ur   
    결제 승인(Execute): PAY_APPROVED 상태의 결제건을 최종 승인.
    req: { payToken: string }
    r3   r%   u   payToken이 필요합니다.rn   r   r0   r1   r   )r2   r3   r5   r6   zExecute resp:  r:   u   승인 실패)r%   rawT)r\   r   )r   r   rT   r   r<   r=   r>   r   r   r@   r?   rA   r8   )r   rB   rr   s       r-   execute_toss_paymentr    s     D$I!?@A3FF,!34!),!
 	A nQ]]O1QVVHEF}}@A3FFVVXFtv677rg   z/api/v2/payments/toss/statusc                  >   t         j                  j                  d      xs t         j                  j                  d      } t         j                  j                  d      }|s| st        ddi      dfS t	        ||       \  }}|rt        d|i      dfS t        |      S )uB   토스페이먼츠 결제 상태 조회 API (공통 함수 사용)r4   r   r3   r%   u   payToken 또는 orderNo 필요rn   rB   rC   r   r   rT   r   rG   )rC   rB   rE   r%   s       r-   status_toss_paymentr    s     ||	*Igll.>.>y.IH  ,IX!ABCSHH +YRK'(#--;rg   z/api/payments/statusc                     t         j                  j                  d      xs@ t         j                  j                  d      xs t         j                  j                  d      } t         j                  j                  d      }| s|st        ddd      dfS t	        || 	      \  }}|rt        d|d      d
fS |xs i j                  d      xs |xs i j                  d      }d}|dk(  rd}n|dv rd}t        d|d      d
fS )u   
    프론트 레거시 호환:
    /api/payments/status?orderId=... -> { success: bool, status: 'COMPLETED'|'PENDING'|'FAILED' }
    rS   r   r4   r3   Fu   orderId 또는 payToken 필요r   rn   r  r:   rJ   rK   r   rO   r   )
PAY_CANCELCANCELEDFAILEDFAILr   T)r\   rK   r  )rW   rB   r   errpay_statmappeds         r-   legacy_status_aliasr%    s     ||	*hgll.>.>y.IhW\\M]M]^gMhH  ,II53STUWZZZ!IIID#
5378#==
,J0@0@0JHF>!	A	Atv67<<rg   )NN)N)+flaskr   r   r   r   flask_loginr   r   osr   r<   base64r   r!   r	   r
   r   r   r   r   r   __name__payments_v2_bpenvironrT   r   r   r>   r.   rG   r]   rf   router   r   r   r   r   rV   r  r  r  r%  r   rg   r-   <module>r.     s,   : : 4 	      ( R R=(3JJNN;(?@	JJNN:(?@ zz~~n-**..!2356576>' R	( 5xHDZ IDZL 6I2Z J2Zh 5xH)C I)CV AF8TZ UZB 5wGr Hrhj^ /&BC CCP 5xH8 I8< 4ugF  G   ,ug>= ?=rg   