I tried, same happened. it's related to how Postgres works internally with the Django-ORM.
On Wednesday, August 21, 2019 at 3:07:47 PM UTC+2, mohamed habib wrote: > > Wild guess in the dark here, as I am unfamiliar with this API. you are > doing: > > `payment.pay_request()` > > before creating the WeacceptTransaction object. > > Maybe this line needs to move below: > `models.WeAcceptTransaction.objects.create(...)` ? > > At what point is the callback request triggered ? > > On Wed, Aug 21, 2019 at 3:36 PM Ahmed Shahwan <[email protected] > <javascript:>> wrote: > >> Transaction model: >> >> >> class WeacceptTransaction(Transaction): >> """Weaccept's Transaction model""" >> >> # before frontend interaction >> auth_token = models.TextField() # got from step 1 >> order_id = models.IntegerField(verbose_name="Accept's Order ID") # >> id from step 2 >> order_url = models.CharField(max_length=255, null=True) # order_url >> from step 2 >> billing_data = JSONField() # provided in request for paymet key, >> step 3 >> payment_key = models.TextField() # payment_token from step 3 >> hmac = models.TextField(null=True) >> # after (from callback) >> success_status = models.BooleanField(default=False) >> is_refunded = models.BooleanField(default=False) >> reference_number = models.IntegerField(null=True) >> processed_clbk_json = JSONField(null=True) >> >> >> The cash_payment View: >> >> class CashPayment(APIView): >> """Cash Payment endpoint""" >> >> serializer_class = serializers.CardPaymentSerializer >> required_fields = ["amount_cents", "billing_data"] >> >> def post(self, request): >> # Validate required fields >> utils.validate(self.required_fields, request) >> payment = utils.CashPayment(**request.data) >> payment.prepare() >> payment.pay_request() >> # create a new transaction >> models.WeacceptTransaction.objects.create( >> merchant_order_id=payment.merchant_order_id, >> amount=payment.amount_cents, >> auth_token=payment.auth_res.get("token"), >> order_id=payment.order_reg_res.get("id"), >> order_url=payment.order_reg_res.get("order_url"), >> billing_data=payment.billing_data, >> payment_key=payment.payment_key_res.get("token"), >> hmac=payment.pay_req_res.get("hmac"), >> ) >> >> return Response( >> { >> "message": "Our representative will go to the address you >> provided " >> "to collect the cash from you", >> **payment.pay_req_res, >> } >> ) >> >> >> Please note: the first 3 steps are wrapped into the method `prepare()` >> the 4th step is `pay_request()` >> >> >> the callback-url endpoint (where the 5th step happens) >> >> class TransactionProcessedCallback(APIView): >> """Processed callback that will recieve "TRANSACTION", "TOKEN", "ORDER >> ", >> "DELIVERY_STATUS" objects""" >> >> def post(self, request): >> # XXX extend to handle TOKEN, DELIVERY_STATUS objects... later >> t_obj = request.data.get("obj") # transaction object >> incoming_hmac = request.query_params.get("hmac") >> calculated_hmac = utils.calculate_hmac_transaction(t_obj) >> >> # if not equal hmac, not coming from Accept! >> if incoming_hmac != calculated_hmac: >> return Response( >> {"message": "invalid data"}, status=status. >> HTTP_400_BAD_REQUEST >> ) >> >> import ipdb >> >> ipdb.set_trace() >> # XXX: The error happens here >> transaction = models.WeacceptTransaction.objects.get( >> merchant_order_id=t_obj.get("order").get("merchant_order_id") >> ) >> transaction.success_status = bool(t_obj.get("success")) >> transaction.is_refunded = bool(t_obj.get("is_refunded")) >> transaction.reference_number = int(t_obj.get("data").get( >> "transaction_no") or 1) >> transaction.processed_clbk_json = t_obj >> transaction.save( >> update_fields=[ >> "success_status", >> "is_refunded", >> "reference_number", >> "processed_clbk_json", >> ] >> ) >> >> email = t_obj.get("order").get("shipping_data").get("email") >> # TODO: send mail based upon success status >> try: >> send_mail( >> "Transaction Processed", >> "Your transaction is processed", >> "SERNDER MAIL", >> [email], >> fail_silently=False, >> ) >> except Exception as ex: >> print(">>>>>>>>>>FAILED TO SEND MAIL") >> print(ex) >> >> return Response({"message": "Transaction Updated!"}, status= >> status.HTTP_200_OK) >> >> >> The 6th step (redirect-url) is irrelevant here, and not included in the >> XPAY's service for this payment option. >> >> >> On Wednesday, August 21, 2019 at 2:03:20 PM UTC+2, mohammed habib wrote: >>> >>> Are you sure the callback request passes the right parameters ? >>> >>> Could you share some of your views code from the 6 steps, and your >>> Transaction model ? >>> >>> Sent from my iPhone >>> >>> On 21 Aug 2019, at 14:46, Ahmed Shahwan <[email protected]> wrote: >>> >>> Hi, >>> >>> I have a very strange problem that I don't know why it happens. >>> I'm creating a REST API service that wraps another REST API payment >>> service, let's call the other services XPAY. It has various payment options >>> (Card, eWallet, Kiosk, and Cash). The steps required to use the services >>> (to make a transaction) >>> >>> 1. authentication 2. order registration 3. payment key 4. prepare >>> frontend based on payment type 5. Callback URL 6. Redirect URL >>> >>> and each step depends on its predecessor. The first 4 steps are >>> performed through HTTP Requests that I issue from my service. I store some >>> of the information I receive in those steps in a Model called Transaction. >>> 5th and 6th steps are Callback endpoints that I create to receive further >>> information about the status of the transaction that I started in the first >>> 4 steps. >>> >>> My endpoints design is: >>> >>> myservice/payment/card >>> myservice/payment/wallet >>> myservice/payment/kiosk >>> myservice/payment/cash >>> >>> myservice/payment/callback-url >>> myservice/payment/redirect-url >>> >>> These endpoints are wrappers for the payment methods available in XPAY's >>> service that my frontend apps will use to provide those payment options for >>> users. >>> >>> I implemented the first 3 endpoints with no problem. inside those >>> endpoints, I create a transaction object with a unique id and then update >>> it from inside the *callback-url endpoint* after I receive the >>> information from XPAY's service. Note that it takes some time between >>> creating the Transaction object and saving it into the database from inside >>> my endpoint, and updating it from inside the callback url endpoint. >>> >>> The weird thing happens in the 4th endpoint `cash` endpoint. XPAY's >>> service responds very quickly on my *callback-url endpoint* and when it >>> gets to the updating step, I get *Transaction.DoesNotExist *Exception while >>> getting the transaction object using Transaction.objects.get(id=id). >>> >>> After some debugging time using ipdb I found that the instance has >>> already been saved to the database! and I can retrieve it with its id. but >>> when I let it run ordinarily the saving operation doesn't finish until that >>> time (I got to know that using some print() statements), which is very >>> strange, it's impossible that my laptop is that slow! >>> >>> Solutions I tried: >>> 1. atomic transaction >>> 2. time.sleep some time after making the request and saving the >>> transaction object to the db >>> 3. time.sleep in the callback-url before getting the transaction from DB >>> >>> I checked any possible logic error related to it and there's nothing >>> illogical. >>> >>> the issue is related to Postgres and how it operates, and also with >>> Django's ORM. I don't know. >>> >>> Main technologies I use: >>> Django 2.2 >>> Postgres Docker container >>> DRF >>> >>> I hope someone gives me an insight into why this is happening and how to >>> work around it. >>> >>> Thanks >>> >>> -- >>> You received this message because you are subscribed to the Google >>> Groups "Django users" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to [email protected]. >>> To view this discussion on the web visit >>> https://groups.google.com/d/msgid/django-users/e43be322-bab9-4162-9fbc-05c6c9b95c94%40googlegroups.com >>> >>> <https://groups.google.com/d/msgid/django-users/e43be322-bab9-4162-9fbc-05c6c9b95c94%40googlegroups.com?utm_medium=email&utm_source=footer> >>> . >>> >>> -- >> You received this message because you are subscribed to the Google Groups >> "Django users" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to [email protected] <javascript:>. >> To view this discussion on the web visit >> https://groups.google.com/d/msgid/django-users/a379e013-a01c-4c58-bf2b-0b4cd01f0fae%40googlegroups.com >> >> <https://groups.google.com/d/msgid/django-users/a379e013-a01c-4c58-bf2b-0b4cd01f0fae%40googlegroups.com?utm_medium=email&utm_source=footer> >> . >> > > > -- > Best regards, > *Mohammed M. Habib, PhD* > > -- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/987c6ce7-70b6-49a9-ab3e-506e369d060e%40googlegroups.com.

