I am attempting to implement a PayPal gateway after user sign-up for a webapp. Once the user registration form is submitted, a signal sets the user to inactive (on purpose). I want to set the user to active after a successful PayPal payment; however, Im having trouble identifying how to get the user id to the receiver to activate the user account since the PayPal button has a separate landing page (and the user isn't authenticated at this point).
Is it possible to pass the newly created user instance from the registration page as context to the payment-process page? Any help would be greatly appreciated.
Code below: VIEWS
def register(request):
if request.method == "POST":
form = RegisterForm(request.POST)
if form.is_valid():
form.save()
return redirect("process-payment")
else:
# create empty form for user to fill in
form = RegisterForm()
return render(request, "register/register.html", {"form": form})
def payment_done(request):
return redirect('login')
def process_payment(request):
host = request.get_host()
paypal_dict = {
"cmd": "_xclick-subscriptions",
'business': settings.PAYPAL_RECEIVER_EMAIL,
"a3": "1.75", # monthly price
"p3": "1", # duration of each unit (depends on unit)
"t3": "M", # duration unit ("M for Month")
"src": "1", # make payments recur
"sra": "1", # reattempt payment on payment error
"no_note": "1", # remove extra notes (optional)
'item_name': 'subscription',
'custom': f"{}", # User ID passed here
'currency_code': 'USD',
'notify_url': f'http://{host}{reverse("paypal-ipn")}',
'return_url': f'http://{host}{reverse("payment-done")}',
'cancel_return': f'http://{host}{reverse("payment-cancelled")}',
}
form = PayPalPaymentsForm(initial=paypal_dict, button_type="subscribe")
return render(request, 'main/process-payment.html', {"form":form})
SIGNALS
@receiver(post_save, sender=User)
def set_user_inactive(sender, instance, created, update_fields, **kwargs):
if created:
instance.is_active = False
instance.save()
@receiver(valid_ipn_received)
def ipn_receiver(sender, **kwargs):
ipn_obj = sender
# check for subscription signup IPN
if ipn_obj.txn_type == "subscr_signup":
# get user id and activate the account
id = ipn_obj.custom
user = User.objects.get(id=id)
user.is_active = True
user.save()
subject = 'Registration Complete'
message = 'Thanks for signing up with our appl!'
email = EmailMessage(subject,
message,
'[email protected]',
[user.email])
email.send()
# check for subscription payment IPN
elif ipn_obj.txn_type == "subscr_payment":
# get user id and extend the subscription
id = ipn_obj.custom
user = User.objects.get(id=id)
user.extend() # extend the subscription
subject = 'Your Invoice for {} is available'.format(
datetime.strftime(datetime.now(), "%b %Y"))
message = 'Thanks for using our app. This is a reoccurring payment notification for your subscription ' \
'to our app. $1.75 charged to your account.'
email = EmailMessage(subject,
message,
'[email protected]',
[user.email])
email.send()
# check for failed subscription payment IPN
elif ipn_obj.txn_type == "subscr_failed":
pass
# check for subscription cancellation IPN
elif ipn_obj.txn_type == "subscr_cancel":
pass
That is a very old, deprecated legacy integration method. Do not use it for new integrations.
See the current PayPal Subscription documentation. You can create plans via its API calls (authenticate with a clientid and secret to obtain an access token) or in the account's web interface: