How can I integrate SSLCommerze to my django app? - django

I have created a ecommerce site. Now i want to integrate payment method. By adding SSLCommerce to my site, all payment method will be taken care of in Bangladesh. But I don't know how can I add it to my Django app. Please help!
They said something session. But I did not get it. Here is thier github repo https://github.com/sslcommerz/SSLCommerz-Python?fbclid=IwAR0KkEH3H-AOwaWneQy0POGkTw6O3vvL9NiRM4amflyQEt54_W1g1rgYB48

There is a wrapper library called "sslcommerz-lib". To use it, you'll first need an account on their sandbox environment. After completing the registration, collect your user credentials from email.
First install the package with pip install sslcommerz-lib
Import the library on your module from sslcommerz_lib import SSLCOMMERZ
Instantiate an object of the SSLCOMMERZ class with sandbox user credentials
sslcz = SSLCOMMERZ({ 'store_id': <your_store_id>, 'store_pass': <your_password>, 'issandbox': True })
Build a dictionary with some info about the transaction and customer. In a real application, most of these data will be collected from user input.
data = {
'total_amount': "100.26",
'currency': "BDT",
'tran_id': "tran_12345",
'success_url': "http://127.0.0.1:8000/payment-successful", # if transaction is succesful, user will be redirected here
'fail_url': "http://127.0.0.1:8000/payment-failed", # if transaction is failed, user will be redirected here
'cancel_url': "http://127.0.0.1:8000/payment-cancelled", # after user cancels the transaction, will be redirected here
'emi_option': "0",
'cus_name': "test",
'cus_email': "test#test.com",
'cus_phone': "01700000000",
'cus_add1': "customer address",
'cus_city': "Dhaka",
'cus_country': "Bangladesh",
'shipping_method': "NO",
'multi_card_name': "",
'num_of_item': 1,
'product_name': "Test",
'product_category': "Test Category",
'product_profile': "general",
}
Get the api reponse
response = sslcz.createSession(data)
After doing chores like updating db etc, redirect the user to 'GatewayPageURL' from the response we got earlier -
from django.shortcuts import redirect
return redirect(response['GatewayPageURL'])

