I am getting this error. ImportError: cannot import name 'Paynow'
. I installed paynow==1.0.4 and i am getting this error when i try importing it. Like:
from paynow import Paynow
Can anyone help?
I am getting this error. ImportError: cannot import name 'Paynow'
. I installed paynow==1.0.4 and i am getting this error when i try importing it. Like:
from paynow import Paynow
Can anyone help?
Activate your enviroment and Try running
pip freeze
, if on linux use
pip freeze | grep paynow
If you don’t notice paynow in the output it means paynow
is not installed, if in case it is run the following command
pip install paynow --upgrade
else run
pip install paynow
or install directly from git repositories
pip install git+git://github.com/paynow/Paynow-Python-SDK
>>> from paynow import Paynow
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/myname/Documents/myprojectfolder/myproject/paynow.py", line 9, in <module>
from paynow import Paynow
ImportError: cannot import name 'Paynow'
this is the error that i’m getting after following the instructions that you gave me. I am using Ubuntu 18.04
Okay i have discovered where i went wrong… I had created a file named paynow.py so python was trying to import Paynow from that file instead of site packages. I renamed that file and all is working well now Thanks for the help.
from paynow import Paynow
File “/////env//python3.5/site-packages/paynow/init.py”, line 18
paid: bool
^
SyntaxError: invalid syntax
Has anyone faced this error before on ubuntu 16
so when i install using pip install paynow {paynow 1.0.4} i get the error above when i try and run the server. So uninstalled paynow and installed using
pip install git+git://github.com/paynow/Paynow-Python-SDK
this version seems to work well { paynow 1.0.2}
Latest version could be faulty {paynow 1.0.4}
Resolved by Editing the entire init.py file
import requests
import hashlib
from urllib.parse import quote_plus, parse_qs
“”"
Exception thrown when hash from Paynow does not match locally generated hash
“”"
class HashMismatchException(Exception):
def init(self, message):
super(HashMismatchException, self).init(message)
class StatusResponse:
paid=bool
“”"
bool: Boolean value indication whether the transaction was paid or not
“”"
status=str
"""
str: The status of the transaction in Paynow
"""
amount=float
"""
float: The total amount of the transaction
"""
reference=any
"""
any: The unique identifier for the transaction
"""
paynow_reference=any
"""
any: Paynow's unique identifier for the transaction
"""
hash= str
"""
any: Hash of the transaction in paynow
"""
def __status_update(self, data):
"""Parses the incoming status update from Paynow
Args:
data (any): The data from paynow
"""
print('Not implemented')
# TODO: Implement method
def __init__(self, data, update):
if update:
self.__status_update(data)
else:
self.status = data['status'].lower()
self.paid = self.status == 'paid'
if 'amount' in data:
self.amount = float(data['amount'])
if 'reference' in data:
self.reference = data['reference']
if 'paynowreference' in data:
self.paynow_reference = data['paynowreference']
if 'hash' in data:
self.hash = data['hash']
class InitResponse:
“”"Wrapper class for response from Paynow during transaction initiation
"""
success=bool
"""
bool: Boolean indicating whether initiate request was successful or not
"""
instructions=str
"""
bool: Boolean indicating whether the response contains a url to redirect to
"""
has_redirect=bool
"""
bool: Boolean indicating whether the response contains a url to redirect to
"""
hash=str
"""
str: Hashed transaction returned from Paynow
"""
redirect_url=str
"""
str: The url the user should be taken to so they can make a payment
"""
error=str
"""
str: he error message from Paynow, if any
"""
poll_url=str
"""
str: The poll URL sent from Paynow
"""
def __init__(self, data):
self.status = data['status']
self.success = data['status'].lower() != 'error'
self.has_redirect = 'browserurl' in data
self.hash = 'hash' in data
if not self.success:
return
self.poll_url = data['pollurl']
if not self.success:
self.error = data['error']
if self.has_redirect:
self.redirect_url = data['browserurl']
if 'instructions' in data:
self.instruction = data['instructions']
class Payment:
“”"Helper class for building up a transaction before sending it off to Paynow
Attributes:
reference (str): Unique identifier for the transaction
items ([]): Array of items in the 'cart'
"""
reference=str = ""
"""
str: Unique identifier for the transaction
"""
items= [] = []
"""
[]: Array of items in the 'cart'
"""
auth_email=str
"""
str: The user's email address.
"""
def __init__(self, reference: str, auth_email: str):
self.reference = reference
self.auth_email = auth_email
def add(self, title: str, amount: float):
""" Add an item to the 'cart'
Args:
title (str): The name of the item
amount (float): The cost of the item
"""
# TODO: Validate
self.items.append([title, amount])
return self
def total(self):
"""Get the total cost of the items in the transaction
Returns:
float: The total
"""
total = 0.0
for item in self.items:
total += float(item[1])
return total
def info(self):
"""Generate text which represents the items in cart
Returns:
str: The text representation of the cart
"""
out = ""
for item in self.items:
out += (item[0] + ", ")
return out
class Paynow:
“”"Contains helper methods to interact with the Paynow API
Attributes:
integration_id (str): Merchant's integration id.
integration_key (str): Merchant's integration key.
return_url (str): Merchant's return url
result_url (str): Merchant's result url
Args:
integration_id (str): Merchant's integration id. (You can generate this in your merchant dashboard)
integration_key (str): Merchant's integration key.
return_url (str): Merchant's return url
result_url (str): Merchant's result url
"""
URL_INITIATE_TRANSACTION = "https://www.paynow.co.zw/interface/initiatetransaction"
"""
str: Transaction initation url (constant)
"""
URL_INITIATE_MOBILE_TRANSACTION = "https://www.paynow.co.zw/interface/remotetransaction"
"""
str: Transaction initation url (constant)
"""
integration_id= str = ""
"""
str: Merchant's integration id
"""
integration_key= str = ""
"""
str: Merchant's integration key
"""
return_url = ""
"""
str: Merchant's return url
"""
result_url = ""
"""
str: Merchant's result url
"""
def __init__(self, integration_id, integration_key, return_url, result_url):
self.integration_id = integration_id
self.integration_key = integration_key
self.return_url = return_url
self.result_url = result_url
def set_result_url(self, url: str):
"""Sets the url where the status of the transaction will be sent when payment status is updated within Paynow
Args:
url (str): The url where the status of the transaction will be sent when
payment status is updated within Paynow
"""
self.result_url = url
def set_return_url(self, url: str):
"""Sets the url where the user will be redirected to after they are done on Paynow
Args:
url (str): The url to redirect user to once they are done on Paynow's side
"""
self.return_url = url
def create_payment(self, reference: str, auth_email: str = ''):
"""Create a new payment
Args:
reference (str): Unique identifier for the transaction.
auth_email (str): The phone number to send to Paynow. This is required for mobile transactions
Note:
Auth email is required for mobile transactions.
Returns:
Payment: An object which provides an easy to use API to add items to Payment
"""
return Payment(reference, auth_email)
def send(self, payment: Payment):
"""Send a transaction to Paynow
Args:
payment (Payment): The payment object with details about transaction
Returns:
StatusResponse: An object with information about the status of the transaction
"""
return self.__init(payment)
def send_mobile(self, payment: Payment, phone: str, method: str):
"""Send a mobile transaction to Paynow
Args:
payment (Payment): The payment object with details about transaction
phone (str): The phone number to send to Paynow
method (str): The mobile money method being employed
Returns:
StatusResponse: An object with information about the status of the transaction
"""
return self.__init_mobile(payment, phone, method)
def process_status_update(self, data: object) -> StatusResponse:
"""This method parses the status update data from Paynow into an easier to use format
Args:
data (dict): A dictionary with the data from Paynow. This is the POST data sent by Paynow
to your result url after the status of a transaction has changed (see Django usage example)
Returns:
StatusResponse: An object with information about the status of the transaction
"""
return StatusResponse(data, True)
def __init(self, payment: Payment):
"""Initiate the given transaction with Paynow
Args:
payment (Payment): The payment object with details about transaction
Returns:
InitResponse: An object with misc information about the initiated transaction i.e
redirect url (if available), status of initiation etc (see `InitResponse` declaration above)
"""
if payment.total() <= 0:
raise ValueError('Transaction total cannot be less than 1')
# Build up the object
data = self.__build(payment)
# Save response from Paynow
response = requests.post(self.URL_INITIATE_TRANSACTION, data=data)
# Reconstruct the response into key-value pairs
response_object = self.__rebuild_response(parse_qs(response.text))
# If an error was encountered return a new InitResponse object without validating hash since hash is not
# generated for error responses
if str(response_object['status']).lower() == 'error':
return InitResponse(response_object)
# Verify the hash from Paynow with the locally generated one
if not self.__verify_hash(response_object, self.integration_key):
raise HashMismatchException("Hashes do not match")
# Create a new InitResponse object object passing in the data from Paynow
return InitResponse(response_object)
def __init_mobile(self, payment: Payment, phone: str, method: str):
"""Initiate a mobile transaction
Args:
payment (Payment): The payment object with details about transaction
phone (str): The phone number to send to Paynow
method (str): The mobile money method being employed
Returns:
InitResponse: An object with misc information about the initiated transaction i.e
redirect url (if available), status of initiation etc (see `InitResponse` declaration above)
"""
if payment.total() <= 0:
raise ValueError('Transaction total cannot be less than 1')
if not payment.auth_email or len(payment.auth_email) <= 0:
raise ValueError('Auth email is required for mobile transactions. You can pass the auth email as the '
'second parameter in the create_payment method call')
# Build up the object
data = self.__build_mobile(payment, phone, method)
# Save response from Paynow
response = requests.post(
self.URL_INITIATE_MOBILE_TRANSACTION, data=data)
# Reconstruct the response into key-value pairs
response_object = self.__rebuild_response(parse_qs(response.text))
# If an error was encountered return a new InitResponse object without validating hash since hash is not
# generated for error responses
if str(response_object['status']).lower() == 'error':
return InitResponse(response_object)
# Verify the hash from Paynow with the locally generated one
if not self.__verify_hash(response_object, self.integration_key):
raise HashMismatchException("Hashes do not match")
# Create a new InitResponse object object passing in the data from Paynow
return InitResponse(response_object)
def check_transaction_status(self, poll_url):
"""Check the status transaction of the transaction with the given poll url
Args:
poll_url (str): Poll url of the transaction
Returns:
StatusResponse: An object with information about the status of the transaction
"""
response = requests.post(poll_url, data={})
response_object = self.__rebuild_response(parse_qs(response.text))
return StatusResponse(
response_object, False)
def __build(self, payment: Payment):
"""Build up a payment into the format required by Paynow
Args:
payment (Payment): The payment object to format
Returns:
dict: A dictionary properly formatted in the format required by Paynow
"""
body = {
"resulturl": self.result_url,
"returnurl": self.return_url,
"reference": payment.reference,
"amount": payment.total(),
"id": self.integration_id,
"additionalinfo": payment.info(),
"authemail": payment.auth_email or "",
"status": "Message"
}
for key, value in body.items():
body[key] = quote_plus(str(value))
body['hash'] = self.__hash(body, self.integration_key)
return body
def __build_mobile(self, payment: Payment, phone: str, method: str):
"""Build up a mobile payment into the format required by Paynow
Args:
payment (Payment): The payment object to format
phone (str): The phone number to send to Paynow
method (str): The mobile money method being employed
Note:
Currently supported methods are `ecocash` and `onemoney`
Returns:
dict: A dictionary properly formatted in the format required by Paynow
"""
body = {
"resulturl": self.result_url,
"returnurl": self.return_url,
"reference": payment.reference,
"amount": payment.total(),
"id": self.integration_id,
"additionalinfo": payment.info(),
"authemail": payment.auth_email,
"phone": phone,
"method": method,
"status": "Message"
}
for key, value in body.items():
if(key == 'authemail'):
continue
body[key] = quote_plus(str(value)) # Url encode the
body['hash'] = self.__hash(body, self.integration_key)
return body
def __hash(self, items: {}, integration_key: str):
"""Generates a SHA512 hash of the transaction
Args:
items (dict): The transaction dictionary to hash
integration_key (str): Merchant integration key to use during hashing
Returns:
str: The hashed transaction
"""
out = ""
for key, value in items.items():
if(str(key).lower() == 'hash'):
continue
out += str(value)
out += integration_key.lower()
return hashlib.sha512(out.encode('utf-8')).hexdigest().upper()
def __verify_hash(self, response: {}, integration_key: str):
"""Verify the hash coming from Paynow
Args:
response (dict): The response from Paynow
integration_key (str): Merchant integration key to use during hashing
"""
if('hash' not in response):
raise ValueError("Response from Paynow does not contain a hash")
old_hash = response['hash']
new_hash = self.__hash(response, integration_key)
return new_hash == new_hash
def __rebuild_response(self, response: {}):
"""
Rebuild a response into key value pairs (as opposed to nested array returned from parse_qs)
Args:
response (dict): The response from Paynow
Returns:
dict: Key value pairs of the data from Paynow
"""
res = {}
for key, value in response.items():
res[key] = str(value[0])
return res