# Resulting notification string (in format application/json)
request_body_json = """
{
"shop_id": 1,
"shop_order_id": "The store's order ID",
"description": "Your payment description",
"shop_amount": 100.0,
"shop_refund": 19.0,
"shop_currency": 840,
"payment_id": 1234,
"client_price": 100.0,
"ps_currency": "840",
"payway": "some_payway_name",
"ps_data": "{\\"amount\\": \\"20.00\\", \\"bill_id\\": \\"i_100\\", \\"ccy\\": \\"USD\\", \\"command\\": \\"bill\\", \\"comment\\": \\"[i_100] Payment\\", \\"error\\": 0, \\"prv_name\\": \\"PaymentSystem\\", \\"ps_payer_account\\": \\"971510000000\\", \\"status\\": \\"paid\\", \\"user\\": \\"tel:+971510000000\\"}",
"created": "2020-08-21T15:38:07",
"updated": "2020-08-21T15:38:07",
"status": "success",
"addons": "{\\"callback_rejected_url\\": \\"https://some-shop.com/callback-rejected-url\\", \\"callback_url\\": \\"https://some-shop.com/callback-url\\", \\"description\\": \\"Some payment\\", \\"failed_url\\": \\"https://some-shop.com/fail\\", \\"phone\\": \\"971510000000\\", \\"success_url\\": \\"https://some-shop.com/success\\"}",
"sign": "1d51960a52a6c7e8cf957d1a22ad2b3263603bace013facc335dd1429ecb4e97"
}"""
import json
parsed_request = json.loads(request_body_json)
# Resulting notification string (in format application/x-www-form-urlencoded)
if content_type == 'application/x-www-form-urlencoded':
request_body_form_urlencoded = (
'shop_id=1&shop_order_id=The+store's+order+ID&description=Your+payment+description&s'
'hop_amount=20.0&shop_refund=19.0&shop_currency=840&payment_id=100&'
'client_price=20.0&ps_currency=840&payway=some_payway_name&ps_data='
'%7B%22amount%22%3A+%2220.00%22%2C+%22bill_id%22%3A+%22i_100%22%2C+'
'%22ccy%22%3A+%22USD%22%2C+%22command%22%3A+%22bill%22%2C+%22commen'
't%22%3A+%22%5Bi_100%5D+Payment%22%2C+%22error%22%3A+0%2C+%22prv_na'
'me%22%3A+%22PaymentSystem%22%2C+%22ps_payer_account%22%3A+%2297151'
'0000000%22%2C+%22status%22%3A+%22paid%22%2C+%22user%22%3A+%22tel%3'
'A%2B971510000000%22%7D&created=2020-08-21T15%3A38%3A07&updated=202'
'0-08-21T15%3A38%3A07&status=success&addons=%7B%22callback_rejected'
'_url%22%3A+%22https%3A%2F%2Fsome-shop.com%2Fcallback-rejected-url%'
'22%2C+%22callback_url%22%3A+%22https%3A%2F%2Fsome-shop.com%2Fcallb'
'ack-url%22%2C+%22description%22%3A+%22Some+payment%22%2C+%22failed'
'_url%22%3A+%22https%3A%2F%2Fsome-shop.com%2Ffail%22%2C+%22phone%22'
'%3A+%22971510000000%22%2C+%22success_url%22%3A+%22https%3A%2F%2Fso'
'me-shop.com%2Fsuccess%22%7D&sign=1d51960a52a6c7e8cf957d1a22ad2b326'
'3603bace013facc335dd1429ecb4e97'
)
from urllib.parse import parse_qsl
parsed_request = dict(parse_qsl(request_body_form_urlencoded))
print(parsed_request)
# {
# 'shop_id': 100,
# 'shop_order_id': 'The store's order ID',
# 'description': 'Some payment',
# 'shop_amount': 20.0,
# 'shop_refund': 19.0,
# 'shop_currency': 840,
# 'payment_id': '100',
# 'client_price': 20.0,
# 'ps_currency': 840,
# 'payway': 'some_payway_name',
# 'ps_data': '{"amount": "20.00", "bill_id": "i_100", "ccy": "USD", "command": "bill", "comment": "[i_100] Payment", "error": 0, "prv_name": "PaymentSystem", "ps_payer_account": "971510000000", "status": "paid", "user": "tel:+971510000000"}',
# 'created': '2020-08-21T15:38:07',
# 'updated': '2020-08-21T15:38:07',
# 'status': 'success',
# 'addons': '{"callback_rejected_url": "https://example.com/callback-rejected-url", "callback_url": "https://example.com/callback-url", "description": "Your payment description", "failed_url": "https://example.com/fail", "phone": "971510000000", "success_url": "https://example.com/success"}',
# 'sign': '1d51960a52a6c7e8cf957d1a22ad2b3263603bace013facc335dd1429ecb4e97',
# }
# Let's get a list of sorted keys for signature generation
keys = sorted(parsed_request)
# Let's remove the signed key from them.
keys.remove('sign')
print(keys)
# This is how the resulting list will look like
# ['addons',
# 'client_price',
# 'created',
# 'description',
# 'payment_id',
# 'payway',
# 'ps_currency',
# 'ps_data',
# 'shop_amount',
# 'shop_currency',
# 'shop_id',
# 'shop_order_id',
# 'shop_refund',
# 'status',
# 'updated']
# Let's compose a line using the sorted key values obtained in the previous step
values_to_sign = []
for k in keys:
if parsed_request[k] != '' and parsed_request[k] is not None:
values_to_sign.append(str(parsed_request[k]))
# Let's form the final signature and check its value with the value received in the response
string_to_sign = ':'.join(values_to_sign) + '<secret_key_here>'
import hashlib
sign = hashlib.sha256(string_to_sign.encode()).hexdigest()
assert sign == parsed_request['sign']