Django-Paypal IPNs 在 Django 管理中标记为重复 txn_id
Django-Paypal IPNs flagged Duplicate txn_id in Django admin
我已经使用 Django-paypal 在我的 Django 应用程序中实现了 Paypal 集成
除此之外,我还根据文档设置了信号接收器。
但问题是:每次有人付款时,即使我将随机发票 ID 与 paypal 字典一起传递,它也会被标记为重复。
这是我尝试过的方法:
来自 views.py:
def generate_cid():
chars = "".join([random.choice(string.ascii_lowercase) for i in range(5)])
digits = "".join([random.choice(string.digits) for i in range(4)])
cid = digits + chars
return cid
def payment_process(request):
minutes = int(request.user.tagging.count()) * 5
testhours = minutes / 60
hours = ''
if request.user.tagging.count() > 11:
# hours = str(round(testhours, 3))
hours = 5
# invoice = generate_cid()
user_info = {
"name": str(request.user.first_name + ' ' + request.user.last_name),
"hours": str(hours),
"taggedArticles": str(request.user.tagging.count()),
"email": str(request.user.email),
"date": str(datetime.date.today()),
}
paypal_dict = {
"business": settings.PAYPAL_RECEIVER_EMAIL,
"item_name": "Certificate of Completion",
"custom": json.dumps(user_info),
"invoice": str(generate_cid()),
"amount": "95.00",
"currency_code": "USD",
"notify_url": settings.host + '/users/paypal',
"return_url": settings.host + "/users/done/",
"cancel_return": settings.host + "/users/cancel/",
}
# Create the instance.
form = PayPalPaymentsForm(initial=paypal_dict)
context = {"form": form}
return render(request, "users/generateCert.html", context)
来自 signals.py:
def show_me_the_money(sender, **kwargs):
ipn_obj = sender
# Undertake some action depending upon `ipn_obj`.
if ipn_obj.payment_status == ST_PP_COMPLETED:
print('Payment is completed')
user_infor = ast.literal_eval(ipn_obj.custom)
if ipn_obj.receiver_email == settings.PAYPAL_RECEIVER_EMAIL:
print('And Payment is valid')
# generate and send an email with pdf certificate file to the user's email
user_infor = ast.literal_eval(ipn_obj.custom)
user_info = {
"name": user_infor['name'],
"hours": user_infor['hours'],
"taggedArticles": user_infor['taggedArticles'],
"email": user_infor['email'],
"date": user_infor['date'],
}
html = render_to_string('users/certificate_template.html',
{'user': user_info})
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'filename=certificate_{}'.format(user_info['name']) + '.pdf'
pdf = weasyprint.HTML(string=html, base_url='http://8d8093d5.ngrok.io/users/process/').write_pdf(
stylesheets=[weasyprint.CSS(string='body { font-family: serif}')])
to_emails = [str(user_infor['email'])]
subject = "Certificate from Nami Montana"
email = EmailMessage(subject, body=pdf, from_email=settings.EMAIL_HOST_USER, to=to_emails)
email.attach("certificate_{}".format(user_infor['name']) + '.pdf', pdf, "application/pdf")
email.content_subtype = "pdf" # Main content is now text/html
email.encoding = 'us-ascii'
email.send()
@receiver(invalid_ipn_received)
def do_not_show_me_the_money(sender, **kwargs):
print('And Payment is not valid')
ipn_obj = sender
user_infor = ast.literal_eval(ipn_obj.custom)
to_emails = [str(user_infor['email'])]
subject = "Certificate"
# message = 'Enjoy your certificate.'
email = EmailMessage(subject, body='Unfortunately, there\'s something wrong with your payment.Check your'
+ 'paypal account, please!',
from_email=settings.EMAIL_HOST_USER, to=to_emails)
# email.content_subtype = "pdf" # Main content is now text/html
# email.encoding = 'us-ascii'
email.send()
valid_ipn_received.connect(show_me_the_money)
Actually, I'm receiving both (Success & Fail) signals with a short difference of time(approx 2 min) for a single transaction.
And below is the screenshot for how IPNs received in Django admin:
Also, From the console:
在 signals.py 有效和无效的 IPN 都被调用,这就是为什么它 returns 在发送电子邮件之前无效的 IPN。
这是正确且有效的 signals.py:
def show_me_the_money(sender, **kwargs):
ipn_obj = sender
# Undertake some action depending upon `ipn_obj`.
if ipn_obj.payment_status == ST_PP_COMPLETED:
print('Payment is completed')
user_infor = ast.literal_eval(ipn_obj.custom)
if ipn_obj.receiver_email == settings.PAYPAL_RECEIVER_EMAIL:
print('And Payment is valid')
# generate and send an email with pdf certificate file to the user's email
user_infor = ast.literal_eval(ipn_obj.custom)
user_info = {
"name": user_infor['name'],
"hours": user_infor['hours'],
"taggedArticles": user_infor['taggedArticles'],
"email": user_infor['email'],
"date": user_infor['date'],
}
html = render_to_string('users/certificate_template.html',
{'user': user_info})
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'filename=certificate_{}'.format(user_info['name']) + '.pdf'
pdf = weasyprint.HTML(string=html, base_url='http://8d8093d5.ngrok.io/users/process/').write_pdf(
stylesheets=[weasyprint.CSS(string='body { font-family: serif}')])
to_emails = [str(user_infor['email'])]
subject = "Certificate from Nami Montana"
email = EmailMessage(subject, body=pdf, from_email=settings.EMAIL_HOST_USER, to=to_emails)
email.attach("certificate_{}".format(user_infor['name']) + '.pdf', pdf, "application/pdf")
email.content_subtype = "pdf" # Main content is now text/html
email.encoding = 'us-ascii'
email.send()
else:
payment_was_flagged.connect(do_not_show_me_the_money)
def do_not_show_me_the_money(sender, **kwargs):
print('And Payment is not valid')
ipn_obj = sender
user_infor = ast.literal_eval(ipn_obj.custom)
to_emails = [str(user_infor['email'])]
subject = "Certificate from Nami Montana"
# message = 'Enjoy your certificate.'
email = EmailMessage(subject, body='Unfortunately, there\'s something wrong with your payment as it\'s'
'not validated.Check your PayPal account, please!',
from_email=settings.EMAIL_HOST_USER, to=to_emails)
email.send()
valid_ipn_received.connect(show_me_the_money)
Just need to call invalid_ipn only in case of an invalid payment.
我已经使用 Django-paypal 在我的 Django 应用程序中实现了 Paypal 集成 除此之外,我还根据文档设置了信号接收器。 但问题是:每次有人付款时,即使我将随机发票 ID 与 paypal 字典一起传递,它也会被标记为重复。
这是我尝试过的方法:
来自 views.py:
def generate_cid():
chars = "".join([random.choice(string.ascii_lowercase) for i in range(5)])
digits = "".join([random.choice(string.digits) for i in range(4)])
cid = digits + chars
return cid
def payment_process(request):
minutes = int(request.user.tagging.count()) * 5
testhours = minutes / 60
hours = ''
if request.user.tagging.count() > 11:
# hours = str(round(testhours, 3))
hours = 5
# invoice = generate_cid()
user_info = {
"name": str(request.user.first_name + ' ' + request.user.last_name),
"hours": str(hours),
"taggedArticles": str(request.user.tagging.count()),
"email": str(request.user.email),
"date": str(datetime.date.today()),
}
paypal_dict = {
"business": settings.PAYPAL_RECEIVER_EMAIL,
"item_name": "Certificate of Completion",
"custom": json.dumps(user_info),
"invoice": str(generate_cid()),
"amount": "95.00",
"currency_code": "USD",
"notify_url": settings.host + '/users/paypal',
"return_url": settings.host + "/users/done/",
"cancel_return": settings.host + "/users/cancel/",
}
# Create the instance.
form = PayPalPaymentsForm(initial=paypal_dict)
context = {"form": form}
return render(request, "users/generateCert.html", context)
来自 signals.py:
def show_me_the_money(sender, **kwargs):
ipn_obj = sender
# Undertake some action depending upon `ipn_obj`.
if ipn_obj.payment_status == ST_PP_COMPLETED:
print('Payment is completed')
user_infor = ast.literal_eval(ipn_obj.custom)
if ipn_obj.receiver_email == settings.PAYPAL_RECEIVER_EMAIL:
print('And Payment is valid')
# generate and send an email with pdf certificate file to the user's email
user_infor = ast.literal_eval(ipn_obj.custom)
user_info = {
"name": user_infor['name'],
"hours": user_infor['hours'],
"taggedArticles": user_infor['taggedArticles'],
"email": user_infor['email'],
"date": user_infor['date'],
}
html = render_to_string('users/certificate_template.html',
{'user': user_info})
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'filename=certificate_{}'.format(user_info['name']) + '.pdf'
pdf = weasyprint.HTML(string=html, base_url='http://8d8093d5.ngrok.io/users/process/').write_pdf(
stylesheets=[weasyprint.CSS(string='body { font-family: serif}')])
to_emails = [str(user_infor['email'])]
subject = "Certificate from Nami Montana"
email = EmailMessage(subject, body=pdf, from_email=settings.EMAIL_HOST_USER, to=to_emails)
email.attach("certificate_{}".format(user_infor['name']) + '.pdf', pdf, "application/pdf")
email.content_subtype = "pdf" # Main content is now text/html
email.encoding = 'us-ascii'
email.send()
@receiver(invalid_ipn_received)
def do_not_show_me_the_money(sender, **kwargs):
print('And Payment is not valid')
ipn_obj = sender
user_infor = ast.literal_eval(ipn_obj.custom)
to_emails = [str(user_infor['email'])]
subject = "Certificate"
# message = 'Enjoy your certificate.'
email = EmailMessage(subject, body='Unfortunately, there\'s something wrong with your payment.Check your'
+ 'paypal account, please!',
from_email=settings.EMAIL_HOST_USER, to=to_emails)
# email.content_subtype = "pdf" # Main content is now text/html
# email.encoding = 'us-ascii'
email.send()
valid_ipn_received.connect(show_me_the_money)
Actually, I'm receiving both (Success & Fail) signals with a short difference of time(approx 2 min) for a single transaction.
And below is the screenshot for how IPNs received in Django admin:
Also, From the console:
在 signals.py 有效和无效的 IPN 都被调用,这就是为什么它 returns 在发送电子邮件之前无效的 IPN。
这是正确且有效的 signals.py:
def show_me_the_money(sender, **kwargs):
ipn_obj = sender
# Undertake some action depending upon `ipn_obj`.
if ipn_obj.payment_status == ST_PP_COMPLETED:
print('Payment is completed')
user_infor = ast.literal_eval(ipn_obj.custom)
if ipn_obj.receiver_email == settings.PAYPAL_RECEIVER_EMAIL:
print('And Payment is valid')
# generate and send an email with pdf certificate file to the user's email
user_infor = ast.literal_eval(ipn_obj.custom)
user_info = {
"name": user_infor['name'],
"hours": user_infor['hours'],
"taggedArticles": user_infor['taggedArticles'],
"email": user_infor['email'],
"date": user_infor['date'],
}
html = render_to_string('users/certificate_template.html',
{'user': user_info})
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'filename=certificate_{}'.format(user_info['name']) + '.pdf'
pdf = weasyprint.HTML(string=html, base_url='http://8d8093d5.ngrok.io/users/process/').write_pdf(
stylesheets=[weasyprint.CSS(string='body { font-family: serif}')])
to_emails = [str(user_infor['email'])]
subject = "Certificate from Nami Montana"
email = EmailMessage(subject, body=pdf, from_email=settings.EMAIL_HOST_USER, to=to_emails)
email.attach("certificate_{}".format(user_infor['name']) + '.pdf', pdf, "application/pdf")
email.content_subtype = "pdf" # Main content is now text/html
email.encoding = 'us-ascii'
email.send()
else:
payment_was_flagged.connect(do_not_show_me_the_money)
def do_not_show_me_the_money(sender, **kwargs):
print('And Payment is not valid')
ipn_obj = sender
user_infor = ast.literal_eval(ipn_obj.custom)
to_emails = [str(user_infor['email'])]
subject = "Certificate from Nami Montana"
# message = 'Enjoy your certificate.'
email = EmailMessage(subject, body='Unfortunately, there\'s something wrong with your payment as it\'s'
'not validated.Check your PayPal account, please!',
from_email=settings.EMAIL_HOST_USER, to=to_emails)
email.send()
valid_ipn_received.connect(show_me_the_money)
Just need to call invalid_ipn only in case of an invalid payment.