def getPayPalLegacySettings(): siteSettings = get_site_settings_from_default_site() if (siteSettings.sandbox_mode): ipn_url = 'https://ipnpb.sandbox.paypal.com/cgi-bin/webscr' return SettingsPayPalLegacy(siteSettings.sandbox_mode, ipn_url) ipn_url = 'https://ipnpb.paypal.com/cgi-bin/webscr' return SettingsPayPalLegacy(siteSettings.sandbox_mode, ipn_url)
def __init__(self, *args, user=None, **kwargs): super().__init__(*args, **kwargs) if not user: raise ValueError(_('Please provide user object')) site_settings = get_site_settings_from_default_site() usermeta_dict = {} for um in user.metas.all(): usermeta_dict[um.field_key] = um.field_value # construct user meta fields from site settings configuration usermetafields = site_settings.user_meta_fields.all() fb = FormBuilder(usermetafields) for key, val in fb.formfields.items(): if isinstance(val, forms.MultipleChoiceField): self.fields["usermetalist_"+key] = val self.fields["usermetalist_" + key].initial = usermeta_dict[key].split(',\n') if key in usermeta_dict else None else: self.fields["usermeta_"+key] = val self.fields["usermeta_" + key].initial = usermeta_dict[key] if key in usermeta_dict else None # Fill up values self.fields["first_name"].widget.attrs['value'] = user.first_name self.fields["last_name"].widget.attrs['value'] = user.last_name self.fields["email"].widget.attrs['value'] = user.email self.fields["email"].widget.attrs['disabled'] = True self.fields["email"].label += ' ' + \ str(user.email_verification_status()) self.fields["opt_in_mailing_list"].initial = user.opt_in_mailing_list self.fields["language_preference"].initial = user.language_preference
def sendDonationNotifToAdmins(donation): siteSettings = get_site_settings_from_default_site() mail_title = _("New One-off Donation") if siteSettings.admin_receive_checkout_emails: sendEmailNotificationsToAdmins( siteSettings, mail_title, get_new_donation_text(donation), render_to_string('donations/email_templates/new_donation.html', context={'donation': donation}))
def sendRecurringCancelRequestNotifToAdmins(subscription): siteSettings = get_site_settings_from_default_site() mail_title = _("Cancellation to a Recurring Donation is requested") sendEmailNotificationsToAdmins( siteSettings, mail_title, get_recurring_cancel_request_admin_text(subscription), render_to_string( 'donations/email_templates/recurring_cancel_request_admin.html', context={'subscription': subscription}))
def sendAccountDeletedNotifToAdmins(user): siteSettings = get_site_settings_from_default_site() mail_title = _("A Donor Account is deleted") if siteSettings.admin_receive_account_deleted_emails: sendEmailNotificationsToAdmins( siteSettings, mail_title, get_account_deleted_admin_text(user), render_to_string( 'donations/email_templates/account_deleted_admin.html', context={'user': user}))
def get2C2PSettings(): siteSettings = get_site_settings_from_default_site() if (siteSettings.sandbox_mode): return Settings2C2P(siteSettings.sandbox_mode, siteSettings._2c2p_testing_merchant_id, siteSettings._2c2p_testing_secret_key) return Settings2C2P(siteSettings.sandbox_mode, siteSettings._2c2p_merchant_id, siteSettings._2c2p_secret_key)
def my_recurring_donations(request): # deleted=False should be valid whether soft-delete mode is on or off subscriptions = Subscription.objects.filter( user=request.user, deleted=False).order_by('-created_at') siteSettings = get_site_settings_from_default_site() return render(request, 'donations/my_recurring_donations.html', { 'subscriptions': subscriptions, 'siteSettings': siteSettings })
def sendDonationRevokedToAdmins(donation): siteSettings = get_site_settings_from_default_site() mail_title = _("A Donation is revoked") if siteSettings.admin_receive_revoked_emails: sendEmailNotificationsToAdmins( siteSettings, mail_title, get_donation_revoked_admin_text(donation), render_to_string( 'donations/email_templates/donation_revoked_admin.html', context={'donation': donation}))
def sendNewRecurringNotifToAdmins(subscription): siteSettings = get_site_settings_from_default_site() mail_title = _("New Recurring Donation") if siteSettings.admin_receive_new_recurring_emails: sendEmailNotificationsToAdmins( siteSettings, mail_title, get_new_recurring_admin_text(subscription), render_to_string( 'donations/email_templates/new_recurring_donation.html', context={'subscription': subscription}))
def sendRecurringCancelledNotifToAdmins(subscription): siteSettings = get_site_settings_from_default_site() mail_title = _("A Recurring Donation is cancelled") if siteSettings.admin_receive_cancel_recurring_emails: sendEmailNotificationsToAdmins( siteSettings, mail_title, get_recurring_cancelled_admin_text(subscription), render_to_string( 'donations/email_templates/recurring_cancelled_admin.html', context={'subscription': subscription}))
def site_settings(attribute): """ The standard way of fetching custom site settings is too clumsy: (see: https://docs.wagtail.io/en/v2.12/reference/contrib/settings.html#using-in-django-templates) This filter should allow templates to be more succinct """ settings = get_site_settings_from_default_site() return getattr(settings, attribute, None)
def my_onetime_donations(request): # deleted=False should be valid whether soft-delete mode is on or off # previously deleted records should still be hidden even soft-delete mode is turned off afterwards donations = Donation.objects.filter( user=request.user, is_recurring=False, deleted=False).order_by('-donation_date') siteSettings = get_site_settings_from_default_site() return render(request, 'donations/my_onetime_donations.html', { 'donations': donations, 'siteSettings': siteSettings })
def __init__(self, request, donation, subscription): # stores the request object from django self.request = request # either one of the donation or subscription object cannot be None if not donation and not subscription: raiseObjectNone( 'Either one of donation or subscription has to be defined while initializing BasePaymentGateway class') self.donation = donation self.subscription = subscription # stores whether current app is in test mode or not site_settings = get_site_settings_from_default_site() self.testing_mode = site_settings.sandbox_mode
def getStripeSettings(): siteSettings = get_site_settings_from_default_site() if (siteSettings.sandbox_mode): return SettingsStripe(siteSettings.sandbox_mode, siteSettings.stripe_testing_webhook_secret, siteSettings.stripe_testing_product_id, siteSettings.stripe_testing_api_publishable_key, siteSettings.stripe_testing_api_secret_key) return SettingsStripe(siteSettings.sandbox_mode, siteSettings.stripe_webhook_secret, siteSettings.stripe_product_id, siteSettings.stripe_api_publishable_key, siteSettings.stripe_api_secret_key)
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) site_settings = get_site_settings_from_default_site() # manually casting signup_footer_text from LazyI18nString to str to avoid the "richtext expects a string" error in the template self.footer_html = str(site_settings.signup_footer_text) # construct user meta fields from site settings configuration usermetafields = site_settings.user_meta_fields.all() fb = FormBuilder(usermetafields) for key, val in fb.formfields.items(): if isinstance(val, forms.MultipleChoiceField): self.fields["usermetalist_" + key] = val else: self.fields["usermeta_" + key] = val
def sendDonationErrorNotifToAdmins(donation, error_title, error_description): siteSettings = get_site_settings_from_default_site() mail_title = _("Donation Error") if siteSettings.admin_receive_donation_error_emails: sendEmailNotificationsToAdmins( siteSettings, mail_title, get_donation_error_admin_text(donation, error_title, error_description), render_to_string( 'donations/email_templates/donation_error_admin.html', context={ 'donation': donation, 'error_title': error_title, 'error_description': error_description }))
def isUpdateSubsFrequencyLimitationPassed(gatewayManager): site_settings = get_site_settings_from_default_site() if site_settings.limit_fiveactions_per_fivemins: # get count of the actions carried out by the same donor in the last 5 minutes nowdt = datetime.now(dt_timezone.utc) fiveminsbf = nowdt - timedelta(minutes=5) count = UserSubscriptionUpdatesLog.objects.filter( user=gatewayManager.subscription.user, created_at__gte=fiveminsbf).count() _debug( 'Count of Subscription Actions done by {} within five minutes: {}'. format(gatewayManager.subscription.user.fullname, count)) if count >= 5: return False return True
def homepage(request): try: siteSettings = get_site_settings_from_default_site() homepage = request.site.root_page # candidates = TranslatablePage.objects.live().specific().child_of( # root_page).filter(content_type__model='homepage') # homepage = candidates.filter(language__code=language).get() return { 'homepage': homepage, 'privacy_policy_link': siteSettings.privacy_policy_link } except MultipleObjectsReturned as e: print(e, flush=True) return { 'homepage': None }
def __call__(self, request): # Code to be executed for each request before # the view (and later middleware) are called. siteSettings = get_site_settings_from_default_site() if not siteSettings.social_login_enabled: # return 404 for social login urls if request.path_info in self.sociallogin_urls: # todo: render nicer 404 templates # print('Dropped in sociallogin_urls', flush=True) return HttpResponse('Page not found', status=404) response = self.get_response(request) # Code to be executed for each request/response after # the view is called. return response
def sendEmailNotificationsToDonor(user_email, subject, textStr, htmlStr): # setDonorLanguagePreference(user) site_settings = get_site_settings_from_default_site() # default_from_name is an I18nCharField if str(site_settings.default_from_name): from_email = '%s <%s>' % (str( site_settings.default_from_name), site_settings.default_from_email) else: from_email = site_settings.default_from_email try: send_mail(str(subject), textStr, from_email, [user_email], html_message=htmlStr) except Exception as e: print("Cannot send '" + str(subject) + "' to '" + user_email + "': " + str(e), flush=True)
def getPayPalSettings(): siteSettings = get_site_settings_from_default_site() if (siteSettings.sandbox_mode): environment = SandboxEnvironment( client_id=siteSettings.paypal_sandbox_api_client_id, client_secret=siteSettings.paypal_sandbox_api_secret_key) api_url = 'https://api-m.sandbox.paypal.com' return SettingsPayPal(siteSettings.sandbox_mode, siteSettings.paypal_sandbox_api_product_id, siteSettings.paypal_sandbox_api_client_id, siteSettings.paypal_sandbox_api_secret_key, siteSettings.paypal_sandbox_api_webhook_id, environment, api_url) environment = LiveEnvironment( client_id=siteSettings.paypal_api_client_id, client_secret=siteSettings.paypal_api_secret_key) api_url = 'https://api-m.paypal.com' return SettingsPayPal(siteSettings.sandbox_mode, siteSettings.paypal_api_product_id, siteSettings.paypal_api_client_id, siteSettings.paypal_api_secret_key, siteSettings.paypal_api_webhook_id, environment, api_url)
def my_renewals(request, id): # deleted=False should be valid whether soft-delete mode is on or off subscription = get_object_or_404(Subscription, id=id, deleted=False) try: if subscription.user == request.user: renewals = Donation.objects.filter( subscription=subscription, deleted=False).order_by('-donation_date') siteSettings = get_site_settings_from_default_site() return render( request, 'donations/my_renewals.html', { 'subscription': subscription, 'renewals': renewals, 'siteSettings': siteSettings }) else: raise PermissionError( _('You are not authorized to view renewals of subscription %(id)d.' ) % {'id': id}) except PermissionError as e: _exception(str(e)) messages.add_message(request, messages.ERROR, str(e)) return redirect('donations:my-recurring-donations')
def is_auto_signup_allowed(self, request, sociallogin): # Very Important: if connect is made in pre_social_login, this method should then be never called! (According to allauth source code) # then decide if social login can skip signup form (draw flag from siteSettings) siteSettings = get_site_settings_from_default_site() return siteSettings.social_skip_signup
def confirm_donation(request): try: siteSettings = get_site_settings_from_default_site() tmpd = TempDonation.objects.get( pk=request.session.get('temp_donation_id', None)) paymentMethod = displayGateway(tmpd) isGatewayHostedBool = isGatewayHosted(tmpd.gateway) if request.method == 'POST': # determine path based on submit-choice if request.POST.get('submit-choice', '') == 'change-submit': # goes back to step 1 which is donation details return redirect('donations:donate') elif request.POST.get('submit-choice', '') == 'confirm-submit': # proceed with the rest of the payment procedures # create processing donation transaction_id = gen_transaction_id(gateway=tmpd.gateway) donation = Donation( is_test=tmpd.is_test, transaction_id=transaction_id, user=request.user if request.user.is_authenticated else None, form=tmpd.form, gateway=tmpd.gateway, is_recurring=tmpd.is_recurring, donation_amount=tmpd.donation_amount, currency=tmpd.currency, guest_email=tmpd.guest_email if not request.user.is_authenticated else '', payment_status=STATUS_PROCESSING, metas=temp_donation_meta_to_donation_meta( tmpd.temp_metas.all()), donation_date=datetime.now(timezone.utc), ) # create a processing subscription if is_recurring if tmpd.is_recurring: # create new Subscription object, with a temporary profile_id created by uuidv4 # user should have been authenticated according to flow logic subscription = Subscription( is_test=tmpd.is_test, profile_id=uuid4_str(), user=request.user if request.user.is_authenticated else None, gateway=tmpd.gateway, recurring_amount=tmpd.donation_amount, currency=tmpd.currency, recurring_status=STATUS_PROCESSING, subscribe_date=datetime.now(timezone.utc)) subscription.save() # link subscription to the donation donation.subscription = subscription donation.save() request.session.pop('temp_donation_id') # delete temp donation instead of saving it as processed tmpd.delete() # tmpd.status = STATUS_PROCESSED # tmpd.save() if 'first_time_registration' in request.session: dpmeta = DonationPaymentMeta( donation=donation, field_key='is_user_first_donation', field_value=request.session['first_time_registration']) dpmeta.save() request.session.pop('first_time_registration') # redirect to payment_gateway gatewayManager = InitPaymentGateway(request, donation=donation) return gatewayManager.redirect_to_gateway_url() else: raise Exception( _('No valid submit-choice is being submitted.')) except TempDonation.DoesNotExist as e: messages.add_message( request, messages.ERROR, str( _('Session data has expired. Please enter the donation details again.' ))) return redirect('donations:donate') except Exception as e: # Should rarely happen, but in case some bugs or order id repeats itself _exception(str(e)) return render( request, 'donations/confirm_donation.html', { 'tmpd': tmpd, 'paymentMethod': paymentMethod, 'isGatewayHosted': isGatewayHostedBool })
def displayGateway(instance): ''' instance can be either TempDonation, Donation or Subscription''' siteSettings = get_site_settings_from_default_site() return getattr(siteSettings, instance.gateway.frontend_label_attr_name, instance.gateway.title)
def __init__(self, *args, **kwargs): self.siteSettings = get_site_settings_from_default_site() super().__init__(*args, **kwargs)
def getOfflineSettings(): ''' Seems there's no need to have separate sets of sandbox/live settings here ''' siteSettings = get_site_settings_from_default_site() return SettingsOffline(siteSettings.sandbox_mode, siteSettings.offline_instructions_text, siteSettings.offline_thankyou_text)
def donate(request): try: siteSettings = get_site_settings_from_default_site() form_template = 'donations/donation_details_form.html' form_blueprint = siteSettings.donation_form if not form_blueprint: raise Exception(_('Donation Form not yet set.')) if request.method == 'POST': form = DonationDetailsForm(request.POST, request=request, blueprint=form_blueprint, label_suffix='') if form.is_valid(): # extract temp meta data temp_donation_metas = extract_temp_donation_meta(request.POST) # process donation amount if form.cleaned_data.get( 'donation_amount_custom', None ) and form.cleaned_data['donation_amount_custom'] > 0: is_amount_custom = True donation_amount = form.cleaned_data[ 'donation_amount_custom'] else: is_amount_custom = False donation_amount = form.cleaned_data['donation_amount'] # create/edit a pending temporary donation object payment_gateway = PaymentGateway.objects.get( pk=form.cleaned_data['payment_gateway']) if request.session.get('temp_donation_id', ''): temp_donation = TempDonation.objects.get( pk=request.session.get('temp_donation_id')) temp_donation.gateway = payment_gateway temp_donation.is_amount_custom = is_amount_custom temp_donation.is_recurring = True if form.cleaned_data[ 'donation_frequency'] == 'monthly' else False temp_donation.donation_amount = donation_amount temp_donation.currency = form.cleaned_data['currency'] temp_donation.temp_metas = temp_donation_metas temp_donation.guest_email = form.cleaned_data.get( 'email', '') temp_donation.save() else: temp_donation = TempDonation( is_test=siteSettings.sandbox_mode, form=form_blueprint, gateway=payment_gateway, is_amount_custom=is_amount_custom, is_recurring=True if form.cleaned_data['donation_frequency'] == 'monthly' else False, donation_amount=donation_amount, currency=form.cleaned_data['currency'], status=STATUS_PENDING, temp_metas=temp_donation_metas, guest_email=form.cleaned_data.get('email', ''), ) temp_donation.save() request.session['temp_donation_id'] = temp_donation.id # determine path based on submit-choice if request.POST.get('submit-choice', '') == 'guest-submit' or request.POST.get( 'submit-choice', '') == 'loggedin-submit': # skip to step 3 which is Donation Confirmation return redirect('donations:confirm-donation') elif request.POST.get('submit-choice', '') == 'register-submit': # proceed to step 2 which is Register or Login return redirect('donations:register-signin') else: raise Exception( _('No valid submit-choice is being submitted.')) else: form = DonationDetailsForm(request=request, blueprint=form_blueprint, label_suffix='') # see: https://docs.djangoproject.com/en/3.0/ref/forms/api/#django.forms.Form.field_order if form_blueprint.isAmountSteppedCustom(): form.order_fields([ 'donation_amount', 'donation_amount_custom', 'donation_frequency', 'payment_gateway', 'email' ]) else: form.order_fields([ 'donation_amount', 'donation_frequency', 'payment_gateway', 'email' ]) except Exception as e: # Should rarely happen, but in case some bugs or order id repeats itself _exception(str(e)) messages.add_message(request, messages.ERROR, str(e)) return redirect('donations:donate') # get offline gateway id and instructions text offline_gateway = PaymentGateway.objects.get(title=GATEWAY_OFFLINE) offline_gateway_id = offline_gateway.id offlineSettings = getOfflineSettings() # manually casting offline_instructions_text from LazyI18nString to str to avoid the "richtext expects a string" error in the template offline_instructions_html = str(offlineSettings.offline_instructions_text) return render( request, form_template, { 'form': form, 'donation_details_fields': DONATION_DETAILS_FIELDS, 'offline_gateway_id': offline_gateway_id, 'offline_instructions_html': offline_instructions_html })