Procházet zdrojové kódy

Merge branch 'version-13-pre-release' into version-13

pull/2/head
Saurabh před 4 roky
rodič
revize
8b0c7c5122
9 změnil soubory, kde provedl 359 přidání a 1 odebrání
  1. +0
    -0
      payments/payment_gateways/doctype/paytm_settings/__init__.py
  2. +8
    -0
      payments/payment_gateways/doctype/paytm_settings/paytm_settings.js
  3. +89
    -0
      payments/payment_gateways/doctype/paytm_settings/paytm_settings.json
  4. +159
    -0
      payments/payment_gateways/doctype/paytm_settings/paytm_settings.py
  5. +10
    -0
      payments/payment_gateways/doctype/paytm_settings/test_paytm_settings.py
  6. +22
    -0
      payments/payment_gateways/doctype/razorpay_settings/razorpay_settings.py
  7. +1
    -1
      payments/templates/pages/gcalendar-success.html
  8. +43
    -0
      payments/templates/pages/paytm_checkout.html
  9. +27
    -0
      payments/templates/pages/paytm_checkout.py

+ 0
- 0
payments/payment_gateways/doctype/paytm_settings/__init__.py Zobrazit soubor


+ 8
- 0
payments/payment_gateways/doctype/paytm_settings/paytm_settings.js Zobrazit soubor

@@ -0,0 +1,8 @@
// Copyright (c) 2020, Frappe Technologies and contributors
// For license information, please see license.txt

frappe.ui.form.on('Paytm Settings', {
refresh: function(frm) {
frm.dashboard.set_headline(__("For more information, {0}.", [`<a href='https://erpnext.com/docs/user/manual/en/erpnext_integration/paytm-integration'>${__('Click here')}</a>`]));
}
});

+ 89
- 0
payments/payment_gateways/doctype/paytm_settings/paytm_settings.json Zobrazit soubor

@@ -0,0 +1,89 @@
{
"actions": [],
"creation": "2020-04-02 00:11:22.846697",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"merchant_id",
"merchant_key",
"staging",
"column_break_4",
"industry_type_id",
"website"
],
"fields": [
{
"fieldname": "merchant_id",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Merchant ID",
"reqd": 1,
"show_days": 1,
"show_seconds": 1
},
{
"fieldname": "merchant_key",
"fieldtype": "Password",
"in_list_view": 1,
"label": "Merchant Key",
"reqd": 1,
"show_days": 1,
"show_seconds": 1
},
{
"default": "0",
"fieldname": "staging",
"fieldtype": "Check",
"label": "Staging",
"show_days": 1,
"show_seconds": 1
},
{
"depends_on": "eval: !doc.staging",
"fieldname": "website",
"fieldtype": "Data",
"label": "Website",
"mandatory_depends_on": "eval: !doc.staging",
"show_days": 1,
"show_seconds": 1
},
{
"fieldname": "column_break_4",
"fieldtype": "Column Break",
"show_days": 1,
"show_seconds": 1
},
{
"depends_on": "eval: !doc.staging",
"fieldname": "industry_type_id",
"fieldtype": "Data",
"label": "Industry Type ID",
"mandatory_depends_on": "eval: !doc.staging",
"show_days": 1,
"show_seconds": 1
}
],
"issingle": 1,
"links": [],
"modified": "2020-06-08 13:36:09.703143",
"modified_by": "Administrator",
"module": "Integrations",
"name": "Paytm Settings",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"print": 1,
"read": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

+ 159
- 0
payments/payment_gateways/doctype/paytm_settings/paytm_settings.py Zobrazit soubor

@@ -0,0 +1,159 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020, Frappe Technologies and contributors
# For license information, please see license.txt

from __future__ import unicode_literals
import json
import requests
from six.moves.urllib.parse import urlencode

import frappe
from frappe.model.document import Document
from frappe import _
from frappe.utils import get_url, call_hook_method, cint, flt, cstr
from frappe.integrations.utils import create_request_log, create_payment_gateway
from frappe.utils import get_request_site_address
from paytmchecksum import generateSignature, verifySignature
from frappe.utils.password import get_decrypted_password

class PaytmSettings(Document):
supported_currencies = ["INR"]

def validate(self):
create_payment_gateway('Paytm')
call_hook_method('payment_gateway_enabled', gateway='Paytm')

def validate_transaction_currency(self, currency):
if currency not in self.supported_currencies:
frappe.throw(_("Please select another payment method. Paytm does not support transactions in currency '{0}'").format(currency))

