Merge pull request #6183 from saurabh6790/subscription_support
provision to handle PayPal and Razoapay subscription charge notifications
This commit is contained in:
commit
d80fd366e7
6 changed files with 115 additions and 15 deletions
|
|
@ -458,8 +458,10 @@ def _set_limits(context, site, limits):
|
|||
frappe.connect()
|
||||
new_limits = {}
|
||||
for limit, value in limits:
|
||||
if limit not in ('daily_emails', 'emails', 'space', 'users', 'email_group',
|
||||
'expiry', 'support_email', 'support_chat', 'upgrade_url'):
|
||||
if limit not in ('daily_emails', 'emails', 'space', 'users', 'email_group', 'currency',
|
||||
'expiry', 'support_email', 'support_chat', 'upgrade_url', 'subscription_id',
|
||||
'subscription_type', 'current_plan', 'subscription_base_price', 'upgrade_plan',
|
||||
'upgrade_base_price'):
|
||||
frappe.throw(_('Invalid limit {0}').format(limit))
|
||||
|
||||
if limit=='expiry' and value:
|
||||
|
|
@ -468,7 +470,7 @@ def _set_limits(context, site, limits):
|
|||
except ValueError:
|
||||
raise ValueError("Incorrect data format, should be YYYY-MM-DD")
|
||||
|
||||
elif limit=='space':
|
||||
elif limit in ('space', 'subscription_base_price', 'upgrade_base_price'):
|
||||
value = float(value)
|
||||
|
||||
elif limit in ('users', 'emails', 'email_group', 'daily_emails'):
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
"label": "Integration Type",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "\nHost\nRemote",
|
||||
"options": "\nHost\nRemote\nSubscription Notification",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
|
|
@ -252,7 +252,7 @@
|
|||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-03-08 14:40:00.783063",
|
||||
"modified": "2019-10-09 14:40:00.783063",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Integrations",
|
||||
"name": "Integration Request",
|
||||
|
|
|
|||
|
|
@ -68,10 +68,10 @@ import frappe
|
|||
import json
|
||||
from frappe import _
|
||||
from datetime import datetime
|
||||
from frappe.utils import get_url, call_hook_method, cint, get_timestamp, cstr, now, date_diff, get_datetime
|
||||
from six.moves.urllib.parse import urlencode
|
||||
from frappe.model.document import Document
|
||||
from frappe.integrations.utils import create_request_log, make_post_request, create_payment_gateway
|
||||
from frappe.utils import get_url, call_hook_method, cint, get_timestamp, cstr, now, date_diff, get_datetime
|
||||
|
||||
|
||||
api_path = '/api/method/frappe.integrations.doctype.paypal_settings.paypal_settings'
|
||||
|
|
@ -367,3 +367,53 @@ def manage_recurring_payment_profile_status(profile_id, action, args, url):
|
|||
if response.get("ACK")[0] != "Success":
|
||||
frappe.throw(_("Failed while amending subscription"))
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def ipn_handler():
|
||||
try:
|
||||
data = frappe.local.form_dict
|
||||
|
||||
validate_ipn_request(data)
|
||||
|
||||
data.update({
|
||||
"payment_gateway": "PayPal"
|
||||
})
|
||||
|
||||
doc = frappe.get_doc({
|
||||
"data": json.dumps(frappe.local.form_dict),
|
||||
"doctype": "Integration Request",
|
||||
"integration_type": "Subscription Notification",
|
||||
"status": "Queued"
|
||||
}).insert(ignore_permissions=True)
|
||||
frappe.db.commit()
|
||||
|
||||
frappe.enqueue(method='frappe.integrations.doctype.paypal_settings.paypal_settings.handle_subscription_notification',
|
||||
queue='long', timeout=600, is_async=True, **{"doctype": "Integration Request", "docname": doc.name})
|
||||
|
||||
except frappe.InvalidStatusError:
|
||||
pass
|
||||
except Exception as e:
|
||||
frappe.log(frappe.log_error(title=e))
|
||||
|
||||
def validate_ipn_request(data):
|
||||
def _throw():
|
||||
frappe.throw(_("In Valid Request"), exc=frappe.InvalidStatusError)
|
||||
|
||||
if not data.get("recurring_payment_id"):
|
||||
_throw()
|
||||
|
||||
doc = frappe.get_doc("PayPal Settings")
|
||||
params, url = doc.get_paypal_params_and_url()
|
||||
|
||||
params.update({
|
||||
"METHOD": "GetRecurringPaymentsProfileDetails",
|
||||
"PROFILEID": data.get("recurring_payment_id")
|
||||
})
|
||||
|
||||
params = urlencode(params)
|
||||
res = make_post_request(url=url, data=params.encode("utf-8"))
|
||||
|
||||
if res['ACK'][0] != 'Success':
|
||||
_throw()
|
||||
|
||||
def handle_subscription_notification(doctype, docname):
|
||||
call_hook_method("handle_subscription_notification", doctype=doctype, docname=docname)
|
||||
|
|
|
|||
|
|
@ -119,7 +119,6 @@ class RazorpaySettings(Document):
|
|||
"content-type": "application/json"
|
||||
}
|
||||
)
|
||||
|
||||
if not resp.get('id'):
|
||||
frappe.log_error(str(resp), 'Razorpay Failed while creating subscription')
|
||||
except:
|
||||
|
|
@ -283,13 +282,12 @@ class RazorpaySettings(Document):
|
|||
})
|
||||
|
||||
return settings
|
||||
|
||||
|
||||
|
||||
def cancel_subscription(self, subscription_id):
|
||||
settings = self.get_settings()
|
||||
|
||||
settings = self.get_settings({})
|
||||
|
||||
try:
|
||||
resp = make_get_request("https://api.razorpay.com/v1/subscriptions/{0}/cancel"
|
||||
resp = make_post_request("https://api.razorpay.com/v1/subscriptions/{0}/cancel"
|
||||
.format(subscription_id), auth=(settings.api_key,
|
||||
settings.api_secret))
|
||||
except Exception:
|
||||
|
|
@ -329,5 +327,54 @@ def capture_payment(is_sandbox=False, sanbox_response=None):
|
|||
def convert_rupee_to_paisa(**kwargs):
|
||||
for addon in kwargs.get('addons'):
|
||||
addon['item']['amount'] *= 100
|
||||
|
||||
frappe.conf.converted_rupee_to_paisa = True
|
||||
|
||||
frappe.conf.converted_rupee_to_paisa = True
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def razorpay_subscription_callback():
|
||||
try:
|
||||
data = frappe.local.form_dict
|
||||
|
||||
validate_payment_callback(data)
|
||||
|
||||
data.update({
|
||||
"payment_gateway": "Razorpay"
|
||||
})
|
||||
|
||||
doc = frappe.get_doc({
|
||||
"data": json.dumps(frappe.local.form_dict),
|
||||
"doctype": "Integration Request",
|
||||
"integration_type": "Subscription Notification",
|
||||
"status": "Queued"
|
||||
}).insert(ignore_permissions=True)
|
||||
frappe.db.commit()
|
||||
|
||||
frappe.enqueue(method='frappe.integrations.doctype.razorpay_settings.razorpay_settings.handle_subscription_notification',
|
||||
queue='long', timeout=600, is_async=True, **{"doctype": "Integration Request", "docname": doc.name})
|
||||
|
||||
except frappe.InvalidStatusError:
|
||||
pass
|
||||
except Exception as e:
|
||||
frappe.log(frappe.log_error(title=e))
|
||||
|
||||
def validate_payment_callback(data):
|
||||
def _throw():
|
||||
frappe.throw(_("Invalid Subscription"), exc=frappe.InvalidStatusError)
|
||||
|
||||
subscription_id = data.get('payload').get("subscription").get("entity").get("id")
|
||||
|
||||
if not(subscription_id):
|
||||
_throw()
|
||||
|
||||
controller = frappe.get_doc("Razorpay Settings")
|
||||
|
||||
settings = controller.get_settings(data)
|
||||
|
||||
resp = make_get_request("https://api.razorpay.com/v1/subscriptions/{0}".format(subscription_id),
|
||||
auth=(settings.api_key, settings.api_secret))
|
||||
|
||||
if resp.get("status") != "active":
|
||||
_throw()
|
||||
|
||||
def handle_subscription_notification(doctype, docname):
|
||||
call_hook_method("handle_subscription_notification", doctype=doctype, docname=docname)
|
||||
|
|
@ -112,4 +112,4 @@ def create_payment_gateway(gateway, settings=None, controller=None):
|
|||
|
||||
def json_handler(obj):
|
||||
if isinstance(obj, (datetime.date, datetime.timedelta, datetime.datetime)):
|
||||
return text_type(obj)
|
||||
return text_type(obj)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
no_cache = True
|
||||
|
||||
def get_context(context):
|
||||
token = frappe.local.form_dict.token
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue