在 Nested Dicts 上实现 PHP 方法 KSORT 和 HTTP_BUILD_QUERY in Python
Implementing the PHP methods KSORT and HTTP_BUILD_QUERY in Python on Nested Dicts
我需要 re-create Python 中的以下代码来验证 API 响应的 header 中包含的签名。
<?php
// Profile Key (ServerKey)
$serverKey = "SRJNLKHG6K-HWMDRGW66J-LRWTGDGRNK"; // Example
// Request body include a signature post Form URL encoded field
// 'signature' (hexadecimal encoding for hmac of sorted post form fields)
$requestSignature = $_POST["signature"];
unset($_POST["signature"]);
$signature_fields = $_POST;
// Ignore empty values fields
$signature_fields = array_filter($signature_fields);
// Sort form fields
ksort($signature_fields);
// Generate URL-encoded query string of Post fields except signature field.
$query = http_build_query($signature_fields);
$signature = hash_hmac('sha256', $query, $serverKey);
if (hash_equals($signature,$requestSignature) === TRUE) {
// VALID Redirect
// Do your logic
}else{
// INVALID Redirect
// Log request
}
?>
我对 PHP 的了解为 0,过去 24 小时我一直在尝试 re-create 但没有成功。
我坚持的部分是 ksort 和 http_build_query 方法。
我想了解的是,对于嵌套数组,这些方法的结果会是什么样子,例如:
{
"tran_ref": "TST2014900000688",
"cart_id": "Sample Payment",
"cart_description": "Sample Payment",
"cart_currency": "AED",
"cart_amount": "1",
"customer_details": {
"name": "John Smith",
"email": "jsmith@gmail.com",
"phone": "9711111111111",
"street1": "404, 11th st, void",
"city": "Dubai",
"state": "DU",
"country": "AE",
"ip": "127.0.0.1"
},
"payment_result": {
"response_status": "A",
"response_code": "831000",
"response_message": "Authorised",
"acquirer_message": "ACCEPT",
"acquirer_rrn": "014910159369",
"transaction_time": "2020-05-28T14:35:38+04:00"
},
"payment_info": {
"card_type": "Credit",
"card_scheme": "Visa",
"payment_description": "4111 11## #### 1111"
}
}
如果 python 中有现成的方法可以实现这一点,那将非常有帮助。
一如既往的感谢。
针对您关于 ksort()
and http_build_query()
的问题,以下是使用 PHP 7.3 和以下代码(基于您给定的 code/data 给定)时的结果。首先,请注意,当我 运行 ksort()
在您的示例数据上时,似乎 ksort()
对数据中的初始键进行排序,但内部键似乎没有排序。
为了也对内部键进行排序,我编写了一个名为 sort_again()
的简单函数,它似乎对内部键进行排序。普通 ksort()
与 sort_again()
结果的结果低于以下示例 PHP 代码。
<?php
$jsonData = '
{
"tran_ref": "TST2014900000688",
"cart_id": "Sample Payment",
"cart_description": "Sample Payment",
"cart_currency": "AED",
"cart_amount": "1",
"customer_details": {
"name": "John Smith",
"email": "jsmith@gmail.com",
"phone": "9711111111111",
"street1": "404, 11th st, void",
"city": "Dubai",
"state": "DU",
"country": "AE",
"ip": "127.0.0.1"
},
"payment_result": {
"response_status": "A",
"response_code": "831000",
"response_message": "Authorised",
"acquirer_message": "ACCEPT",
"acquirer_rrn": "014910159369",
"transaction_time": "2020-05-28T14:35:38+04:00"
},
"payment_info": {
"card_type": "Credit",
"card_scheme": "Visa",
"payment_description": "4111 11## #### 1111"
}
}
';
$jsonArray = json_decode($jsonData, $flags=JSON_OBJECT_AS_ARRAY);
ksort($jsonArray);
echo "ksort() results:\n";
print_r($jsonArray);
// ref: q16.py
function sort_again($arr) {
ksort($arr);
$result = [];
foreach ($arr as $key => $value) {
if (is_array($value)) {
$result[$key] = sort_again($value);
} else {
$result[$key] = $value;
}
}
return $result;
}
$result = sort_again($jsonArray);
echo "sort_again() results:\n";
print_r($result);
$querystring = http_build_query($result);
echo "http_build_query() results:\n";
echo $querystring;
输出:
ksort() results:
Array
(
[cart_amount] => 1
[cart_currency] => AED
[cart_description] => Sample Payment
[cart_id] => Sample Payment
[customer_details] => Array
(
[name] => John Smith
[email] => jsmith@gmail.com
[phone] => 9711111111111
[street1] => 404, 11th st, void
[city] => Dubai
[state] => DU
[country] => AE
[ip] => 127.0.0.1
)
[payment_info] => Array
(
[card_type] => Credit
[card_scheme] => Visa
[payment_description] => 4111 11## #### 1111
)
[payment_result] => Array
(
[response_status] => A
[response_code] => 831000
[response_message] => Authorised
[acquirer_message] => ACCEPT
[acquirer_rrn] => 014910159369
[transaction_time] => 2020-05-28T14:35:38+04:00
)
[tran_ref] => TST2014900000688
)
sort_again() results:
Array
(
[cart_amount] => 1
[cart_currency] => AED
[cart_description] => Sample Payment
[cart_id] => Sample Payment
[customer_details] => Array
(
[city] => Dubai
[country] => AE
[email] => jsmith@gmail.com
[ip] => 127.0.0.1
[name] => John Smith
[phone] => 9711111111111
[state] => DU
[street1] => 404, 11th st, void
)
[payment_info] => Array
(
[card_scheme] => Visa
[card_type] => Credit
[payment_description] => 4111 11## #### 1111
)
[payment_result] => Array
(
[acquirer_message] => ACCEPT
[acquirer_rrn] => 014910159369
[response_code] => 831000
[response_message] => Authorised
[response_status] => A
[transaction_time] => 2020-05-28T14:35:38+04:00
)
[tran_ref] => TST2014900000688
)
http_build_query() results: cart_amount=1&cart_currency=AED&cart_description=Sample+Payment&cart_id=Sample+Payment&customer_details%5Bcity%5D=Dubai&customer_details%5Bcountry%5D=AE&customer_details%5Bemail%5D=jsmith%40gmail.com&customer_details%5Bip%5D=127.0.0.1&customer_details%5Bname%5D=John+Smith&customer_details%5Bphone%5D=9711111111111&customer_details%5Bstate%5D=DU&customer_details%5Bstreet1%5D=404%2C+11th+st%2C+void&payment_info%5Bcard_scheme%5D=Visa&payment_info%5Bcard_type%5D=Credit&payment_info%5Bpayment_description%5D=4111+11%23%23+%23%23%23%23+1111&payment_result%5Bacquirer_message%5D=ACCEPT&payment_result%5Bacquirer_rrn%5D=014910159369&payment_result%5Bresponse_code%5D=831000&payment_result%5Bresponse_message%5D=Authorised&payment_result%5Bresponse_status%5D=A&payment_result%5Btransaction_time%5D=2020-05-28T14%3A35%3A38%2B04%3A00&tran_ref=TST2014900000688
(注意:由于代码格式问题,输出实际上在 http_build_query() results:
部分后有一个换行符,但我似乎无法让代码块正常工作当试图在 post.)
中展示时
现在,对于问题的第二部分,如果您使用 Python 执行与 ksort()
类似的操作,下面的代码示例显示了如何使用 sort_again()
在 Python 上下文中运行。另外,据我所知,Python 中 http_build_query()
的类似选项可能类似于 urllib.parse.urlencode()
。但是,我确实注意到,此方法生成的查询字符串与 PHP http_build_query()
函数略有不同。在本 post.
末尾有更多相关信息
import json
import pprint
from collections import OrderedDict
from urllib.parse import urlencode
obj = {
"tran_ref": "TST2014900000688",
"cart_id": "Sample Payment",
"cart_description": "Sample Payment",
"cart_currency": "AED",
"cart_amount": "1",
"customer_details": {
"name": "John Smith",
"email": "jsmith@gmail.com",
"phone": "9711111111111",
"street1": "404, 11th st, void",
"city": "Dubai",
"state": "DU",
"country": "AE",
"ip": "127.0.0.1"
},
"payment_result": {
"response_status": "A",
"response_code": "831000",
"response_message": "Authorised",
"acquirer_message": "ACCEPT",
"acquirer_rrn": "014910159369",
"transaction_time": "2020-05-28T14:35:38+04:00"
},
"payment_info": {
"card_type": "Credit",
"card_scheme": "Visa",
"payment_description": "4111 11## #### 1111"
}
}
def sort_again(obj):
sorted_obj = sorted(obj)
# Note: if you are using Python 3.7 or higher, you should be able
# to use a plain dictionary here instead of using an OrderedDict()
# because the dict class can now remember insertion order.
# ref: https://docs.python.org/3/library/collections.html
# #ordereddict-objects
#d = OrderedDict()
d = {}
i = 0
for key in sorted_obj:
if isinstance(obj[key], dict):
d[sorted_obj[i]] = sort_again(obj[key])
else:
d[sorted_obj[i]] = obj[key]
i += 1
return d
results = sort_again(obj)
print("sort_again() results:")
pprint.pprint(results)
encoded = urlencode(results)
print("urlencode() results:")
print(encoded)
输出:
sort_again() results:
{'cart_amount': '1',
'cart_currency': 'AED',
'cart_description': 'Sample Payment',
'cart_id': 'Sample Payment',
'customer_details': {'city': 'Dubai',
'country': 'AE',
'email': 'jsmith@gmail.com',
'ip': '127.0.0.1',
'name': 'John Smith',
'phone': '9711111111111',
'state': 'DU',
'street1': '404, 11th st, void'},
'payment_info': {'card_scheme': 'Visa',
'card_type': 'Credit',
'payment_description': '4111 11## #### 1111'},
'payment_result': {'acquirer_message': 'ACCEPT',
'acquirer_rrn': '014910159369',
'response_code': '831000',
'response_message': 'Authorised',
'response_status': 'A',
'transaction_time': '2020-05-28T14:35:38+04:00'},
'tran_ref': 'TST2014900000688'}
urlencode() results:
cart_amount=1&cart_currency=AED&cart_description=Sample+Payment&cart_id=Sample+Payment&customer_details=%7B%27city%27%3A+%27Dubai%27%2C+%27country%27%3A+%27AE%27%2C+%27email%27%3A+%27jsmith%40gmail.com%27%2C+%27ip%27%3A+%27127.0.0.1%27%2C+%27name%27%3A+%27John+Smith%27%2C+%27phone%27%3A+%279711111111111%27%2C+%27state%27%3A+%27DU%27%2C+%27street1%27%3A+%27404%2C+11th+st%2C+void%27%7D&payment_info=%7B%27card_scheme%27%3A+%27Visa%27%2C+%27card_type%27%3A+%27Credit%27%2C+%27payment_description%27%3A+%274111+11%23%23+%23%23%23%23+1111%27%7D&payment_result=%7B%27acquirer_message%27%3A+%27ACCEPT%27%2C+%27acquirer_rrn%27%3A+%27014910159369%27%2C+%27response_code%27%3A+%27831000%27%2C+%27response_message%27%3A+%27Authorised%27%2C+%27response_status%27%3A+%27A%27%2C+%27transaction_time%27%3A+%272020-05-28T14%3A35%3A38%2B04%3A00%27%7D&tran_ref=TST2014900000688
现在,关于 http_build_query()
和 urlencode()
选项之间的差异,当 运行 上面 PHP 和 Python 示例中输出的查询字符串时通过 an online tool,这里是解码后的查询字符串:
PHP版本输出:
cart_amount=1&cart_currency=AED&cart_description=Sample+Payment&cart_id=Sample+Payment&customer_details[city]=Dubai&customer_details[country]=AE&customer_details[email]=jsmith@gmail.com&customer_details[ip]=127.0.0.1&customer_details[name]=John+Smith&customer_details[phone]=9711111111111&customer_details[state]=DU&customer_details[street1]=404,+11th+st,+void&payment_info[card_scheme]=Visa&payment_info[card_type]=Credit&payment_info[payment_description]=4111+11##+####+1111&payment_result[acquirer_message]=ACCEPT&payment_result[acquirer_rrn]=014910159369&payment_result[response_code]=831000&payment_result[response_message]=Authorised&payment_result[response_status]=A&payment_result[transaction_time]=2020-05-28T14:35:38+04:00&tran_ref=TST2014900000688
Python版本输出:
cart_amount=1&cart_currency=AED&cart_description=Sample+Payment&cart_id=Sample+Payment&customer_details={'city':+'Dubai',+'country':+'AE',+'email':+'jsmith@gmail.com',+'ip':+'127.0.0.1',+'name':+'John+Smith',+'phone':+'9711111111111',+'state':+'DU',+'street1':+'404,+11th+st,+void'}&payment_info={'card_scheme':+'Visa',+'card_type':+'Credit',+'payment_description':+'4111+11##+####+1111'}&payment_result={'acquirer_message':+'ACCEPT',+'acquirer_rrn':+'014910159369',+'response_code':+'831000',+'response_message':+'Authorised',+'response_status':+'A',+'transaction_time':+'2020-05-28T14:35:38+04:00'}&tran_ref=TST2014900000688
从这个输出来看,在我看来,查询字符串中的差异(特别是 PHP []
与 Python {}
项)可能与如何相关PHP 经常使用数组来处理结构化数据,而 Python 也可以使用字典之类的东西(而不是仅仅使用列表之类的东西)。我不知道这种差异是否会对您的用例产生影响,但想指出即使 PHP 函数和 Python 方法生成的输出也可能略有不同使用的都是相似的。
另外:
如果您不想从 Python 示例中得到 +
signs in the query string 输出,可以进行以下更改:
在上面的 Python 示例中更改此行:
from urllib.parse import urlencode
为此:
from urllib.parse import quote, urlencode
还有这一行:
encoded = urlencode(results)
为此:
encoded = urlencode(results, quote_via=quote)
查询字符串输出应如下所示:
cart_amount=1&cart_currency=AED&cart_description=Sample%20Payment&cart_id=Sample%20Payment&customer_details=%7B%27city%27%3A%20%27Dubai%27%2C%20%27country%27%3A%20%27AE%27%2C%20%27email%27%3A%20%27jsmith%40gmail.com%27%2C%20%27ip%27%3A%20%27127.0.0.1%27%2C%20%27name%27%3A%20%27John%20Smith%27%2C%20%27phone%27%3A%20%279711111111111%27%2C%20%27state%27%3A%20%27DU%27%2C%20%27street1%27%3A%20%27404%2C%2011th%20st%2C%20void%27%7D&payment_info=%7B%27card_scheme%27%3A%20%27Visa%27%2C%20%27card_type%27%3A%20%27Credit%27%2C%20%27payment_description%27%3A%20%274111%2011%23%23%20%23%23%23%23%201111%27%7D&payment_result=%7B%27acquirer_message%27%3A%20%27ACCEPT%27%2C%20%27acquirer_rrn%27%3A%20%27014910159369%27%2C%20%27response_code%27%3A%20%27831000%27%2C%20%27response_message%27%3A%20%27Authorised%27%2C%20%27response_status%27%3A%20%27A%27%2C%20%27transaction_time%27%3A%20%272020-05-28T14%3A35%3A38%2B04%3A00%27%7D&tran_ref=TST2014900000688
And when decoded,应该是这样的:
cart_amount=1&cart_currency=AED&cart_description=Sample Payment&cart_id=Sample Payment&customer_details={'city': 'Dubai', 'country': 'AE', 'email': 'jsmith@gmail.com', 'ip': '127.0.0.1', 'name': 'John Smith', 'phone': '9711111111111', 'state': 'DU', 'street1': '404, 11th st, void'}&payment_info={'card_scheme': 'Visa', 'card_type': 'Credit', 'payment_description': '4111 11## #### 1111'}&payment_result={'acquirer_message': 'ACCEPT', 'acquirer_rrn': '014910159369', 'response_code': '831000', 'response_message': 'Authorised', 'response_status': 'A', 'transaction_time': '2020-05-28T14:35:38+04:00'}&tran_ref=TST2014900000688
我需要 re-create Python 中的以下代码来验证 API 响应的 header 中包含的签名。
<?php
// Profile Key (ServerKey)
$serverKey = "SRJNLKHG6K-HWMDRGW66J-LRWTGDGRNK"; // Example
// Request body include a signature post Form URL encoded field
// 'signature' (hexadecimal encoding for hmac of sorted post form fields)
$requestSignature = $_POST["signature"];
unset($_POST["signature"]);
$signature_fields = $_POST;
// Ignore empty values fields
$signature_fields = array_filter($signature_fields);
// Sort form fields
ksort($signature_fields);
// Generate URL-encoded query string of Post fields except signature field.
$query = http_build_query($signature_fields);
$signature = hash_hmac('sha256', $query, $serverKey);
if (hash_equals($signature,$requestSignature) === TRUE) {
// VALID Redirect
// Do your logic
}else{
// INVALID Redirect
// Log request
}
?>
我对 PHP 的了解为 0,过去 24 小时我一直在尝试 re-create 但没有成功。
我坚持的部分是 ksort 和 http_build_query 方法。
我想了解的是,对于嵌套数组,这些方法的结果会是什么样子,例如:
{
"tran_ref": "TST2014900000688",
"cart_id": "Sample Payment",
"cart_description": "Sample Payment",
"cart_currency": "AED",
"cart_amount": "1",
"customer_details": {
"name": "John Smith",
"email": "jsmith@gmail.com",
"phone": "9711111111111",
"street1": "404, 11th st, void",
"city": "Dubai",
"state": "DU",
"country": "AE",
"ip": "127.0.0.1"
},
"payment_result": {
"response_status": "A",
"response_code": "831000",
"response_message": "Authorised",
"acquirer_message": "ACCEPT",
"acquirer_rrn": "014910159369",
"transaction_time": "2020-05-28T14:35:38+04:00"
},
"payment_info": {
"card_type": "Credit",
"card_scheme": "Visa",
"payment_description": "4111 11## #### 1111"
}
}
如果 python 中有现成的方法可以实现这一点,那将非常有帮助。
一如既往的感谢。
针对您关于 ksort()
and http_build_query()
的问题,以下是使用 PHP 7.3 和以下代码(基于您给定的 code/data 给定)时的结果。首先,请注意,当我 运行 ksort()
在您的示例数据上时,似乎 ksort()
对数据中的初始键进行排序,但内部键似乎没有排序。
为了也对内部键进行排序,我编写了一个名为 sort_again()
的简单函数,它似乎对内部键进行排序。普通 ksort()
与 sort_again()
结果的结果低于以下示例 PHP 代码。
<?php
$jsonData = '
{
"tran_ref": "TST2014900000688",
"cart_id": "Sample Payment",
"cart_description": "Sample Payment",
"cart_currency": "AED",
"cart_amount": "1",
"customer_details": {
"name": "John Smith",
"email": "jsmith@gmail.com",
"phone": "9711111111111",
"street1": "404, 11th st, void",
"city": "Dubai",
"state": "DU",
"country": "AE",
"ip": "127.0.0.1"
},
"payment_result": {
"response_status": "A",
"response_code": "831000",
"response_message": "Authorised",
"acquirer_message": "ACCEPT",
"acquirer_rrn": "014910159369",
"transaction_time": "2020-05-28T14:35:38+04:00"
},
"payment_info": {
"card_type": "Credit",
"card_scheme": "Visa",
"payment_description": "4111 11## #### 1111"
}
}
';
$jsonArray = json_decode($jsonData, $flags=JSON_OBJECT_AS_ARRAY);
ksort($jsonArray);
echo "ksort() results:\n";
print_r($jsonArray);
// ref: q16.py
function sort_again($arr) {
ksort($arr);
$result = [];
foreach ($arr as $key => $value) {
if (is_array($value)) {
$result[$key] = sort_again($value);
} else {
$result[$key] = $value;
}
}
return $result;
}
$result = sort_again($jsonArray);
echo "sort_again() results:\n";
print_r($result);
$querystring = http_build_query($result);
echo "http_build_query() results:\n";
echo $querystring;
输出:
ksort() results:
Array
(
[cart_amount] => 1
[cart_currency] => AED
[cart_description] => Sample Payment
[cart_id] => Sample Payment
[customer_details] => Array
(
[name] => John Smith
[email] => jsmith@gmail.com
[phone] => 9711111111111
[street1] => 404, 11th st, void
[city] => Dubai
[state] => DU
[country] => AE
[ip] => 127.0.0.1
)
[payment_info] => Array
(
[card_type] => Credit
[card_scheme] => Visa
[payment_description] => 4111 11## #### 1111
)
[payment_result] => Array
(
[response_status] => A
[response_code] => 831000
[response_message] => Authorised
[acquirer_message] => ACCEPT
[acquirer_rrn] => 014910159369
[transaction_time] => 2020-05-28T14:35:38+04:00
)
[tran_ref] => TST2014900000688
)
sort_again() results:
Array
(
[cart_amount] => 1
[cart_currency] => AED
[cart_description] => Sample Payment
[cart_id] => Sample Payment
[customer_details] => Array
(
[city] => Dubai
[country] => AE
[email] => jsmith@gmail.com
[ip] => 127.0.0.1
[name] => John Smith
[phone] => 9711111111111
[state] => DU
[street1] => 404, 11th st, void
)
[payment_info] => Array
(
[card_scheme] => Visa
[card_type] => Credit
[payment_description] => 4111 11## #### 1111
)
[payment_result] => Array
(
[acquirer_message] => ACCEPT
[acquirer_rrn] => 014910159369
[response_code] => 831000
[response_message] => Authorised
[response_status] => A
[transaction_time] => 2020-05-28T14:35:38+04:00
)
[tran_ref] => TST2014900000688
)
http_build_query() results: cart_amount=1&cart_currency=AED&cart_description=Sample+Payment&cart_id=Sample+Payment&customer_details%5Bcity%5D=Dubai&customer_details%5Bcountry%5D=AE&customer_details%5Bemail%5D=jsmith%40gmail.com&customer_details%5Bip%5D=127.0.0.1&customer_details%5Bname%5D=John+Smith&customer_details%5Bphone%5D=9711111111111&customer_details%5Bstate%5D=DU&customer_details%5Bstreet1%5D=404%2C+11th+st%2C+void&payment_info%5Bcard_scheme%5D=Visa&payment_info%5Bcard_type%5D=Credit&payment_info%5Bpayment_description%5D=4111+11%23%23+%23%23%23%23+1111&payment_result%5Bacquirer_message%5D=ACCEPT&payment_result%5Bacquirer_rrn%5D=014910159369&payment_result%5Bresponse_code%5D=831000&payment_result%5Bresponse_message%5D=Authorised&payment_result%5Bresponse_status%5D=A&payment_result%5Btransaction_time%5D=2020-05-28T14%3A35%3A38%2B04%3A00&tran_ref=TST2014900000688
(注意:由于代码格式问题,输出实际上在 http_build_query() results:
部分后有一个换行符,但我似乎无法让代码块正常工作当试图在 post.)
现在,对于问题的第二部分,如果您使用 Python 执行与 ksort()
类似的操作,下面的代码示例显示了如何使用 sort_again()
在 Python 上下文中运行。另外,据我所知,Python 中 http_build_query()
的类似选项可能类似于 urllib.parse.urlencode()
。但是,我确实注意到,此方法生成的查询字符串与 PHP http_build_query()
函数略有不同。在本 post.
import json
import pprint
from collections import OrderedDict
from urllib.parse import urlencode
obj = {
"tran_ref": "TST2014900000688",
"cart_id": "Sample Payment",
"cart_description": "Sample Payment",
"cart_currency": "AED",
"cart_amount": "1",
"customer_details": {
"name": "John Smith",
"email": "jsmith@gmail.com",
"phone": "9711111111111",
"street1": "404, 11th st, void",
"city": "Dubai",
"state": "DU",
"country": "AE",
"ip": "127.0.0.1"
},
"payment_result": {
"response_status": "A",
"response_code": "831000",
"response_message": "Authorised",
"acquirer_message": "ACCEPT",
"acquirer_rrn": "014910159369",
"transaction_time": "2020-05-28T14:35:38+04:00"
},
"payment_info": {
"card_type": "Credit",
"card_scheme": "Visa",
"payment_description": "4111 11## #### 1111"
}
}
def sort_again(obj):
sorted_obj = sorted(obj)
# Note: if you are using Python 3.7 or higher, you should be able
# to use a plain dictionary here instead of using an OrderedDict()
# because the dict class can now remember insertion order.
# ref: https://docs.python.org/3/library/collections.html
# #ordereddict-objects
#d = OrderedDict()
d = {}
i = 0
for key in sorted_obj:
if isinstance(obj[key], dict):
d[sorted_obj[i]] = sort_again(obj[key])
else:
d[sorted_obj[i]] = obj[key]
i += 1
return d
results = sort_again(obj)
print("sort_again() results:")
pprint.pprint(results)
encoded = urlencode(results)
print("urlencode() results:")
print(encoded)
输出:
sort_again() results:
{'cart_amount': '1',
'cart_currency': 'AED',
'cart_description': 'Sample Payment',
'cart_id': 'Sample Payment',
'customer_details': {'city': 'Dubai',
'country': 'AE',
'email': 'jsmith@gmail.com',
'ip': '127.0.0.1',
'name': 'John Smith',
'phone': '9711111111111',
'state': 'DU',
'street1': '404, 11th st, void'},
'payment_info': {'card_scheme': 'Visa',
'card_type': 'Credit',
'payment_description': '4111 11## #### 1111'},
'payment_result': {'acquirer_message': 'ACCEPT',
'acquirer_rrn': '014910159369',
'response_code': '831000',
'response_message': 'Authorised',
'response_status': 'A',
'transaction_time': '2020-05-28T14:35:38+04:00'},
'tran_ref': 'TST2014900000688'}
urlencode() results:
cart_amount=1&cart_currency=AED&cart_description=Sample+Payment&cart_id=Sample+Payment&customer_details=%7B%27city%27%3A+%27Dubai%27%2C+%27country%27%3A+%27AE%27%2C+%27email%27%3A+%27jsmith%40gmail.com%27%2C+%27ip%27%3A+%27127.0.0.1%27%2C+%27name%27%3A+%27John+Smith%27%2C+%27phone%27%3A+%279711111111111%27%2C+%27state%27%3A+%27DU%27%2C+%27street1%27%3A+%27404%2C+11th+st%2C+void%27%7D&payment_info=%7B%27card_scheme%27%3A+%27Visa%27%2C+%27card_type%27%3A+%27Credit%27%2C+%27payment_description%27%3A+%274111+11%23%23+%23%23%23%23+1111%27%7D&payment_result=%7B%27acquirer_message%27%3A+%27ACCEPT%27%2C+%27acquirer_rrn%27%3A+%27014910159369%27%2C+%27response_code%27%3A+%27831000%27%2C+%27response_message%27%3A+%27Authorised%27%2C+%27response_status%27%3A+%27A%27%2C+%27transaction_time%27%3A+%272020-05-28T14%3A35%3A38%2B04%3A00%27%7D&tran_ref=TST2014900000688
现在,关于 http_build_query()
和 urlencode()
选项之间的差异,当 运行 上面 PHP 和 Python 示例中输出的查询字符串时通过 an online tool,这里是解码后的查询字符串:
PHP版本输出:
cart_amount=1&cart_currency=AED&cart_description=Sample+Payment&cart_id=Sample+Payment&customer_details[city]=Dubai&customer_details[country]=AE&customer_details[email]=jsmith@gmail.com&customer_details[ip]=127.0.0.1&customer_details[name]=John+Smith&customer_details[phone]=9711111111111&customer_details[state]=DU&customer_details[street1]=404,+11th+st,+void&payment_info[card_scheme]=Visa&payment_info[card_type]=Credit&payment_info[payment_description]=4111+11##+####+1111&payment_result[acquirer_message]=ACCEPT&payment_result[acquirer_rrn]=014910159369&payment_result[response_code]=831000&payment_result[response_message]=Authorised&payment_result[response_status]=A&payment_result[transaction_time]=2020-05-28T14:35:38+04:00&tran_ref=TST2014900000688
Python版本输出:
cart_amount=1&cart_currency=AED&cart_description=Sample+Payment&cart_id=Sample+Payment&customer_details={'city':+'Dubai',+'country':+'AE',+'email':+'jsmith@gmail.com',+'ip':+'127.0.0.1',+'name':+'John+Smith',+'phone':+'9711111111111',+'state':+'DU',+'street1':+'404,+11th+st,+void'}&payment_info={'card_scheme':+'Visa',+'card_type':+'Credit',+'payment_description':+'4111+11##+####+1111'}&payment_result={'acquirer_message':+'ACCEPT',+'acquirer_rrn':+'014910159369',+'response_code':+'831000',+'response_message':+'Authorised',+'response_status':+'A',+'transaction_time':+'2020-05-28T14:35:38+04:00'}&tran_ref=TST2014900000688
从这个输出来看,在我看来,查询字符串中的差异(特别是 PHP []
与 Python {}
项)可能与如何相关PHP 经常使用数组来处理结构化数据,而 Python 也可以使用字典之类的东西(而不是仅仅使用列表之类的东西)。我不知道这种差异是否会对您的用例产生影响,但想指出即使 PHP 函数和 Python 方法生成的输出也可能略有不同使用的都是相似的。
另外:
如果您不想从 Python 示例中得到 +
signs in the query string 输出,可以进行以下更改:
在上面的 Python 示例中更改此行:
from urllib.parse import urlencode
为此:
from urllib.parse import quote, urlencode
还有这一行:
encoded = urlencode(results)
为此:
encoded = urlencode(results, quote_via=quote)
查询字符串输出应如下所示:
cart_amount=1&cart_currency=AED&cart_description=Sample%20Payment&cart_id=Sample%20Payment&customer_details=%7B%27city%27%3A%20%27Dubai%27%2C%20%27country%27%3A%20%27AE%27%2C%20%27email%27%3A%20%27jsmith%40gmail.com%27%2C%20%27ip%27%3A%20%27127.0.0.1%27%2C%20%27name%27%3A%20%27John%20Smith%27%2C%20%27phone%27%3A%20%279711111111111%27%2C%20%27state%27%3A%20%27DU%27%2C%20%27street1%27%3A%20%27404%2C%2011th%20st%2C%20void%27%7D&payment_info=%7B%27card_scheme%27%3A%20%27Visa%27%2C%20%27card_type%27%3A%20%27Credit%27%2C%20%27payment_description%27%3A%20%274111%2011%23%23%20%23%23%23%23%201111%27%7D&payment_result=%7B%27acquirer_message%27%3A%20%27ACCEPT%27%2C%20%27acquirer_rrn%27%3A%20%27014910159369%27%2C%20%27response_code%27%3A%20%27831000%27%2C%20%27response_message%27%3A%20%27Authorised%27%2C%20%27response_status%27%3A%20%27A%27%2C%20%27transaction_time%27%3A%20%272020-05-28T14%3A35%3A38%2B04%3A00%27%7D&tran_ref=TST2014900000688
And when decoded,应该是这样的:
cart_amount=1&cart_currency=AED&cart_description=Sample Payment&cart_id=Sample Payment&customer_details={'city': 'Dubai', 'country': 'AE', 'email': 'jsmith@gmail.com', 'ip': '127.0.0.1', 'name': 'John Smith', 'phone': '9711111111111', 'state': 'DU', 'street1': '404, 11th st, void'}&payment_info={'card_scheme': 'Visa', 'card_type': 'Credit', 'payment_description': '4111 11## #### 1111'}&payment_result={'acquirer_message': 'ACCEPT', 'acquirer_rrn': '014910159369', 'response_code': '831000', 'response_message': 'Authorised', 'response_status': 'A', 'transaction_time': '2020-05-28T14:35:38+04:00'}&tran_ref=TST2014900000688