Hi,
I’m trying to prepare a payment gateway. The payment provider also wants product information in the basket. I didn’t find out how to call the product list in the basket. The code I’m working on is as follows.
def log(*args, **kwargs):
print("\n".join(args))
class IyzicoSettings(Document):
service_name = "Iyzico"
supported_currencies = ["TRY", "USD", "EUR", "GBP"]
is_embedable = True
def validate(self):
create_payment_gateway("Iyzico")
call_hook_method("payment_gateway_enabled", gateway=self.service_name)
if not self.flags.ignore_mandatory:
self.validate_iyzico_credentails()
def on_update(self):
pass
def get_embed_context(self, context):
# list countries for billing address form
context["iyzico_countries"] = frappe.get_list("Country", fields=["country_name", "name"], ignore_permissions=1)
default_country = frappe.get_value("System Settings", "System Settings", "country")
default_country_doc = next((x for x in context["iyzico_countries"] if x.name == default_country), None)
country_idx = context["iyzico_countries"].index(default_country_doc)
context["iyzico_countries"].pop(country_idx)
context["iyzico_countries"] = [default_country_doc] + context["iyzico_countries"]
context["year"] = datetime.today().year
# get the iyzico user record
#iyzico_user = get_iyzico_user()
#if iyzico_user:
# context["stored_payments"] = iyzico_user.get("stored_payments", [])
def get_embed_form(self, context={}):
context.update({
"source": "templates/includes/integrations/iyzico/embed.html"
})
context = _dict(context)
self.get_embed_context(context)
return {
"form": frappe.render_template(context.source, context),
"style_url": "/assets/css/iyzico_embed.css",
"script_url": "/assets/js/iyzico_embed.js"
}
def validate_iyzico_credentails(self):
pass
def validate_transaction_currency(self, currency):
if currency not in self.supported_currencies:
frappe.throw(_("Please select another payment method. {0} does not support transactions in currency \"{1}\"").format(self.service_name, currency))
def build_iyzico_request(self, **kwargs):
"""Creates an iyzico Request record to keep params off the url"""
data = {
"doctype": "Iyzico Request",
"status": "Issued",
}
data.update(kwargs)
del data["reference_docname"] # have to set it after insert
request = frappe.get_doc(data)
request.flags.ignore_permissions = 1
request.insert()
# TODO: Why must we save doctype first before setting docname?
request.reference_docname = kwargs["reference_docname"]
request.save()
frappe.db.commit()
return request
def get_payment_url(self, **kwargs):
request = self.build_iyzico_request(**kwargs)
url = "./integrations/iyzico_checkout/{0}"
result = get_url(url.format(request.get("name" )))
return result
def get_settings(self):
settings = frappe._dict({
"api_key": self.api_key,
"secret_key": self.get_password(fieldname="secret_key", raise_exception=False)
})
return settings
def process_payment(self):
# used for feedback about which payment was used
iyzico_data = {}
# the current logged in contact
contact = get_contact()
# get iyzico user if available
#iyzico_user = get_iyzico_user()
# the cc data available
data = self.process_data
# get auth keys
settings = self.get_settings()
# fetch redirect info
redirect_to = data.get("notes", {}).get("redirect_to") or None
redirect_message = data.get("notes", {}).get("redirect_message") or None
# uses dummy request doc for unittests as we are only testing processing
if not data.get("unittest"):
if data.get("name"):
request = frappe.get_doc("Iyzico Request", data.get("name"))
else:
# Create request from scratch when embeding form on the fly
#
# This allows payment processing without having to pre-create
# a request first.
#
# This path expects all the payment request information to be
# available!!
#
# keys expected: ('amount', 'currency', 'order_id', 'title', \
# 'description', 'payer_email', 'payer_name', \
# 'reference_docname', 'reference_doctype')
request = self.build_iyzico_request(**{ \
key: data[key] for key in \
('amount', 'currency', 'order_id', 'title', \
'description', 'payer_email', 'payer_name', \
'reference_docname', 'reference_doctype') })
data["name"] = request.get("name")
else:
request = frappe.get_doc({"doctype": "Iyzico Request"})
request.flags.ignore_permissions = 1
# set the max log level as per settings
request.max_log_level(self.log_level)
try:
if self.card_info:
# ensure card fields exist
required_card_fields = ['cardHolderName', 'cardNumber', 'expireMonth', 'expireYear', 'cvc']
for f in required_card_fields:
if not self.card_info.get(f):
request.status = "Error"
return request, None, "Missing field: %s" % f, {}
# prepare authorize api
#authorize.Configuration.configure(
# authorize.Environment.TEST if self.use_sandbox else authorize.Environment.PRODUCTION,
# settings.api_login_id,
# settings.api_transaction_key
#)
ayar = {
'api_key': settings.api_key,
'secret_key': settings.secret_key,
'base_url': iyzipay.base_url
}
# cache billing fields as per authorize api requirements
buyer = iyzico_buyer_address(self.billing_info)
billingAddress = iyzico_address(self.billing_info)
if self.shipping_info:
shippingAddress = iyzico_address(self.billing_info)
else:
shippingAddress = None
# attempt to find valid email address
email = self.process_data.get("payer_email")
if email:
email = email.split(',')[0]
if "@" not in email and contact:
email = contact.get("email_id")
if "@" not in email:
if contact and contact.user:
email = frappe.get_value("User", contact.user, "email_id")
if "@" not in email:
log("Iyzico FAILURE! Bad email: {0}".format(email))
raise ValueError("There are no valid emails associated with this customer")
address = {
'contactName': 'Jane Doe',
'city': 'Istanbul',
'country': 'Turkey',
'address': 'Nidakule Göztepe, Merdivenköy Mah. Bora Sok. No:1',
'zipCode': '34732'
}
buyer = {
'id': 'BY789',
'name': 'John',
'surname': 'Doe',
'gsmNumber': '+905350000000',
'email': 'email@email.com',
'identityNumber': '74300864791',
'lastLoginDate': '2015-10-05 12:43:35',
'registrationDate': '2013-04-21 15:12:09',
'registrationAddress': 'Nidakule Göztepe, Merdivenköy Mah. Bora Sok. No:1',
'ip': '85.34.78.112',
'city': 'Istanbul',
'country': 'Turkey',
}
# build transaction data
transaction_data = {
"locale": "TR",
"conversationId": "123456789",
"price": flt(self.process_data.get("amount")),
"paidPrice": flt(self.process_data.get("amount")),
"currency": "TRY",
"installment": 1,
"paymentGroup": "OTHER",
'buyer': buyer,
'shippingAddress': address,
'billingAddress': address
}
# track ip for tranasction records
if frappe.local.request_ip:
transaction_data.update({
"buyer": {
"ip": frappe.local.request_ip
}
})
# get iyzico profile informatio for stored payments
iyzico_profile = self.process_data.get("iyzico_profile");
# use card
# see: https://vcatalano.github.io/py-authorize/transaction.html
if self.card_info != None:
# exp formating for sale/auth api
transaction_data.update({
"paymentCard": {
"cardHolderName": self.card_info.get("cardHolderName"),
"cardNumber": self.card_info.get("cardNumber"),
"expireMonth": self.card_info.get("expireMonth"),
"expireYear": self.card_info.get("expireYear"),
"cvc": self.card_info.get("cvc")
}
})
elif iyzico_profile:
# if the customer_id isn't provided, then fetch from iyzicouser
if not iyzico_profile.get("customer_id"):
iyzico_profile["customer_id"] = iyzico_user.get("iyzico_id")
# or stored payment
transaction_data.update({
"customer_id": iyzico_profile.get("customer_id"),
"payment_id": iyzico_profile.get("payment_id")
})
# track transaction payment profile ids to return later
iyzico_data.update({
"customer_id": iyzico_profile.get("customer_id"),
"payment_id": iyzico_profile.get("payment_id")
})
else:
raise "Missing Credit Card Information"
# add billing information if available
contactName = self.card_info["cardHolderName"]
if len(billingAddress.keys()):
transaction_data["billingAddress"] = billingAddress
transaction_data["billingAddress"]["contactName"] = name
if shippingAddress and len(shippingAddress.keys()):
transaction_data["shippingAddress"] = billingAddress
transaction_data["shippingAddress"]["contactName"] = name
if buyer and len(buyer.keys()):
transaction_data["buyer"] = billingAddress
transaction_data["buyer"]["email"] = email
transaction_data["identityNumber"] = "74300864791"
# include line items if available
> if self.process_data.get("items"):
transaction_data["basketItems"] = self.process_data.get("items")
request.log_action("Requesting Transaction: %s" % \
json.dumps(transaction_data), "Debug")
# performt transaction finally
result = iyzipay.Payment().create(transaction_data, ayar)
print(result.read())
request.log_action(result, "Debug")
# if all went well, record transaction id
request.status = "Authorized"
request.flags.ignore_permissions = 1
I need to add the product information in the basket to basketItems.
For example:
basket_items = [
{
'id': 'BI101',
'name': 'Binocular',
'category1': 'Collectibles',
'category2': 'Accessories',
'itemType': 'PHYSICAL',
'price': '0.3'
},
{
'id': 'BI102',
'name': 'Game code',
'category1': 'Game',
'category2': 'Online Game Items',
'itemType': 'VIRTUAL',
'price': '0.5'
},
{
'id': 'BI103',
'name': 'Usb',
'category1': 'Electronics',
'category2': 'Usb / Cable',
'itemType': 'PHYSICAL',
'price': '0.2'
}
]