def confirm_transaction(request): if request.method == "POST": logger.info("Received callback request from TTT ScratchCard servers") # logger.info("Refferer: " + request.META["HTTP_REFERER"]) # logger.info("Host: " + request.META["REMOTE_HOST"]) logger.info(request.POST) try: matching_transaction = Transaction.objects.get( transaction_id=request.POST["partner_tran_id"], order_id=request.POST["id"] ) logger.info("Found matching transaction:") logger.info(matching_transaction) matching_transaction.status = 3 # PENDING if request.POST["status"] == '4': logger.info({'msg': 'Card already used!'}) matching_transaction.status = 1 # FAILED matching_transaction.remark = 'Card already used!' if request.POST["status"] == '5': logger.info({'msg': 'Wrong PIN'}) matching_transaction.status = 1 # FAILED matching_transaction.remark = 'Wrong PIN' if request.POST["status"] == '7': logger.info({'msg': 'Wrong Serial'}) matching_transaction.status = 1 # FAILED matching_transaction.remark = 'Wrong Serial' if request.POST["status"] == '8': logger.info({'msg': 'Wrong Amount'}) matching_transaction.status = 1 # FAILED matching_transaction.remark = 'Wrong Amount' if request.POST["status"] == '1': logger.info({'msg': 'Confirming Transaction!'}) matching_transaction.status = 0 # success matching_transaction.amount = request.POST["amount"] matching_transaction.remark = 'Successfully Deposited!' # update user balance after updating matching transaction helpers.addOrWithdrawBalance(matching_transaction.user_id, request.POST["amount"], "add") matching_transaction.arrive_time = timezone.now() matching_transaction.last_updated = timezone.now() matching_transaction.save() return JsonResponse({ "success": True, "message": "received response" }) except ObjectDoesNotExist as e: logger.critical("FATAL__ERROR::ScratchCard::Matching transaction not found", exc_info=1, stack_info=1) return JsonResponse({ "success": False, "message": "Could not find matching transaction" }) except Exception as e: logger.exception("Exception occurred::"+repr(e)) return JsonResponse({ "success": False, "message": "There was an exception" })
def post(self, request, *args, **kwargs): serializer = self.serializer_class(self.get_queryset(), many=True) trans_status = request.data.get('Status') depositID = request.data.get('ID') update_data = Transaction.objects.get( transaction_id=request.POST.get('Reference'), user_id=CustomUser.objects.get(pk=request.POST.get('Customer')) ) if update_data.order_id != '0': # attempting to confirm the same transaction twice logger.info("Callback was sent twice for Deposit #" + str(request.POST.get('Reference'))) return JsonResponse({ "error": "Transaction was already modified from 3rd party callback", "message": "Transaction already exists" }) result = "Pending" if trans_status == '000': update_data.status = 0 result = "Success" can_deposit = helpers.addOrWithdrawBalance(update_data.user_id, request.POST.get('Amount'), 'add') if not can_deposit: return JsonResponse({ 'message': 'There was an error with updating the user balance', 'success': False }) elif trans_status == '001': update_data.status = 1 result = "Failed" elif trans_status == '006': update_data.status = 4 result = "Approved" elif trans_status == '007': update_data.status = 8 result = "Rejected" elif trans_status == '009': update_data.status = 3 result = "Pending" update_data.order_id = depositID update_data.arrive_time = timezone.now() update_data.last_updated = timezone.now() update_data.remark = result update_data.save() return Response({ 'message': 'Received callback from Help2Pay', 'status': trans_status, 'result': result }, status=status.HTTP_200_OK)
def post(self, request): # print(request) new_amount = request.POST.get("new_amount") reason = request.POST.get("reason") pk = request.POST.get("txn_id") try: with transaction.atomic(): curr_txn = Transaction.objects.get(pk=pk) if new_amount: curr_txn.amount = new_amount new_status = 0 if curr_txn.status == 1 else 1 curr_txn.status = new_status curr_txn.remark = curr_txn.remark + " -> Result override to " + curr_txn.get_status_display( ) # TODO: implement changelog function to record # addToChangelog() can_update = helpers.addOrWithdrawBalance( curr_txn.user_id.username, curr_txn.amount, "add") if can_update: curr_txn.save() return HttpResponse( "Transaction No. " + pk + " was changed from 'Failed' to 'Successful'") else: return HttpResponse( "Was not able to update user's balance") except Exception as e: logger.error( "There was an error with overriding the transaction result", exc_info=1) logger.error(repr(e)) return HttpResponse( "There was an error when overriding the result")
def post(self, request, *args, **kwargs): serializer = approvePayoutSerialize(self.queryset, context={'request': request}, many=True) orderId = self.request.POST['order_id'] userId = self.request.POST['user_id'] notes = self.request.POST['remark'] list = [merchantId, orderId, userId, notes] message = '|'.join(str(x) for x in list) mymessage = bytes(message, 'utf-8') secret = bytes(merchantApiKey, 'utf-8') my_hmac = generateHash(secret, mymessage) url = api + apiVersion + '/' + merchantId + '/payout/' + orderId + '/reject' headers = { 'Accept': 'application/json', 'Content-Type': 'application/x-www-form-urlencoded', } delay = kwargs.get("delay", 5) #retry success = False for x in range(3): try: r = requests.post(url, headers=headers, data={ 'rejectedBy': userId, 'notes': notes, 'messageAuthenticationCode': my_hmac, }) if r.status_code == 200: success = True break except ValueError: logger.info( 'Request failed {} time(s).wating for %s seconds before retrying again' .format(x + 1)) sleep(delay) if not success: logger.critical( 'Failed to complete a request for rejecting payout transaction' ) # Handle error rdata = r.json() #print(rdata) if r.status_code == 200: for x in Transaction._meta.get_field('currency').choices: if rdata['currency'] == x[1]: cur_val = x[0] for y in Transaction._meta.get_field('status').choices: if rdata["status"] == y[1]: cur_status = y[0] try: with transaction.atomic(): user = CustomUser.objects.get(username=rdata['userId']) update_data = Transaction.objects.get( transaction_id=rdata['orderId']) update_data.order_id = rdata['transactionId'] update_data.last_updated = rdata["dateUpdated"] update_data.status = TRAN_REJECTED_TYPE update_data.review_status = REVIEW_REJ update_data.remark = notes update_data.release_by = user update_data.save() addOrWithdrawBalance(user.username, update_data.amount, 'add') logger.info('Finish updating the status of withdraw ' + str(rdata['orderId']) + ' to Approve') return Response(rdata) except ObjectDoesNotExist as e: logger.error( "matching transaction not found / does not exist for qaicash rejecting payout" ) return Response({ "error": "Could not find matching transaction for qaicash rejecting payout", "code": ERROR_CODE_NOT_FOUND }) except DatabaseError as e: logger.info( "Error update transaction for qaicash rejecting payout" + str(e)) return Response({ "error": "Error updating transaction for qaicash rejecting payout", "code": ERROR_CODE_DATABASE }) else: logger.error( 'The request information is not correct for qaicash rejecting payout, please try again.' ) return Response({ "error": "The request information is not correct for qaicash rejecting payout", "code": ERROR_CODE_INVALID_INFO })
def post(self, request): # user will need to submit bank acc information data = json.loads(request.body) username = request.user.username try: user = CustomUser.objects.get(username=username) withdraw_password = data.get("withdrawPassword") # toBankAccountName = 'orion' # toBankAccountNumber = '12345123' toBankAccountName = data.get("toBankAccountName") toBankAccountNumber = data.get("toBankAccountNumber") amount = float(data.get("amount")) currency = data.get("currency") or 2 # 2 = THB, 8 = VND currency = int(currency) trans_id = username+"-"+timezone.datetime.today().isoformat()+"-"+str(random.randint(0, 10000000)) # trans_id = "orion-"+timezone.datetime.today().isoformat()+"-"+str(random.randint(0, 10000000)) ip = helpers.get_client_ip(request) bank = data.get("bank") user_id=user.pk merchant_code = '123' secret_key = '123' payoutURL = '123' if currency == 2: merchant_code = HELP2PAY_MERCHANT_THB secret_key = HELP2PAY_SECURITY_THB payoutURL = H2P_PAYOUT_URL_THB elif currency == 8: merchant_code = HELP2PAY_MERCHANT_VND secret_key = HELP2PAY_SECURITY_VND payoutURL = H2P_PAYOUT_URL_VND strAmount = str('%.2f' % amount) utc_datetime = datetime.datetime.utcnow().replace(tzinfo=pytz.utc).astimezone(pytz.timezone('Asia/Shanghai')) Datetime = utc_datetime.strftime("%Y-%m-%d %H:%M:%S%p") key_time = utc_datetime.strftime("%Y%m%d%H%M%S") secretMsg = merchant_code+trans_id+str(user_id)+strAmount+currencyConversion[currency]+key_time+toBankAccountNumber+secret_key checksum = MD5(secretMsg) if check_password(withdraw_password, user.withdraw_password): try: db_currency_code = 7 if currency == 8 else 2 withdraw_request = Transaction( transaction_id=trans_id, amount=amount, user_id=user, method='Bank Transfer', currency=currency, transaction_type=TRANSACTION_WITHDRAWAL, channel=0, request_time=timezone.now(), other_data={'checksum': checksum} ) withdraw_request.save() logger.info("Withdraw request created: " + str(withdraw_request)) can_withdraw = helpers.addOrWithdrawBalance(username, amount, "withdraw") if can_withdraw: data = { "Key": checksum, "ClientIP": ip, "ReturnURI": HELP2PAY_RETURN_URL, "MerchantCode": merchant_code, "TransactionID": str(trans_id), "MemberCode": user_id, "CurrencyCode": currencyConversion[currency], "Amount": amount, "TransactionDateTime": Datetime, "BankCode": bank, "toBankAccountName": toBankAccountName, "toBankAccountNumber": toBankAccountNumber, } r = requests.post(payoutURL, data=data) if r.status_code == 200: return HttpResponse(r.content, content_type="text/xml") else: return JsonResponse({ 'status_code': ERROR_CODE_FAIL, 'message': 'Payment service unavailable' }) else: return JsonResponse({ 'status_code': ERROR_CODE_FAIL, 'message': 'Insufficient funds' }) except (ObjectDoesNotExist, IntegrityError, DatabaseError) as e: logger.critical("FATAL__ERROR::Help2Pay::Exception occured when submitting a payout request", exc_info=1) return HttpResponse(status=500) else: logger.error("withdraw password is not correct.") return JsonResponse({ 'status_code': ERROR_CODE_INVALID_INFO, 'message': 'Withdraw password is not correct.' }) except ObjectDoesNotExist as e: logger.error(repr(e)) return HttpResponse(status=500)
def confirm_payment(request): if request.method == "GET": logger.info("Hello GET") return HttpResponse(status=404) if request.method == "POST": logger.info("[" + str(datetime.datetime.now()) + "] Received confirm_payment() callback from CirclePay") transaction_data = json.loads(request.body) logger.info(transaction_data) # query for transaction in ibet db try: matching_transaction = Transaction.objects.get( transaction_id=transaction_data["partner_tran_id"], amount=transaction_data["amount"], ) logger.info("Found matching transaction!") if matching_transaction.order_id != '0': return JsonResponse({ "code": "888", "message": "Callback rejected: Transaction already processed" }) if transaction_data["status"] == '00': # deposit successful matching_transaction.status = 0 matching_transaction.remark = "Deposit successful!" successful = helpers.addOrWithdrawBalance( matching_transaction.user_id, transaction_data["amount"], "add") if not successful: return JsonResponse({ "success": False, "message": "Could not modify balance" }) if transaction_data["status"] == '01' or transaction_data[ "status"] == '04': # deposit pending matching_transaction.status = 3 matching_transaction.remark = "Deposit pending!" if transaction_data["status"] == '02': # deposit canceled matching_transaction.status = 5 matching_transaction.remark = "Deposit canceled!" if transaction_data["status"] == '03': # deposit failed matching_transaction.status = 1 matching_transaction.remark = "Deposit failed!" payment_method = matching_transaction.method + "_" + transaction_data[ "method"] matching_transaction.order_id = transaction_data["tran_id"] matching_transaction.method = payment_method matching_transaction.arrive_time = timezone.datetime.strptime( transaction_data["time"], '%Y-%m-%d %H:%M:%S') matching_transaction.last_updated = timezone.now() matching_transaction.save() # update transaction record status return JsonResponse({ "success": True, "message": "Received confirmation of payment" }) except ObjectDoesNotExist as e: logger.critical( "FATAL__ERROR::CirclePay::Unable to confirm payment", exc_info=1, stack_info=1) return JsonResponse({ "success": False, "message": "Could not find matching transaction" })
def confirm_payment(request): if request.method == "GET": logger.info(request.GET) logger.info("Hello, GET request received on payzod confirm_payment()") return HttpResponse( "You are at the endpoint for Payzod confirm payment") # query for transaction in ibet db # update transaction record status if request.method == "POST": logger.info("Hello, POST request received on payzod confirm_payment()") logger.info(request.POST) req = request.POST try: matching_transaction = Transaction.objects.get( transaction_id=req.get("ref_no"), amount=req.get("amount")) logger.info("Found matching transaction!") if matching_transaction.order_id != '0': return JsonResponse({ "responseCode": "202", "responseMesg": "Transaction already exists" }) # success if req.get("response_code") == "001": matching_transaction.status = 0 matching_transaction.remark = req.get("response_msg") matching_transaction.order_id = req.get("transaction_no") matching_transaction.arrive_time = timezone.now() matching_transaction.last_updated = timezone.now() matching_transaction.save() logger.info("Finished updating transaction in DB!") logger.info("Updating user balance...") helpers.addOrWithdrawBalance(matching_transaction.user_id, req.get("amount"), "add") return JsonResponse({ "responseCode": "000", "responseMesg": req.get("response_msg") }) else: # failure matching_transaction.status = 1 matching_transaction.remark = req.get("response_msg") matching_transaction.order_id = req.get("transaction_no") matching_transaction.arrive_time = timezone.now() matching_transaction.last_updated = timezone.now() matching_transaction.save() logger.info("Finished updating transaction in DB!") return JsonResponse({ "responseCode": "888", "responseMesg": req.get("response_msg") }) except ObjectDoesNotExist as e: logger.critical( "FATAL__ERROR::Payzod::Payment confirmation failed", exc_info=1, stack_info=1) return JsonResponse( {"message": "Could not find matching transaction"}) return HttpResponse("Invalid Request")
def transfer(request): """ This method is called by PaymentIQ after a successfully processed transaction to credit (increase) or debit (decrease) a user's account balance. Note: The Operator Platform must always accept a transfer request, even if it results in a negative user balance because the payment transaction has already been processed by the payment provider. :param request: HTTP request containing user info & transaction data Example request: { "userId": "user_123", "txAmount": "100.50", "txAmountCy": "SEK", "txPspAmount": "12.50", "txPspAmountCy": "EUR", "fee": "0.50", "feeCy": "SEK", "txId": "25A0324", "txTypeId": "101", "txName": "CreditcardDeposit", "provider": "Neteller", "txRefId": "100019999A26720" } :return: """ if request.method == "POST": post_data = json.loads(request.body) user = CustomUser.objects.get(username=post_data["userId"]) try: if "deposit" in post_data["txName"].lower(): matching_transaction = Transaction.objects.get( user_id=user, order_id=post_data["txId"], amount=float(post_data["txAmount"]), method=post_data["provider"] + ": " + post_data["txName"], currency=cyConversion[post_data["txAmountCy"]], transaction_type=0, # 0 = DEPOSIT channel=10, # 10 = PaymentIQ ) if matching_transaction.status != 2: return JsonResponse({ "success": False, "errCode": "200", # custom error code (used internally by ibet) "errMsg": "Transfer failed: duplicate Transfer action" # message explaining error }) success = helpers.addOrWithdrawBalance(matching_transaction.user_id, matching_transaction.amount, "add") matching_transaction.status = 0 matching_transaction.arrive_time = timezone.now() matching_transaction.last_updated = timezone.now() matching_transaction.remark = "Successfully deposited!" matching_transaction.save() result = { "userId": post_data["userId"], "success": success, "txId": post_data["txId"], "merchantTxId": matching_transaction.transaction_id, } return JsonResponse(result) elif "withdraw" in post_data["txName"].lower(): matching_transaction = Transaction.objects.get( user_id=user, order_id=post_data["txId"], amount=float(post_data["txAmount"]), method=post_data["provider"] + ": " + post_data["txName"], currency=cyConversion[post_data["txAmountCy"]], transaction_type=0, # 0 = DEPOSIT channel=10, # 10 = PaymentIQ ) if matching_transaction.status != 2: return JsonResponse({ "success": False, "errCode": "200", # custom error code (used internally by ibet) "errMsg": "Transfer failed: duplicate Transfer action" # message explaining error }) matching_transaction.status = 0 matching_transaction.arrive_time = timezone.now() matching_transaction.last_updated = timezone.now() matching_transaction.remark = "Successfully withdrew!" matching_transaction.save() success = helpers.addOrWithdrawBalance(matching_transaction.user_id, matching_transaction.amount, "withdraw") if success: result = { "userId": post_data["userId"], "success": success, "txId": post_data["txId"], "merchantTxId": trans_id, } return JsonResponse(result) else: result = { "userId": post_data["userId"], "success": success, "txId": post_data["txId"], "merchantTxId": trans_id, "errCode": "001", "errMsg": "Authorize failed: not enough withdraw balance" } return JsonResponse(result) except ObjectDoesNotExist as e: logger.info(e) return JsonResponse({ "userId": post_data["userId"], "success": False, "merchantTxId": trans_id, "errCode": "001", # custom error code (used internally by ibet) "errMsg": "Transfer failed: Transaction does not exist" # message explaining error })