SSLCOMMERZ - Python (sslcommerz-lib)
Note: If you're using this wrapper with our sandbox environment issandbox is true and live issandbox is false. (Details: Test Or Sandbox Account).
settings = { 'store_id': 'testbox', 'store_pass': 'qwerty', 'issandbox': True }
sslcommerz = SSLCOMMERZ(settings)
Installation
pip install sslcommerz-lib
Authentication Keys
You can find your store_id and store_pass at the API Documentation Page. Create an account on SSLCOMMERZ, log in and visit this link: https://developer.sslcommerz.com/registration/
Usage
Create a Initial Payment Request Session
from sslcommerz_lib import SSLCOMMERZ
settings = { 'store_id': 'testbox', 'store_pass': 'qwerty', 'issandbox': True }
sslcz = SSLCOMMERZ(settings)
post_body = {}
post_body['total_amount'] = 100.26
post_body['currency'] = "BDT"
post_body['tran_id'] = "12345"
post_body['success_url'] = "your success url"
post_body['fail_url'] = "your fail url"
post_body['cancel_url'] = "your cancel url"
post_body['emi_option'] = 0
post_body['cus_name'] = "test"
post_body['cus_email'] = "test#test.com"
post_body['cus_phone'] = "01700000000"
post_body['cus_add1'] = "customer address"
post_body['cus_city'] = "Dhaka"
post_body['cus_country'] = "Bangladesh"
post_body['shipping_method'] = "NO"
post_body['multi_card_name'] = ""
post_body['num_of_item'] = 1
post_body['product_name'] = "Test"
post_body['product_category'] = "Test Category"
post_body['product_profile'] = "general"
response = sslcz.createSession(post_body) # API response
print(response)
# Need to redirect user to response['GatewayPageURL']
Vaidate payment with IPN
from sslcommerz_lib import SSLCOMMERZ
settings = { 'store_id': 'test_testemi', 'store_pass': 'test_testemi#ssl', 'issandbox': True }
sslcz = SSLCOMMERZ(settings)
post_body = {}
post_body['tran_id'] = '5E121A0D01F92'
post_body['val_id'] = '200105225826116qFnATY9sHIwo'
post_body['amount'] = "10.00"
post_body['card_type'] = "VISA-Dutch Bangla"
post_body['store_amount'] = "9.75"
post_body['card_no'] = "418117XXXXXX6675"
post_body['bank_tran_id'] = "200105225825DBgSoRGLvczhFjj"
post_body['status'] = "VALID"
post_body['tran_date'] = "2020-01-05 22:58:21"
post_body['currency'] = "BDT"
post_body['card_issuer'] = "TRUST BANK, LTD."
post_body['card_brand'] = "VISA"
post_body['card_issuer_country'] = "Bangladesh"
post_body['card_issuer_country_code'] = "BD"
post_body['store_id'] = "test_testemi"
post_body['verify_sign'] = "d42fab70ae0bcbda5280e7baffef60b0"
post_body['verify_key'] = "amount,bank_tran_id,base_fair,card_brand,card_issuer,card_issuer_country,card_issuer_country_code,card_no,card_type,currency,currency_amount,currency_rate,currency_type,risk_level,risk_title,status,store_amount,store_id,tran_date,tran_id,val_id,value_a,value_b,value_c,value_d"
post_body['verify_sign_sha2'] = "02c0417ff467c109006382d56eedccecd68382e47245266e7b47abbb3d43976e"
post_body['currency_type'] = "BDT"
post_body['currency_amount'] = "10.00"
post_body['currency_rate'] = "1.0000"
post_body['base_fair'] = "0.00"
post_body['value_a'] = ""
post_body['value_b'] = ""
post_body['value_c'] = ""
post_body['value_d'] = ""
post_body['risk_level'] = "0"
post_body['risk_title'] = "Safe"
if sslcz.hash_validate_ipn(post_body):
response = sslcz.validationTransactionOrder(post_body['val_id'])
print(response)
else:
print("Hash validation failed")
Get the status or details of a Payment Request by sessionkey
from sslcommerz_lib import SSLCOMMERZ
settings = { 'store_id': 'testbox', 'store_pass': 'qwerty', 'issandbox': True }
sslcz = SSLCOMMERZ(settings)
sessionkey = 'A8EF93B75B8107E4F36049E80B4F9149'
response = sslcz.transaction_query_session(sessionkey)
print(response)
Get the status or details of a Payment Request by tranid
from sslcommerz_lib import SSLCOMMERZ
settings = { 'store_id': 'testbox', 'store_pass': 'qwerty', 'issandbox': True }
sslcz = SSLCOMMERZ(settings)
tranid = '59C2A4F6432F8'
response = sslcz.transaction_query_tranid(tranid)
print(response)

Related

boto3 EC2 script email: One email for all status checks

