def async_payment(self, registration_id, token, logger_context=None): self.setup_logger(logger_context) self.registration = Registration.objects.get(id=registration_id) event = self.registration.event try: response = stripe.Charge.create( amount=event.get_price(self.registration.user), currency="NOK", source=token, description=event.slug, metadata={ "EVENT_ID": event.id, "USER_ID": self.registration.user.id, "USER": self.registration.user.full_name, "EMAIL": self.registration.user.email, }, ) log.info("stripe_payment_success", registration_id=self.registration.id) return response except stripe.error.CardError as e: raise self.retry(exc=e, max_retries=0) except stripe.error.InvalidRequestError as e: log.error("invalid_request", exception=e, registration_id=self.registration.id) self.registration.charge_status = e.json_body["error"]["type"] self.registration.save() notify_user_payment( constants.SOCKET_PAYMENT_FAILURE, self.registration, error_message="Invalid request", ) except stripe.error.StripeError as e: log.error("stripe_error", exception=e, registration_id=self.registration.id) raise self.retry(exc=e)
def on_failure(self, return_value, *args): if self.request.retries == self.max_retries: if return_value.json_body: error = return_value.json_body["error"] notify_user_payment( constants.SOCKET_INITIATE_PAYMENT_FAILURE, self.registration, error_message=error["message"], ) else: notify_user_payment( constants.SOCKET_INITIATE_PAYMENT_FAILURE, self.registration, error_message="Noe gikk galt med betalingen.", )
def registration_payment_save(self, result, registration_id, logger_context=None): self.setup_logger(logger_context) try: registration = Registration.objects.get(id=registration_id) registration.charge_id = result["id"] registration.charge_amount = result["amount"] registration.charge_status = result["status"] registration.save() notify_user_payment( constants.SOCKET_PAYMENT_SUCCESS, registration, success_message="Betaling gjennomført", ) except IntegrityError as e: log.error( "registration_save_error", exception=e, registration_id=registration_id ) raise self.retry(exc=e)
def on_failure(self, return_value, *args): # There is no reason to retry card declined errors, the exception has max_retries=0 isCardError = isinstance(return_value, stripe.error.CardError) if self.request.retries == self.max_retries or isCardError: if return_value.json_body: error = return_value.json_body["error"] self.registration.charge_id = error["charge"] self.registration.charge_status = error["code"] self.registration.save() notify_user_payment( constants.SOCKET_PAYMENT_FAILURE, self.registration, error_message=error["message"], ) else: self.registration.charge_status = constants.PAYMENT_FAILURE self.registration.save() notify_user_payment( constants.SOCKET_PAYMENT_FAILURE, self.registration, error_message="Payment failed", )
def async_payment(self, registration_id, token, logger_context=None): self.setup_logger(logger_context) self.registration = Registration.objects.get(id=registration_id) event = self.registration.event try: response = stripe.Charge.create( amount=event.get_price(self.registration.user), currency='NOK', source=token, description=event.slug, metadata={ 'EVENT_ID': event.id, 'USER_ID': self.registration.user.id, 'USER': self.registration.user.full_name, 'EMAIL': self.registration.user.email, }) log.info('stripe_payment_success', registration_id=self.registration.id) return response except stripe.error.CardError as e: raise self.retry(exc=e) except stripe.error.InvalidRequestError as e: log.error('invalid_request', exception=e, registration_id=self.registration.id) self.registration.charge_status = e.json_body['error']['type'] self.registration.save() notify_user_payment(constants.SOCKET_PAYMENT_FAILURE, self.registration, error_message='Invalid request') except stripe.error.StripeError as e: log.error('stripe_error', exception=e, registration_id=self.registration.id) raise self.retry(exc=e)
def stripe_webhook_event(self, event_id, event_type, logger_context=None): """ Task that handles webhook events from Stripe, and updates the users registration in accordance with the payment status. """ self.setup_logger(logger_context) event = stripe.Event.retrieve(event_id) if event_type in [ constants.STRIPE_EVENT_INTENT_SUCCESS, constants.STRIPE_EVENT_INTENT_PAYMENT_FAILED, constants.STRIPE_EVENT_INTENT_PAYMENT_CANCELED, ]: serializer = StripePaymentIntentSerializer(data=event.data["object"]) serializer.is_valid(raise_exception=True) metadata = serializer.data["metadata"] registration = Registration.objects.filter( event_id=metadata["EVENT_ID"], user__email=metadata["EMAIL"] ).first() if not registration: log.error("stripe_webhook_error", event_id=event_id, metadata=metadata) raise WebhookDidNotFindRegistration(event_id, metadata) registration.payment_amount = serializer.data["amount"] # We update the payment status based on the stripe event type if event_type == constants.STRIPE_EVENT_INTENT_SUCCESS: registration.payment_status = constants.PAYMENT_SUCCESS notify_user_payment( constants.SOCKET_PAYMENT_SUCCESS, registration, success_message="Betaling godkjent", ) elif event_type == constants.STRIPE_EVENT_INTENT_PAYMENT_FAILED: registration.payment_status = constants.PAYMENT_FAILURE notify_user_payment( constants.SOCKET_PAYMENT_FAILURE, registration, error_message="Betaling feilet", ) elif event_type == constants.STRIPE_EVENT_INTENT_PAYMENT_CANCELED: registration.payment_status = constants.PAYMENT_CANCELED registration.payment_intent_id = None registration.payment_idempotency_key = None registration.save() elif event_type in [constants.STRIPE_EVENT_CHARGE_REFUNDED]: serializer = StripeChargeSerializer(data=event.data["object"]) serializer.is_valid(raise_exception=True) metadata = serializer.data["metadata"] registration = Registration.objects.filter( event_id=metadata["EVENT_ID"], user__email=metadata["EMAIL"] ).first() if not registration: log.error("stripe_webhook_error", event_id=event_id, metadata=metadata) raise WebhookDidNotFindRegistration(event_id, metadata) registration.payment_status = constants.PAYMENT_SUCCESS registration.payment_amount_refunded = serializer.data["amount_refunded"] registration.save() log.info("stripe_webhook_received", event_id=event_id)