Ver código fonte

finalize recurring payments for paypal

pull/2/head
Saurabh 6 anos atrás
pai
commit
7f116b7bdc
1 arquivos alterados com 78 adições e 89 exclusões
  1. +78
    -89
      payments/payment_gateways/doctype/paypal_settings/paypal_settings.py

+ 78
- 89
payments/payment_gateways/doctype/paypal_settings/paypal_settings.py Ver arquivo

@@ -68,11 +68,14 @@ import frappe
import json
from frappe import _
from datetime import datetime
from frappe.utils import get_url, call_hook_method, cint, get_timestamp
from frappe.utils import get_url, call_hook_method, cint, get_timestamp, cstr, nowdate, date_diff
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


api_path = '/api/method/frappe.integrations.doctype.paypal_settings.paypal_settings'

class PayPalSettings(Document):
supported_currencies = ["AUD", "BRL", "CAD", "CZK", "DKK", "EUR", "HKD", "HUF", "ILS", "JPY", "MYR", "MXN",
"TWD", "NZD", "NOK", "PHP", "PLN", "GBP", "RUB", "SGD", "SEK", "CHF", "THB", "TRY", "USD"]
@@ -144,9 +147,8 @@ class PayPalSettings(Document):
"token": response.get("TOKEN")[0],
"correlation_id": response.get("CORRELATIONID")[0]
})
print(kwargs)
self.integration_request = create_request_log(kwargs, "Remote", "PayPal", response.get("TOKEN")[0])
print(return_url.format(kwargs["token"]))
return return_url.format(kwargs["token"])

def execute_set_express_checkout(self, **kwargs):
@@ -154,49 +156,61 @@ class PayPalSettings(Document):

params.update({
"METHOD": "SetExpressCheckout",
"returnUrl": get_url("/api/method/frappe.integrations.doctype.paypal_settings.paypal_settings.get_express_checkout_details"),
"cancelUrl": get_url("/payment-cancel")
"returnUrl": get_url("{0}.get_express_checkout_details".format(api_path)),
"cancelUrl": get_url("/payment-cancel"),
"PAYMENTREQUEST_0_PAYMENTACTION": "SALE",
"PAYMENTREQUEST_0_AMT": kwargs['amount'],
"PAYMENTREQUEST_0_CURRENCYCODE": kwargs['currency'].upper()
})
if kwargs.get('subscription_details'):
params.update({
"L_BILLINGTYPE0": "RecurringPayments", #The type of billing agreement
"L_BILLINGAGREEMENTDESCRIPTION0": kwargs['description']
})
else:
params.update({
"PAYMENTREQUEST_0_PAYMENTACTION": "SALE",
"PAYMENTREQUEST_0_AMT": kwargs['amount'],
"PAYMENTREQUEST_0_CURRENCYCODE": kwargs['currency'].upper(),
})
self.configure_recurring_payments(params, kwargs)

params = urlencode(params)

response = make_post_request(url, data=params.encode("utf-8"))

if response.get("ACK")[0] != "Success":
frappe.throw(_("Looks like something is wrong with this site's Paypal configuration."))

return response
def cancel_recurring_profile(self, **kwargs):
params, url = self.get_paypal_params_and_url()

if not kwargs.get('profile_id'):
frappe.throw(_("PayPal Recurring Profile ID is required"))
def configure_recurring_payments(self, params, kwargs):
# removing the params as we have to setup rucurring payments
for param in ('PAYMENTREQUEST_0_PAYMENTACTION', 'PAYMENTREQUEST_0_AMT',
'PAYMENTREQUEST_0_CURRENCYCODE'):
del params[param]

params.update({
"METHOD": "ManageRecurringPaymentsProfileStatus",
"PROFILEID": kwargs['profile_id'],
"ACTION": "Cancel"
"L_BILLINGTYPE0": "RecurringPayments", #The type of billing agreement
"L_BILLINGAGREEMENTDESCRIPTION0": kwargs['description']
})

params = urlencode(params)
def get_paypal_and_transaction_details(token):
doc = frappe.get_doc("PayPal Settings")
doc.setup_sandbox_env(token)
params, url = doc.get_paypal_params_and_url()

response = make_post_request(url, data=params.encode("utf-8"))
if response.get("ACK")[0] != "Success":
frappe.throw(_("Looks like something is wrong with this site's Paypal configuration."))
integration_request = frappe.get_doc("Integration Request", token)
data = json.loads(integration_request.data)

return response
return data, params, url

def setup_redirect(data, redirect_url, custom_redirect_to=None, redirect=True):
redirect_to = data.get('redirect_to') or None
redirect_message = data.get('redirect_message') or None

if custom_redirect_to:
redirect_to = custom_redirect_to

if redirect_to:
redirect_url += '?' + urlencode({'redirect_to': redirect_to})
if redirect_message:
redirect_url += '&' + urlencode({'redirect_message': redirect_message})

# this is done so that functions called via hooks can update flags.redirect_to
if redirect:
frappe.local.response["type"] = "redirect"
frappe.local.response["location"] = get_url(redirect_url)

@frappe.whitelist(allow_guest=True, xss_safe=True)
def get_express_checkout_details(token):
@@ -225,8 +239,6 @@ def get_express_checkout_details(token):
"payerid": response.get("PAYERID")[0],
"payer_email": response.get("EMAIL")[0]
}, "Authorized", doc=doc)

frappe.local.response["type"] = "redirect"
frappe.local.response["location"] = get_redirect_uri(doc, token, response.get("PAYERID")[0])
@@ -237,19 +249,8 @@ def get_express_checkout_details(token):
@frappe.whitelist(allow_guest=True, xss_safe=True)
def confirm_payment(token):
try:
redirect = True
status_changed_to, redirect_to = None, None

doc = frappe.get_doc("PayPal Settings")
doc.setup_sandbox_env(token)

integration_request = frappe.get_doc("Integration Request", token)
data = json.loads(integration_request.data)

redirect_to = data.get('redirect_to') or None
redirect_message = data.get('redirect_message') or None
data, params, url = get_paypal_and_transaction_details(token)

