kltn21110 commited on
Commit
9dc6e20
·
verified ·
1 Parent(s): ad17e66

Upload RefundService.py

Browse files
Files changed (1) hide show
  1. service/RefundService.py +224 -0
service/RefundService.py ADDED
@@ -0,0 +1,224 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel
2
+ import uuid, hmac, hashlib, requests
3
+
4
+ # --- Thông tin định danh ---
5
+ PARTNER_CODE = "MOMO"
6
+ ACCESS_KEY = "F8BBA842ECF85"
7
+ SECRET_KEY = "K951B6PE1waDMi640xX08PD3vg6EkVlz"
8
+
9
+ # --- Model yêu cầu hoàn tiền ---
10
+ class RefundRequest(BaseModel):
11
+ partnerCode: str
12
+ orderId: str
13
+ requestId: str
14
+ amount: int
15
+ transId: int
16
+ description: str
17
+ lang: str = "vi"
18
+
19
+ # --- Tạo chữ ký ---
20
+ def generate_refund_signature(data: dict) -> str:
21
+ raw_data = (
22
+ f"accessKey={ACCESS_KEY}&amount={data['amount']}&description={data['description']}"
23
+ f"&orderId={data['orderId']}&partnerCode={PARTNER_CODE}"
24
+ f"&requestId={data['requestId']}&transId={data['transId']}"
25
+ )
26
+ return hmac.new(SECRET_KEY.encode(), raw_data.encode(), hashlib.sha256).hexdigest()
27
+
28
+ def call_momo_refund(amount: int, trans_id: int, description: str = "Hoàn tiền giao dịch"):
29
+ order_id = str(uuid.uuid4())
30
+ request_id = str(uuid.uuid4())
31
+
32
+ refund = RefundRequest(
33
+ partnerCode=PARTNER_CODE,
34
+ orderId=order_id,
35
+ requestId=request_id,
36
+ amount=amount,
37
+ transId=trans_id,
38
+ description=description,
39
+ )
40
+
41
+ payload = refund.dict()
42
+ payload["signature"] = generate_refund_signature(payload)
43
+
44
+ response = requests.post(
45
+ "https://test-payment.momo.vn/v2/gateway/api/refund",
46
+ json=payload,
47
+ headers={"Content-Type": "application/json"},
48
+ timeout=90,
49
+ )
50
+
51
+ return response.json()
52
+
53
+
54
+ # result = call_momo_refund(amount=100000, trans_id=4506777858)
55
+ # print(result)
56
+
57
+
58
+ import hmac
59
+ import hashlib
60
+ import requests
61
+ from datetime import datetime
62
+ import uuid
63
+
64
+ # ====== CẤU HÌNH MẶC ĐỊNH ======
65
+ VNP_URL = "https://sandbox.vnpayment.vn/merchant_webapi/api/transaction"
66
+ VNP_TMN_CODE = 'MCQ3SXQ1'
67
+ VNP_SECRET_KEY = '2QS3MSRVQQAFN36I5GA02DWB353KO4FD'
68
+ IP_ADDR = "127.0.0.1"
69
+
70
+ # ====== HÀM TẠO CHECKSUM HMAC SHA512 ======
71
+ def hmac_sha512(key: str, data: str) -> str:
72
+ return hmac.new(key.encode(), data.encode(), hashlib.sha512).hexdigest()
73
+
74
+ # ====== HÀM HOÀN TIỀN VNPAY ======
75
+ def call_vnpay_refund(
76
+ txn_ref: str,
77
+ amount: int,
78
+ transaction_date: str,
79
+ create_by: str,
80
+ order_info: str,
81
+ transaction_no: str = "", # optional
82
+ transaction_type: str = "02", # "02": full refund, "03": partial
83
+ vnp_url: str = VNP_URL,
84
+ vnp_tmn_code: str = VNP_TMN_CODE,
85
+ vnp_secret_key: str = VNP_SECRET_KEY,
86
+ ip_addr: str = IP_ADDR,
87
+ ):
88
+ # Lấy thời gian hiện tại (vnp_CreateDate)
89
+ now = datetime.now().strftime("%Y%m%d%H%M%S")
90
+
91
+ # Tạo request body
92
+ params = {
93
+ "vnp_RequestId": str(uuid.uuid4().hex[:32]),
94
+ "vnp_Version": "2.1.0",
95
+ "vnp_Command": "refund",
96
+ "vnp_TmnCode": vnp_tmn_code,
97
+ "vnp_TransactionType": transaction_type,
98
+ "vnp_TxnRef": txn_ref,
99
+ "vnp_Amount": str(amount), # nhân 100 nếu VNP yêu cầu
100
+ "vnp_TransactionNo": transaction_no,
101
+ "vnp_TransactionDate": transaction_date,
102
+ "vnp_CreateBy": create_by,
103
+ "vnp_CreateDate": now,
104
+ "vnp_IpAddr": ip_addr,
105
+ "vnp_OrderInfo": order_info
106
+ }
107
+
108
+ sign_data = "|".join([
109
+ params["vnp_RequestId"],
110
+ params["vnp_Version"],
111
+ params["vnp_Command"],
112
+ params["vnp_TmnCode"],
113
+ params["vnp_TransactionType"],
114
+ params["vnp_TxnRef"],
115
+ params["vnp_Amount"],
116
+ params["vnp_TransactionNo"],
117
+ params["vnp_TransactionDate"],
118
+ params["vnp_CreateBy"],
119
+ params["vnp_CreateDate"],
120
+ params["vnp_IpAddr"],
121
+ params["vnp_OrderInfo"]
122
+ ])
123
+
124
+
125
+ params["vnp_SecureHash"] = hmac_sha512(vnp_secret_key, sign_data)
126
+ response = requests.post(vnp_url, json=params, headers={"Content-Type": "application/json"})
127
+ return {
128
+ "status_code": response.status_code,
129
+ "data": response.json()
130
+ }
131
+
132
+
133
+
134
+ import hmac
135
+ import hashlib
136
+ import requests
137
+ import time
138
+ from datetime import datetime
139
+ import random
140
+ import string
141
+
142
+ # Cấu hình tài khoản ZaloPay
143
+ APP_ID = "2553"
144
+ KEY1 = "PcY4iZIKFCIdgZvA6ueMcMHHUbRLYjPL"
145
+ QUERY_ENDPOINT = "https://sb-openapi.zalopay.vn/v2/query"
146
+ REFUND_ENDPOINT = "https://sb-openapi.zalopay.vn/v2/refund"
147
+
148
+ def generate_mac(data: str, key: str) -> str:
149
+ return hmac.new(key.encode(), data.encode(), hashlib.sha256).hexdigest()
150
+
151
+ def generate_m_refund_id():
152
+ date_part = datetime.now().strftime("%y%m%d")
153
+ random_part = ''.join(random.choices(string.digits, k=10))
154
+ return f"{date_part}_{APP_ID}_{random_part}"
155
+
156
+ def call_zalopay_refund(app_trans_id: str, amount: int, description: str, refund_fee_amount: int = None):
157
+ """
158
+ Hàm thực hiện hoàn tiền giao dịch ZaloPay dựa trên app_trans_id.
159
+
160
+ Args:
161
+ app_trans_id (str): Mã giao dịch của ứng dụng.
162
+ amount (int): Số tiền hoàn lại (đơn vị: VND).
163
+ description (str): Mô tả lý do hoàn tiền.
164
+ refund_fee_amount (int, optional): Số tiền phí hoàn (nếu có).
165
+
166
+ Returns:
167
+ dict: Kết quả phản hồi từ ZaloPay.
168
+ """
169
+ # Bước 1: Truy vấn để lấy zp_trans_id
170
+ mac_input = f"{APP_ID}|{app_trans_id}|{KEY1}"
171
+ mac = generate_mac(mac_input, KEY1)
172
+
173
+ query_payload = {
174
+ "app_id": APP_ID,
175
+ "app_trans_id": app_trans_id,
176
+ "mac": mac
177
+ }
178
+
179
+ try:
180
+ query_response = requests.post(QUERY_ENDPOINT, data=query_payload)
181
+ query_result = query_response.json()
182
+ zp_trans_id = query_result.get("zp_trans_id")
183
+
184
+ if not zp_trans_id:
185
+ print("❌ Không tìm thấy zp_trans_id từ app_trans_id.")
186
+ return {"code": -1, "message": "Không tìm thấy zp_trans_id"}
187
+
188
+ except Exception as e:
189
+ print("❌ Lỗi khi truy vấn giao dịch:", e)
190
+ return {"code": -2, "message": "Lỗi truy vấn giao dịch"}
191
+
192
+ timestamp = int(time.time() * 1000)
193
+ m_refund_id = generate_m_refund_id()
194
+
195
+ if refund_fee_amount is not None:
196
+ hmac_data = f"{APP_ID}|{zp_trans_id}|{amount}|{refund_fee_amount}|{description}|{timestamp}"
197
+ else:
198
+ hmac_data = f"{APP_ID}|{zp_trans_id}|{amount}|{description}|{timestamp}"
199
+
200
+ refund_mac = generate_mac(hmac_data, KEY1)
201
+
202
+ refund_data = {
203
+ "app_id": APP_ID,
204
+ "m_refund_id": m_refund_id,
205
+ "zp_trans_id": zp_trans_id,
206
+ "amount": amount,
207
+ "timestamp": timestamp,
208
+ "description": description,
209
+ "mac": refund_mac
210
+ }
211
+
212
+ if refund_fee_amount is not None:
213
+ refund_data["refund_fee_amount"] = refund_fee_amount
214
+
215
+ try:
216
+ headers = {
217
+ "Content-Type": "application/x-www-form-urlencoded"
218
+ }
219
+ refund_response = requests.post(REFUND_ENDPOINT, data=refund_data, headers=headers)
220
+ return refund_response.json()
221
+
222
+ except Exception as e:
223
+ print("❌ Lỗi khi gửi hoàn tiền:", e)
224
+ return {"code": -3, "message": "Lỗi hoàn tiền"}