I am getting one email per instance that fails status checks. I want to get one email for all status checks.
Here is my code:
import boto3
import smtplib
client = boto3.client("ec2")
clientsns = boto3.client("sns")
status = client.describe_instance_status(IncludeAllInstances = True)
#failed_instances = []
for i in status["InstanceStatuses"]:
# failed_instances.append(i[{'Instance'})]
in_status = i['InstanceStatus']['Details'][0]['Status']
sys_status = i['SystemStatus']['Details'][0]['Status']
# check statuses failed instances
if ((in_status != 'passed') or (sys_status != 'passed')):
msg = f'The following instances failed status checks, {i["InstanceId"]}'
clientsns.publish(TopicArn='arn:aws:sns:us-west-1:462518063038:test',Message=msg)
Try something like this:
import boto3
import botocore
from boto3 import Session
boto3.setup_default_session(profile_name='account2')
def get_tag(tags, key='Name'):
if not tags: return ''
for tag in tags:
if tag['Key'] == key:
return tag['Value']
return ''
client = boto3.client("ec2")
conn = boto3.resource('ec2')
#instances = conn.instances.filter()
instances = conn.instances.filter(
Filters=[{'Name': 'instance-state-name', 'Values': ['running']}])
filter_for = {
"running": [{"Name": "instance-state-name", "Values": ["running"]}],
}
ec2instance = client.describe_instance_status(IncludeAllInstances = True, Filters=filter_for["running"])
failed_instances = []
for i in ec2instance["InstanceStatuses"]:
in_status = i['InstanceStatus']['Details'][0]['Status']
sys_status = i['SystemStatus']['Details'][0]['Status']
# check statuses failed instances
if ((in_status != 'passed') or (sys_status != 'passed')):
failed_instances.append(i["InstanceId"])
if len(failed_instances)>0:
# new_line = '\n'
# msg = f'The following instances failed status checks:{new_line} {new_line.join(failed_instances)}'
# #msg = f'The following instances failed status checks, {failed_instances}'
# clientsns.publish(TopicArn='arn:aws:sns:us-west-1:462518063038:test',Message=msg)
for j in failed_instances:
instance = [x for x in list(instances) if x.id == j][0]
instance_name = get_tag(instance.tags)
print (instance_name, instance.id, instance.instance_type)

cannot post a new DB to apache-superset, 400 Error with CSRF

I am unsure how I can set the CSRF token so apache superset is happy.. here is my code
Create a DB Connection for Apache Superset
import requests
import json
base_url = "http://SOMEIP:8088/"
login_url = base_url + "api/v1/security/login"
csrf_url = base_url + "api/v1/security/csrf_token"
def create_db_connection(session, db_ip, db_port, db_user, db_pass, db_name):
url = base_url + "api/v1/database/"
sqlalchemy_url = "postgresql://" + db_user + ":" + db_pass + "#" + db_ip + ":" + str(db_port)+"/" + db_name
data_out = {
"allow_csv_upload": True,
"allow_ctas": True,
"allow_cvas": True,
"allow_dml": True,
"allow_multi_schema_metadata_fetch": True,
"allow_run_async": True,
"cache_timeout": 0,
"database_name": db_name,
"expose_in_sqllab": True,
"impersonate_user": True,
"sqlalchemy_uri": sqlalchemy_url
}
response = session.post(url=url, headers=dict(Referrer=login_url), json=data_out)
response.raise_for_status()
return response
if __name__ == "__main__":
username = "mysupersetuser"
password = "mysupersetpass"
db_user = "MYUSER"
db_password = "MYDBPASS"
db_host = "MYPOSTGRESIP"
db_port = 5432
db_name = "MYDBNAME"
session = requests.session()
login_url = base_url + "api/v1/security/login"
login_data = {
"password": password,
"provider": "db",
"refresh": False,
"username": username
}
response = session.post(url=login_url, json=login_data)
response.raise_for_status()
head = {
"Authorization": "Bearer " + json.loads(response.text)['access_token']
}
response = session.get(csrf_url, headers=head)
response.raise_for_status()
response = create_db_connection(session, db_ip=db_host, db_port=db_port, db_user=db_user, db_pass=db_password, db_name=db_name)
print(str(response.text))
I see multiple ways people are stating to set the CSRF token.. but none have worked so far.
Always it's the same response 400
'{"errors": [{"message": "400 Bad Request: The CSRF token is missing.", "error_type": "GENERIC_BACKEND_ERROR", "level": "error", "extra": {"issue_codes": [{"code": 1011, "message": "Issue 1011 - Superset encountered an unexpected error."}]}}]}'
It looks like Apache-Superset uses Flask-AppBuilder which uses Flask_WTF. You should be able to set it in the request headers.
def create_db_connection(session, db_ip, db_port, db_user, db_pass, db_name, token_from_your_crsf_url):
headers = {
'Referrer': login_url,
'X-CSRFToken': token_from_your_crsf_url
}
...
response = session.post(url=url, headers=headers, json=data_out)
...

