微信云支付 SDK
接入场景
本文为您介绍收银机+扫码枪场景的接入流程,在收银机上实现腾讯云支付功能,当用扫码枪扫码顾客微信支付或支付宝付款码,收银机调用云支付的 API 发起刷卡支付。
接入流程
服务商/子商户入驻流程
前提条件
入驻流程
说明
流程图中的 out_mch_id、out_sub_mch_id、out_shop_id、decive_id、staff_id、子商户订单前缀、认证 key、私钥在调用刷卡支付时需用到。
获取云支付服务商账号
登录 云支付控制台,选择服务商账户管理,在服务商账号列表可查看云支付服务商账号。
获取云支付子商户账号
登录 云支付控制台,选择子商户管理,在子商户账号列表可查看云支付子商户账号。
获取订单号前缀
在子商户详情页有两个订单前缀,推荐使用纯数字的8位订单前缀,便于机具扫订单条码退款时很容易扫上。
获取门店全局 ID、设备 ID(设备编号)、店员 ID(店员编号)
获取认证密钥和签名私钥
配置子商户时,保存到本地的“认证密码”和“签名私钥”。
SDK API 接入流程
刷卡支付接入流程(顾客被扫)
1. 初始化 SDK 时,commonconf 配置的 micro_pay_query_order_count 和 micro_pay_query_order_interval 两个参数,分别为刷卡支付后查询结果次数和间隔,默认次数是25次、时间间隔是6s,即一共会持续查询150s看是否有支付结果。
用户如果需要调整次数和间隔时间太,可在初始化时设置这两个参数的值。
2. 提交刷卡支付时,out_trade_no 为云支付分配的子商户订单前缀+商户自己定义的部分。子商户订单前缀可在云支付控制台的子商户页面获取。
3. 刷卡支付是一个异步操作,提交刷卡支付成功,不代表支付成功,只代表 SDK 已经受理这笔交易,调用方需要调用查单接口来确认支付结果。
4. 刷卡支付提交后,返回参数里会有一个 json 结构的支付平台,需要调用方解析出来,查单的时候需用这里解析出来的支付平台。
5. SDK 提供的接口,请求参数和返回参数均是 json 结构。
6. 使用 SDK 的 get_errmsg() 接口获取具体的错误描述信息。
退款接入流程
申请退款成功,并不代表退款成功。
退款是一个异步过程,申请退款成功后,只是代表第三方支付平台受理这笔退款,是否到账需要看这笔钱退到哪里。
如果是退款至微信零钱账户或支付宝账户,会很快到账。
如果是退款至顾客的银行卡,到账时间与银行处理进度相关,可能要花几个小时。
因此申请退款成功后,需告知顾客,申请退款已经成功,请关注后续到账情况。顾客可以关注微信或支付宝的消息,查看已经发起退款或退款到账的消息。
如果想在设备上看这笔退款是否到账,可以调用退款查询接口,通过退款单的状态来查看是否退款成功。
日志上报
接口说明
机具直接对接云支付的情况下,为方便商户定位问题,云支付提供日志上报接口,将日志数据上报到云支付的后端,可以帮助商户分析问题,例如机具业务流程各个环节消耗了多少时延,业务流程各个环节的数据情况等。
接口名:
https://pay.qcloud.com/cpay/upload_client_monitor_info
说明
云支付日志上报是接口维度的,例如刷卡支付、查询订单、退款。每个接口,调用方可以统计调用接口的时延传到云支付。
业务流程上的日志,可以上传多条,每天日志的记录时间点、精确到毫秒,需要调用方自己来完成。
流程说明
说明
总时延 = 记录结束时间 - 记录起始时间
设备维度订单统计
商户需要按设备维度统计订单相关的信息时:
统计某一个设备的订单信息,需要接入方知会商家在手机端管理系统,添加门店的设备 ID 和设备名称。
统计某一个款设备型号的订单,需要在支付时,OrderClient 结构里填写 sub_terminal_type 字段。
统计某一个平台的订单,例如 Windows 平台、Andriod 平台,需要在支付时,OrderClient 结构里填写 terminal_type 字段。
常见问题
请求格式
以下是刷卡支付的请求内容, 为方便用户查看需注意点,以下一整个字符串换行显示。
格式注意一
整个数据格式是一个 json,其中 request_content 的内容也是一个 json,因此这里有两层,所以第二层有\\出现。如下图,括号里的内容本身也是一个 json 结构,toString 后赋给 request_content。
格式注意二
request_content 的内容是一个字符串,如下图,所以第2行和第7号,分别有一个双引号。
计算认证码
参与计算认证码的数据内容如下图,双引号内的数据参与计算认证码,request_content 这个关键字不参与计算认证码。
请求包完整示例
Json::Value pay_mch_key; // 构造 pay_mch_keypay_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_contentpay_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_clientorder_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"] = "10.15.244.75";order_client["staff_id"] = "1003";order_client["terminal_type"] = 2; // 平台 Windows Linux Android posorder_client["sub_terminal_type"] = 1111; //设备型号,如商家的 pos 的 AXX01 型号,这个字段接入方自定义,保证自己设备型号的唯一性,可用于统计某一款设备的订单信息。Json::Value request_content; // 构造 request_contentrequest_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);Json::Value authen;authen["authen_code"] = hmac_sha256(authen_key, request_content_str); //计算认证码authen["authen_type"] = 1; //hmac_sha256 为1Json::Value authen_info;authen_info["a"] = authen; //认证码,签名是 sJson::Value request; //构造最终发给服务器的请求request["request_content"] = request_content_str;request["authen_info"] = authen_info;std::string request_str = w.write(request);return request_str;
订单号
不同设备的唯一性
订单号由云支付分配的订单唯一前缀+商户自定义两部分组成。其中商户自定义部分需要保证不同设备的唯一性,例如一个商户的订单号自定义部分为年+月+日+时+分+秒,会在多个机器支付时出现订单号重复,导致支付失败。
订单号不能回滚
例如商户自定义部分订单号为:机号+年月日+序列号,序列号由1、2、3、.. 往上增。如果某个时间点机器故障或软件故障,序列号不能又从1、2、3往上增,否则会出现订单号重复导致支付失败。