def get_payment_url(self, **kwargs):
'''Return payment url with several params'''
# create unique order id by making it equal to the integration request
integration_request = create_request_log(kwargs, "Host", "Paytm")
kwargs.update(dict(order_id=integration_request.name))

return get_url("./integrations/paytm_checkout?{0}".format(urlencode(kwargs)))

def get_paytm_config():
''' Returns paytm config '''

paytm_config = frappe.db.get_singles_dict('Paytm Settings')
paytm_config.update(dict(merchant_key=get_decrypted_password('Paytm Settings', 'Paytm Settings', 'merchant_key')))

if cint(paytm_config.staging):
paytm_config.update(dict(
website="WEBSTAGING",
url='https://securegw-stage.paytm.in/order/process',
transaction_status_url='https://securegw-stage.paytm.in/order/status',
industry_type_id='RETAIL'
))
else:
paytm_config.update(dict(
url='https://securegw.paytm.in/order/process',
transaction_status_url='https://securegw.paytm.in/order/status',
))
return paytm_config

def get_paytm_params(payment_details, order_id, paytm_config):

# initialize a dictionary
paytm_params = dict()
redirect_uri = get_request_site_address(True) + "/api/method/frappe.integrations.doctype.paytm_settings.paytm_settings.verify_transaction"


paytm_params.update({
"MID" : paytm_config.merchant_id,
"WEBSITE" : paytm_config.website,
"INDUSTRY_TYPE_ID" : paytm_config.industry_type_id,
"CHANNEL_ID" : "WEB",
"ORDER_ID" : order_id,
"CUST_ID" : payment_details['payer_email'],
"EMAIL" : payment_details['payer_email'],
"TXN_AMOUNT" : cstr(flt(payment_details['amount'], 2)),
"CALLBACK_URL" : redirect_uri,
})

checksum = generateSignature(paytm_params, paytm_config.merchant_key)

paytm_params.update({
"CHECKSUMHASH" : checksum
})

return paytm_params

@frappe.whitelist(allow_guest=True)
def verify_transaction(**paytm_params):
'''Verify checksum for received data in the callback and then verify the transaction'''
paytm_config = get_paytm_config()
is_valid_checksum = False

paytm_params.pop('cmd', None)
paytm_checksum = paytm_params.pop('CHECKSUMHASH', None)

if paytm_params and paytm_config and paytm_checksum:
# Verify checksum
is_valid_checksum = verifySignature(paytm_params, paytm_config.merchant_key, paytm_checksum)

if is_valid_checksum and paytm_params.get('RESPCODE') == '01':
verify_transaction_status(paytm_config, paytm_params['ORDERID'])
else:
frappe.respond_as_web_page("Payment Failed",
"Transaction failed to complete. In case of any deductions, deducted amount will get refunded to your account.",
http_status_code=401, indicator_color='red')
frappe.log_error("Order unsuccessful. Failed Response:"+cstr(paytm_params), 'Paytm Payment Failed')

def verify_transaction_status(paytm_config, order_id):
'''Verify transaction completion after checksum has been verified'''
paytm_params=dict(
MID=paytm_config.merchant_id,
ORDERID= order_id
)

checksum = generateSignature(paytm_params, paytm_config.merchant_key)
paytm_params["CHECKSUMHASH"] = checksum

post_data = json.dumps(paytm_params)
url = paytm_config.transaction_status_url

response = requests.post(url, data = post_data, headers = {"Content-type": "application/json"}).json()
finalize_request(order_id, response)

def finalize_request(order_id, transaction_response):
request = frappe.get_doc('Integration Request', order_id)
transaction_data = frappe._dict(json.loads(request.data))
redirect_to = transaction_data.get('redirect_to') or None
redirect_message = transaction_data.get('redirect_message') or None

if transaction_response['STATUS'] == "TXN_SUCCESS":
if transaction_data.reference_doctype and transaction_data.reference_docname:
custom_redirect_to = None
try:
custom_redirect_to = frappe.get_doc(transaction_data.reference_doctype,
transaction_data.reference_docname).run_method("on_payment_authorized", 'Completed')
request.db_set('status', 'Completed')
except Exception:
request.db_set('status', 'Failed')
frappe.log_error(frappe.get_traceback())

if custom_redirect_to:
redirect_to = custom_redirect_to

redirect_url = '/integrations/payment-success'
else:
request.db_set('status', 'Failed')
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})