params, url = doc.get_paypal_params_and_url()
params.update({
"METHOD": "DoExpressCheckoutPayment",
"PAYERID": data.get("payerid"),
@@ -272,22 +273,11 @@ def confirm_payment(token):
data.get("reference_docname")).run_method("on_payment_authorized", "Completed")
frappe.db.commit()

if custom_redirect_to:
redirect_to = custom_redirect_to

redirect_url = '/integrations/payment-success'
else:
redirect_url = "/integrations/payment-failed"

if redirect_to:
redirect_url += '?' + urlencode({'redirect_to': redirect_to})
if redirect_message:
redirect_url += '&' + urlencode({'redirect_message': redirect_message})

# this is done so that functions called via hooks can update flags.redirect_to
if redirect:
frappe.local.response["type"] = "redirect"
frappe.local.response["location"] = get_url(redirect_url)
setup_redirect(data, redirect_url, custom_redirect_to)

except Exception:
frappe.log_error(frappe.get_traceback())
@@ -295,20 +285,15 @@ def confirm_payment(token):
@frappe.whitelist(allow_guest=True, xss_safe=True)
def create_recurring_profile(token, payerid):
try:
redirect = True
status_changed_to, redirect_to = None, None

doc = frappe.get_doc("PayPal Settings")
doc.setup_sandbox_env(token)

integration_request = frappe.get_doc("Integration Request", token)
data = json.loads(integration_request.data)
data, params, url = get_paypal_and_transaction_details(token)

addons = data.get("addons")
subscription_details = data.get("subscription_details")
redirect_to = data.get('redirect_to') or None
redirect_message = data.get('redirect_message') or None
setup_subscription_amount(data, addons)

if data['subscription_id'] and addons:
manage_recurring_payment_profile_status(data['subscription_id'], 'Cancel', params, url)

params, url = doc.get_paypal_params_and_url()
params.update({
"METHOD": "CreateRecurringPaymentsProfile",
"PAYERID": payerid,
@@ -316,13 +301,13 @@ def create_recurring_profile(token, payerid):
"DESC": data.get("description"),
"BILLINGPERIOD": subscription_details.get("billing_period"),
"BILLINGFREQUENCY": subscription_details.get("billing_frequency"),
"AMT": data.get("amount"),
"AMT": data.get("amount") if data.get("subscription_amount") == data.get("amount") else data.get("subscription_amount"),
"CURRENCYCODE": data.get("currency").upper(),
"INITAMT": subscription_details.get("upfront_amount")
})

starts_at = subscription_details.get("start_date") if subscription_details.get("start_date")\
else frappe.utils.now()
starts_at = subscription_details.get("start_date") or nowdate()
status_changed_to = 'Completed' if subscription_details.get("upfront_amount") else 'Verified'

params.update({
"PROFILESTARTDATE": datetime.utcfromtimestamp(get_timestamp(starts_at)).isoformat()
@@ -336,33 +321,26 @@ def create_recurring_profile(token, payerid):
}, "Completed")

if data.get("reference_doctype") and data.get("reference_docname"):
data['subscription_details']['subscription_id'] = response.get("PROFILEID")[0]
data['subscription_id'] = response.get("PROFILEID")[0]

frappe.flags.data = data
custom_redirect_to = frappe.get_doc(data.get("reference_doctype"),
data.get("reference_docname")).run_method("on_payment_authorized", "Completed")
data.get("reference_docname")).run_method("on_payment_authorized", status_changed_to)
frappe.db.commit()

if custom_redirect_to:
redirect_to = custom_redirect_to

redirect_url = '/integrations/payment-success'
else:
redirect_url = "/integrations/payment-failed"

if redirect_to:
redirect_url += '?' + urlencode({'redirect_to': redirect_to})
if redirect_message:
redirect_url += '&' + urlencode({'redirect_message': redirect_message})

# this is done so that functions called via hooks can update flags.redirect_to
if redirect:
frappe.local.response["type"] = "redirect"
frappe.local.response["location"] = get_url(redirect_url)
setup_redirect(data, redirect_url, custom_redirect_to)

except Exception:
frappe.log_error(frappe.get_traceback())

def setup_subscription_amount(data, addons):
for addon in addons:
data['subscription_amount'] += addon['item']['amount']

def update_integration_request_status(token, data, status, error=False, doc=None):
if not doc:
doc = frappe.get_doc("Integration Request", token)
@@ -372,9 +350,20 @@ def update_integration_request_status(token, data, status, error=False, doc=None
def get_redirect_uri(doc, token, payerid):
data = json.loads(doc.data)
if data.get("subscription_details"):
return get_url( \
"/api/method/frappe.integrations.doctype.paypal_settings.paypal_settings.create_recurring_profile?token={0}&payerid={1}".format(token, payerid))
if data.get("subscription_details") or data.get("subscription_id"):
return get_url("{0}.create_recurring_profile?token={1}&payerid={2}".format(api_path, token, payerid))
else:
return get_url( \
"/api/method/frappe.integrations.doctype.paypal_settings.paypal_settings.confirm_payment?token={0}".format(token))
return get_url("{0}.confirm_payment?token={1}".format(api_path, token))

def manage_recurring_payment_profile_status(profile_id, action, args, url):
args.update({
"METHOD": "ManageRecurringPaymentsProfileStatus",
"PROFILEID": profile_id,
"ACTION": action
})

response = make_post_request(url, data=args)

if response.get("ACK")[0] != "Success":
frappe.throw(_("Failed while amending subscription"))


Carregando…
Cancelar
Salvar