Calling Web Service method throwing Remote Disconnected error in Zeep

I am using the Python Zeep library to call Maximo web services and able to fetch the WSDL without any issues. When I am trying to query using one of the method in Web service, it is throwing error
requests.exceptions.ConnectionError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response',))
multiasset_wsdl = "http://maximoqa.xyz.com:9080/meaweb/services/MULTIASSET?wsdl"
work_order = 'NA0000211'
# set the session
session = Session()
session.auth = HTTPBasicAuth(Username, Password)
session.verify = False
transport = Transport(session=session)
settings = Settings(strict=False ,force_https = False)
maximo_multiasset_client = Client(multiasset_wsdl, transport=transport, settings=settings
multiasset_type_factory = maximo_multiasset_client.type_factory('ns0')
mult_asset_query = multiasset_type_factory.QueryMULTIASSETType(
baseLanguage = "?",
creationDateTime = tt.get_now(),
maximoVersion = "?",
maxItems = "1",
messageID = "?",
rsStart = "0",
transLanguage = "EN",
uniqueResult = False,
MULTIASSETQuery = multiasset_type_factory.MULTIASSETQueryType
(
operandMode = multiasset_type_factory.OperandModeType('AND'),
orderby = "?",
WHERE = f"WONUM='{work_order}'",
WORKORDER = None
)
)
print('Calling Query MultiAsset')
query_response = maximo_multiasset_client.service.QueryMULTIASSET(mult_asset_query)
Appreciate any help on this issue.

Bittrex REST API for Python, I want to create an order using API v3 https://api.bittrex.com/v3/orders

I need help to create orders using the bittrex version 3 REST API. I have the code below and I can't understand what is missing to work.
I can make other GET calls, but I cannot make this POST request.
I don't know how to deal with the passing of parameters.
Official documentation at https://bittrex.github.io/api/v3#tag-Orders.
def NewOrder(market, amount, price):
#print 'open sell v3', market
market = 'HEDG-BTC'#'BTC-'+market
uri = 'https://api.bittrex.com/v3/orders?'
params = {
'marketSymbol': 'BTC-HEDG',#'HEDG-BTC', #market
'direction': 'BUY',
'type': 'LIMIT',
'quantity': amount,
'limit': price,
'timeInForce': 'POST_ONLY_GOOD_TIL_CANCELLED',
'useAwards': True
}
timestamp = str(int(time.time()*1000))
Content = ""
contentHash = hashlib.sha512(Content.encode()).hexdigest()
Method = 'POST'
uri2 = buildURI(uri, params)
#uri2 = 'https://api.bittrex.com/v3/orders?direction=BUY&limit=0.00021&marketSymbol=HEDG-BTC&quantity=1.1&timeInForce=POST_ONLY_GOOD_TIL_CANCELLED&type=LIMIT&useAwards=True'
#print uri2
PreSign = timestamp + uri2 + Method + contentHash# + subaccountId
#print PreSign
Signature = hmac.new(apisecret, PreSign.encode(), hashlib.sha512).hexdigest()
headers = {
'Api-Key' : apikey,
'Api-Timestamp' : timestamp,
'Api-Content-Hash': contentHash,
'Api-Signature' : Signature
}
r = requests.post(uri2, data={}, headers=headers, timeout=11)
return json.loads(r.content)
NewOrder('HEDG', 1.1, 0.00021)
And my error message:
{u'code': u'BAD_REQUEST', u'data': {u'invalidRequestParameter': u'direction'}, u'detail': u'Refer to the data field for specific field validation failures.'}
It seems from the documentation that this body is expected by the api as json data:
{
"marketSymbol": "string",
"direction": "string",
"type": "string",
"quantity": "number (double)",
"ceiling": "number (double)",
"limit": "number (double)",
"timeInForce": "string",
"clientOrderId": "string (uuid)",
"useAwards": "boolean"
}
and you are setting these values as url params that's the issue.
you need to do this:
uri = 'https://api.bittrex.com/v3/orders'
# NOTE >>>> please check that you provide all the required fields.
payload = {
'marketSymbol': 'BTC-HEDG',#'HEDG-BTC', #market
'direction': 'BUY',
'type': 'LIMIT',
'quantity': amount,
'limit': price,
'timeInForce': 'POST_ONLY_GOOD_TIL_CANCELLED',
'useAwards': True
}
# do rest of the stuffs as you are doing
# post payload as json data with the url given in doc
r = requests.post(uri, json=payload, headers=headers, timeout=11)
print(r.json())
If you still have issues let us know. If it works then please mark answer as accepted.
Hope this helps.
I made the following modifications to the code but started to give error in 'Content-Hash'
I'm assuming that some parameters are optional so they are commented.
def NewOrder(market, amount, price):
market = 'BTC-'+market
uri = 'https://api.bittrex.com/v3/orders'
payload = {
'marketSymbol': market,
'direction': 'BUY',
'type': 'LIMIT',
'quantity': amount,
#"ceiling": "number (double)",
'limit': price,
'timeInForce': 'POST_ONLY_GOOD_TIL_CANCELLED',
#"clientOrderId": "string (uuid)",
'useAwards': True
}
#ceiling (optional, must be included for ceiling orders and excluded for non-ceiling orders)
#clientOrderId (optional) client-provided identifier for advanced order tracking
timestamp = str(int(time.time()*1000))
Content = ''+json.dumps(payload, separators=(',',':'))
print Content
contentHash = hashlib.sha512(Content.encode()).hexdigest()
Method = 'POST'
#uri2 = buildURI(uri, payload)#line not used
print uri
#PreSign = timestamp + uri2 + Method + contentHash# + subaccountId
PreSign = timestamp + uri + Method + contentHash# + subaccountId
print PreSign
Signature = hmac.new(apisecret, PreSign.encode(), hashlib.sha512).hexdigest()
headers = {
'Api-Key' : apikey,
'Api-Timestamp' : timestamp,
'Api-Content-Hash': contentHash,
'Api-Signature' : Signature
}
r = requests.post(uri, json=payload, headers=headers, timeout=11)
print(r.json())
return json.loads(r.content)
NewOrder('HEDG', 1.5, 0.00021)
{u'code': u'INVALID_CONTENT_HASH'}
Bittrex API via requests package PYTHON
import hmac
import hashlib
import time, requests
nonce = str(int(time.time() * 1000))
content_hash = hashlib.sha512(''.encode()).hexdigest()
signature = hmac.new(
'<SECRET_KEY>'.encode(),
''.join([nonce, url, 'GET', content_hash]).encode(),
hashlib.sha512
).hexdigest()
headers = {
'Api-Timestamp': nonce,
'Api-Key': '<API_KEY>',
'Content-Type': 'application/json',
'Api-Content-Hash': content_hash,
'Api-Signature': signature
}
result = requests.get(url=url, headers=headers)

Mock Stripe Methods in Python for testing

So I am trying to mock all the stripe web hooks in the method so that I can write the Unit test for it. I am using the mock library for mocking the stripe methods. Here is the method I am trying to mock:
class AddCardView(APIView):
"""
* Add card for the customer
"""
permission_classes = (
CustomerPermission,
)
def post(self, request, format=None):
name = request.DATA.get('name', None)
cvc = request.DATA.get('cvc', None)
number = request.DATA.get('number', None)
expiry = request.DATA.get('expiry', None)
expiry_month, expiry_year = expiry.split("/")
customer_obj = request.user.contact.business.customer
customer = stripe.Customer.retrieve(customer_obj.stripe_id)
try:
card = customer.sources.create(
source={
"object": "card",
"number": number,
"exp_month": expiry_month,
"exp_year": expiry_year,
"cvc": cvc,
"name": name
}
)
# making it the default card
customer.default_source = card.id
customer.save()
except CardError as ce:
logger.error("Got CardError for customer_id={0}, CardError={1}".format(customer_obj.pk, ce.json_body))
return Response({"success": False, "error": "Failed to add card"})
else:
customer_obj.card_last_4 = card.get('last4')
customer_obj.card_kind = card.get('type', '')
customer_obj.card_fingerprint = card.get('fingerprint')
customer_obj.save()
return Response({"success": True})
This is the method for unit testing:
#mock.patch('stripe.Customer.retrieve')
#mock.patch('stripe.Customer.create')
def test_add_card(self,create_mock,retrieve_mock):
response = {
'default_card': None,
'cards': {
"count": 0,
"data": []
}
}
# save_mock.return_value = response
create_mock.return_value = response
retrieve_mock.return_value = response
self.api_client.client.login(username = self.username, password = self.password)
res = self.api_client.post('/biz/api/auth/card/add')
print res
Now stripe.Customer.retrieve is being mocked properly. But I am not able to mock customer.sources.create. I am really stuck on this.
This is the right way of doing it:
#mock.patch('stripe.Customer.retrieve')
def test_add_card_failure(self, retrieve_mock):
data = {
'name': "shubham",
'cvc': 123,
'number': "4242424242424242",
'expiry': "12/23",
}
e = CardError("Card Error", "", "")
retrieve_mock.return_value.sources.create.return_value = e
self.api_client.client.login(username=self.username, password=self.password)
res = self.api_client.post('/biz/api/auth/card/add', data=data)
self.assertEqual(self.deserialize(res)['success'], False)
Even though the given answer is correct, there is a way more comfortable solution using vcrpy. That is creating a cassette (record) once a given record does not exist yet. When it does, the mocking is done transparently and the record will be replayed. Beautiful.
Having a vanilla pyramid application, using py.test, my test now looks like this:
import vcr
# here we have some FactoryBoy fixtures
from tests.fixtures import PaymentServiceProviderFactory, SSOUserFactory
def test_post_transaction(sqla_session, test_app):
# first we need a PSP and a User existent in the DB
psp = PaymentServiceProviderFactory() # type: PaymentServiceProvider
user = SSOUserFactory()
sqla_session.add(psp, user)
sqla_session.flush()
with vcr.use_cassette('tests/casettes/tests.checkout.services.transaction_test.test_post_transaction.yaml'):
# with that PSP we create a new PSPTransaction ...
res = test_app.post(url='/psps/%s/transaction' % psp.id,
params={
'token': '4711',
'amount': '12.44',
'currency': 'EUR',
})
assert 201 == res.status_code
assert 'id' in res.json_body
IMO, the following method is better than the rest of the answers
import unittest
import stripe
import json
from unittest.mock import patch
from stripe.http_client import RequestsClient # to mock the request session
stripe.api_key = "foo"
stripe.default_http_client = RequestsClient() # assigning the default HTTP client
null = None
false = False
true = True
charge_resp = {
"id": "ch_1FgmT3DotIke6IEFVkwh2N6Y",
"object": "charge",
"amount": 1000,
"amount_captured": 1000,
"amount_refunded": 0,
"billing_details": {
"address": {
"city": "Los Angeles",
"country": "USA",
},
"email": null,
"name": "Jerin",
"phone": null
},
"captured": true,
}
def get_customer_city_from_charge(stripe_charge_id):
# this is our function and we are writing unit-test for this function
charge_response = stripe.Charge.retrieve("foo-bar")
return charge_response.billing_details.address.city
class TestStringMethods(unittest.TestCase):
#patch("stripe.default_http_client._session")
def test_get_customer_city_from_charge(self, mock_session):
mock_response = mock_session.request.return_value
mock_response.content.decode.return_value = json.dumps(charge_resp)
mock_response.status_code = 200
city_name = get_customer_city_from_charge("some_id")
self.assertEqual(city_name, "Los Angeles")
if __name__ == '__main__':
unittest.main()
Advantages of this method
You can generate the corresponding class objects (here, the charge_response variable is a type of Charge--(source code))
You can use the dot (.) operator over the response (as we can do with real stripe SDK)
dot operator support for deep attributes