frappe.local.response['type'] = 'redirect'
frappe.local.response['location'] = redirect_url

def get_gateway_controller(doctype, docname):
reference_doc = frappe.get_doc(doctype, docname)
gateway_controller = frappe.db.get_value("Payment Gateway", reference_doc.payment_gateway, "gateway_controller")
return gateway_controller

+ 10
- 0
payments/payment_gateways/doctype/paytm_settings/test_paytm_settings.py Zobrazit soubor

@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020, Frappe Technologies and Contributors
# See license.txt
from __future__ import unicode_literals

# import frappe
import unittest

class TestPaytmSettings(unittest.TestCase):
pass

+ 22
- 0
payments/payment_gateways/doctype/razorpay_settings/razorpay_settings.py Zobrazit soubor

@@ -64,6 +64,9 @@ from __future__ import unicode_literals
import frappe
from frappe import _
import json
import hmac
import razorpay
import hashlib
from six.moves.urllib.parse import urlencode
from frappe.model.document import Document
from frappe.utils import get_url, call_hook_method, cint, get_timestamp
@@ -73,6 +76,11 @@ from frappe.integrations.utils import (make_get_request, make_post_request, crea
class RazorpaySettings(Document):
supported_currencies = ["INR"]

def init_client(self):
if self.api_key:
secret = self.get_password(fieldname="api_secret", raise_exception=False)
self.client = razorpay.Client(auth=(self.api_key, secret))

def validate(self):
create_payment_gateway('Razorpay')
call_hook_method('payment_gateway_enabled', gateway='Razorpay')
@@ -317,6 +325,20 @@ class RazorpaySettings(Document):
except Exception:
frappe.log_error(frappe.get_traceback())

def verify_signature(self, body, signature, key):
key = bytes(key, 'utf-8')
body = bytes(body, 'utf-8')

dig = hmac.new(key=key, msg=body, digestmod=hashlib.sha256)

generated_signature = dig.hexdigest()
result = hmac.compare_digest(generated_signature, signature)

if not result:
frappe.throw(_('Razorpay Signature Verification Failed'), exc=frappe.PermissionError)

return result

def capture_payment(is_sandbox=False, sanbox_response=None):
"""
Verifies the purchase as complete by the merchant.


+ 1
- 1
payments/templates/pages/gcalendar-success.html Zobrazit soubor

@@ -9,7 +9,7 @@
{{ _("Success") }}</span>
</div>
<p>{{ _("Your connection request to Google Calendar was successfully accepted") }}</p>
<div><a href='{{ "/desk" }}' class='btn btn-primary btn-sm'>
<div><a href='{{ "/app" }}' class='btn btn-primary btn-sm'>
{{ _("Back to Desk") }}</a></div>
</div>
<style>


+ 43
- 0
payments/templates/pages/paytm_checkout.html Zobrazit soubor

@@ -0,0 +1,43 @@
{% extends "templates/web.html" %}

{% block title %} Payment {% endblock %}

{%- block header -%}
<head>
<title>Merchant Checkout Page</title>
</head>
{% endblock %}

{% block script %}
<script defer type="text/javascript">
document.paytm_form.submit();
</script>
{% endblock %}

{%- block page_content -%}
<body>
<div class="centered">
<h2>Please do not refresh this page...</h2>

<form method="post" action="{{ url }}" name="paytm_form">
{% for name, value in payment_details.items() %}
<input type="hidden" name="{{ name }}" value="{{ value }}">
{% endfor %}
</form>
</div>
</body>
{% endblock %}

{% block style %}
<style>
.centered {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.web-footer {
display: none;
}
</style>
{% endblock %}

+ 27
- 0
payments/templates/pages/paytm_checkout.py Zobrazit soubor

@@ -0,0 +1,27 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
from frappe import _
import json
from frappe.integrations.doctype.paytm_settings.paytm_settings import get_paytm_params, get_paytm_config

def get_context(context):
context.no_cache = 1
paytm_config = get_paytm_config()

try:
doc = frappe.get_doc("Integration Request", frappe.form_dict['order_id'])

context.payment_details = get_paytm_params(json.loads(doc.data), doc.name, paytm_config)

context.url = paytm_config.url

except Exception:
frappe.log_error()
frappe.redirect_to_message(_('Invalid Token'),
_('Seems token you are using is invalid!'),
http_status_code=400, indicator_color='red')

frappe.local.flags.redirect_location = frappe.local.response.location
raise frappe.Redirect

Načítá se…
Zrušit
Uložit