通讯说明
所有接口均使用 HTTPS 通信,数据包格式为 json(HTTP 请求的 content-type 字段必须使用 application/json)。
请求必须传认证信息,需要传认证码和认证算法。
响应要验证认证码。
所有接口参数名使用的字母均为小写。
数据包格式说明
请求包格式
请求格式示例(以 query_order 接口为例):
{??????"authen_info":?{??????????"a":?{??????????????"authen_type":?1,??????????????"authen_code":?"69E65DA0A32F18D059DBE81CA4D9D702470184966E12A03715584249788BD8DD"??????????}??????},??????"request_content":?"{\\"pay_mch_key\\":?{\\"pay_platform\\":?1,?\\"sub_pay_platform\\":?100,?\\"out_shop_id\\":?\\"sz011biKxOguirmBqiFR\\",?\\"out_sub_mch_id\\":?\\"sz01KzuCUOmw8yjtPite\\",?\\"out_mch_id\\":?\\"sz01lXKA6DKGjNzr2l4B\\"},?\\"trade_type\\":?1,?\\"out_trade_no\\":?\\"sz010002cz11564386781\\",?\\"nonce_str\\":?\\"E94C00688C3F429CA2B0B396BF823548\\",?\\"order_client\\":?{\\"staff_id\\":?\\"1192\\",?\\"machine_no\\":?\\"1111\\",?\\"terminal_type\\":?1,?\\"sdk_version\\":?\\"1.0\\",?\\"device_id\\":?\\"12345\\",?\\"spbill_create_ip\\":?\\"90.0.00.0\\"}}"??}??
详解:
请求包含两个字段:authen_info 和 request_content。前者表示认证信息,为 json 结构;后者表示请求具体内容,为 json 形式字符串化。
request_content 为具体请求内容的 json 字符串化结构,见各具体接口。
authen_info 结构有嵌套属性 a,字段为认证码:
字段 | 类型 | 说明 |
authen_type | Number(32) | 认证算法类型。只支持填1,即为 HMAC-SHA256 |
authen_code | String(64) | 认证码 |
认证码生成算法:HMAC-SHA256 认证密钥为服务商在云支付录入商户时,在子商户页面上生成的认证密钥。
响应包格式
响应包与请求包类似,包含两个字段:authen_info 和 response_content。前者表示认证信息(响应包仅有认证码方式),为 json 结构;后者表示响应具体内容,为 json 形式字符串化。响应格式示例(以交接班接口为例):
{??????"authen_info":?{??????????"a":{?????????????"authen_type":?1,??????????????"authen_code"?:?"1CB622818DF1E2D91741A5FE792F1EFDD2557343FBD1275628E832A95CBB0FBC"??????????}??????},??????"response_content":?"{\\"status\\":0,\\"description\\":\\"\\\\u64CD\\\\u4F5C\\\\u6210\\\\u529F\\\\u3002\\",\\"log_id\\":1167366844,\\"internal_status\\":0}"??}??
其它说明
各种 update 接口中,如选填字段不填写,则该字段不需修改。清空此字段时,需上传此字段的内容为空。
接口调用说明
交易接口中的门店信息,必须和子商户在云支付手机端商户管理系统设置的一致。
订单和退款单号说明
为了保护不同商户的订单号不重复,云支付为每个服务商录入的子商户分配“云支付订单前缀”,在云支付后台的商户详情中可以看到,该商户的订单和退款单必须以云支付子商户号做前缀。
数据包构造示例
下面以刷卡支付为例来介绍整个认证过程:
客户端向服务器发送请求
1. 判定使用场景。
在这个示例中,我们要发出的是刷卡支付请求。因此,需要使用认证算法来计算认证码。
2. 根据接口的输入参数,构造 json 格式字符串。
?
?3. 将 json 格式字符串转换为字符串,并使用认证算法,认证 key 来计算认证码。
?
?4. 构造 authen_info 结构。
?
?5. 构造 json 格式的请求数据包,需要包含 authen_info 和 request_content 字段。
6. 将 json 格式请求转换为字符串,发送给服务器。
?
?客户端验证服务器应答消息
1. 将响应包从 string 转换为 json 格式消息。
2. 取出 json 格式消息中的 authen_info 和 response_content 字段信息。
3. 使用认证算法和认证 key 对 response_content 计算认证码。
4. 将计算得到的认证码和 authen_info 中的 authen_code 进行比较;正确情况下,两者应该一致。
代码示例(C++)
构造请求字符串(以刷卡支付为例):
std::string?MicroPay_request_str()??{??????/*?1.构造业务请求参数?*/??????Json::Value?pay_mch_key;??????//?构造?pay_mch_key??????pay_mch_key["pay_platform"]???=?1;??????pay_mch_key["out_mch_id"]?????=?"sz013NzuonO6CMJd0rCB";??????pay_mch_key["out_sub_mch_id"]?=?"sz01ELTR281OFpmdAp6J";??????pay_mch_key["out_shop_id"]????=?"sz01qyoPJmd3j1hWmul4";??????Json::Value?pay_content;??????//?构造?pay_content??????pay_content["out_trade_no"]???=?"sz0100lmnx20171228151031";??????pay_content["author_code"]????=?"134680423163089456";??????pay_content["total_fee"]??????=?1;??????pay_content["fee_type"]???????=?"CNY";??????pay_content["attach"]?????????=?"attach";??????Json::Value?order_client;????????//?构造?order_client??????order_client["machine_no"]???????=?"32-62-A8-14-B3-C0";??????order_client["sdk_version"]??????=?"1.0";??????order_client["device_id"]????????=?1;??????order_client["spbill_create_ip"]?=?"192.168.100.75";??????order_client["staff_id"]?????????=?"1003";?????order_client["terminal_type"]????=?2;??????Json::Value?request_content;?????//?构造?request_content??????request_content["pay_mch_key"]???=?pay_mch_key;??????request_content["pay_content"]???=?pay_content;??????request_content["order_client"]??=?order_client;??????request_content["nonce_str"]?????=?"416492026bc84091bcaf7e74ea90ceba";??????Json::FastWriter?w;??????std::string?request_content_str?=?w.write(request_content);??????/*?2.?根据上面的业务请求参数计算认证码?*/??????Json::Value?authen;??????std::string?hmac;?????calc_HMAC_SHA256(authen_key,?request_content_str,?&hmac);?//计算认证码??????authen["authen_code"]?=?hmac;??????authen["authen_type"]?=?1;?//hmac_sha256?为1??????Json::Value?authen_info;??????authen_info["a"]?=?authen;??//认证码??????/*?3.?拼装最终请求参数?*/??????Json::Value?request;???????//构造最终发给服务器的请求??????request["request_content"]?=?request_content_str;??????request["authen_info"]?????=?authen_info;??????std::string?request_str?=?w.write(request);??????return?request_str;??}??
计算认证码:
/*?返回是否成功,成功时认证码存放于?hmac?指向的?string?*/??bool?calc_HMAC_SHA256(const?std::string?&key,?const?std::string?&input,?std::string?*hmac)??{??????unsigned?char?md[SHA256_DIGEST_LENGTH]?=?{0};//32?bytes??????char?format_md[65]?=?{0};??????unsigned?int?md_len?=?sizeof(md);??????HMAC_CTX?ctx;??????HMAC_CTX_init(&ctx);??????if?(!HMAC_Init_ex(&ctx,?key.data(),?(int)key.length(),?EVP_sha256(),?NULL)??||??????????!HMAC_Update(&ctx,?(const?unsigned?char?*)input.data(),?input.length())?||??????????!HMAC_Final(&ctx,?md,?&md_len))?{??????????HMAC_CTX_cleanup(&ctx);??????????return?false;??????}??????HMAC_CTX_cleanup(&ctx);??????for?(int?i?=?0;?i?<?32;?i++)?{??????????snprintf(&format_md[i?*?2],?3,?"%02x",?md[i]);?//二进制转为十六进制大写??????}??????hmac->assign(format_md);??????//?转大写??????transform(hmac->begin(),?hmac->end(),?hmac->begin(),?::toupper);??????return?true;??}??
?