收钱吧-轻POS接口
一次性开发,线上线下全渠道对接所有主流移动支付方式
所有请求格式均采用JSON格式,请求字符集采用UTF-8编码
1、收钱吧官方文档地址:https://doc.shouqianba.com/LitePos/
2、通用请求体样式
{"request": {"head": {"version": "1.0.0","sign_type": "SHA1","appid": "28lp61847655","request_time": "2001-07-04T12:08:56+05:30","reserve": "{}"},"body": {"subject": "this is request business body"}},"signature":"blmSaxUF6/N2XOcz7UWRRVQ5XsVCEz1BpZl6R9Rc6TA3+IfWhJtmCsUZjtw72w1QQ8rEV6+uMh3GWbyzH02Y9dJQCW"
}
3、上干货
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.security.KeyFactory;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSONObject;public class ShouqianbaPush {private static Logger logger = LoggerFactory.getLogger(ShouqianbaPush.class);/**私钥*/private static String privateKeyStr = "收钱吧提供的私钥";/**公钥*/private static String publicKeyStr = "收钱吧提供的公钥";/**轻POS接口地址*/private static final String API_DOMAIN = "https://vapi.shouqianba.com/";/**APPID*/private static final String APP_ID = "你的APPID";/**品牌编号,系统对接前由"收钱吧"分配并提供*/private static final String BRAND_CODE = "收钱吧提供的品牌编号";/**商户内部使用的门店编号*/private static final String STORE_SN = "收钱吧提供的门店编号";/*** 收钱吧 推送支付订单信息* @param url 接口地址* @param orderSn 商户订单号,在商户系统中唯一* @param createTime 商户订单创建时间* @param price 订单价格,精确到分* @param subject 订单简短描述,建议传8个字内* @param operator 操作员,可以传入收款的收银员或导购员。例如"张三"* @param customer 可以传入需要备注顾客的信息* @param posInfo 传入商户系统的产品名称、系统编号等信息,便于帮助商户调查问题* @return* @author lan* @since 2020-7-17*/public static boolean shouqianbaOrderPush(String url,String orderSn,Date createTime,String price,String subject,String operator,String customer,String posInfo) {boolean result = false;try {String timestr = getTime(createTime);//请求接口参数Map<String,Object> param = new HashMap<String,Object>();param.put("request_id", UUID.randomUUID());//请求编号,每次请求必须唯一param.put("brand_code", BRAND_CODE);//品牌编号,系统对接前由"收钱吧"分配并提供param.put("store_sn", STORE_SN);//商户内部使用的门店编号param.put("workstation_sn", "0");//门店收银机编号,如果没有请传入"0"param.put("check_sn", orderSn);param.put("scene", "1");//场景值:1-智能终端,2-H5,4-PCparam.put("sales_time", timestr);param.put("amount", price);param.put("currency", "156");//币种param.put("subject", subject);param.put("operator", operator);param.put("customer", customer);param.put("industry_code", "0");//行业代码, 0=零售;1:酒店; 2:餐饮; 3:文娱; 4:教育;param.put("pos_info", posInfo);param.put("notify_url", "接口调用成功后的回调地址");//eg:http://127.0.0.1:8080/projectName/payNotify.json//传入参数 生成对应签名体//注意:完整的请求内容,如步骤1(不包含"request"字段,仅包括request的值)使用RSA私钥签名,并转换为BASE64编码。即:/*{"head": {"version": "1.0.0","sign_type": "SHA1","appid": "你的APPID","request_time": "2001-07-04T12:08:56+05:30"},"body": {"request_id": UUID.randomUUID(),"brand_code": BRAND_CODE,"store_sn": STORE_SN,......(请求接口参数全部内容)}}*/String signBody = createSignatureBody(timestr,param);//将生成的签名体使用私钥加密,生成签名String sign = getSignature(signBody);//将参数及签名组装成对应的通用请求体格式String paramStr = createParamBody(param,sign,timestr);//进行http post请求String responseStr = sendPost(API_DOMAIN+url,paramStr);Map map = getResponseData(responseStr);if(null != map && null != map.get("result_code") && Integer.parseInt(map.get("result_code").toString()) == 200 ){Map bizResponse = JSONObject.parseObject(map.get("biz_response").toString(),Map.class);if(null != bizResponse && null != bizResponse.get("result_code") && Integer.parseInt(bizResponse.get("result_code").toString()) == 200){result = true;}}} catch (Exception e) {logger.error("收钱吧 推送支付订单失败",e);return false;}return result;}/*** 获取 YYYY-MM-DDThh:mm:ssTZD 格式时间(时间格式请参考官方文档)* @return* @author lan* @since 2020-6-28*/private static String getTime(Date date){SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");if(date == null){return sdf.format(new Date());}return sdf.format(date);}/*** 生成签名体* @param appId 轻POS应用编号,商户入网后由收钱吧技术支持提供* @param storeSn 商户内部使用的门店编号* @param brandCode 品牌编号,系统对接前由"收钱吧"分配并提供* @param checkSn 商户订单号,在商户系统中唯一* @param workstationSn 门店收银机编号,如果没有请传入"0"* @return* @author lan* @since 2020-6-28*/private static String createSignatureBody(String timestr,Map<String,Object> param){String result = null;try {JSONObject head = new JSONObject();head.put("sign_type", "SHA1");head.put("appid", APP_ID);head.put("request_time", timestr);head.put("version", "1.0.0");JSONObject body = new JSONObject();for (String key : param.keySet()) {body.put(key, param.get(key));}JSONObject res = new JSONObject();res.put("head", head);res.put("body", body);result = res.toJSONString();} catch (Exception e) {return null;}return result;}/*** 获取签名* @param signBody* @return* @author lan* @since 2020-7-17*/public static String getSignature(String signBody){try {KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA");gen.initialize(2048);PrivateKey privateKey = getPrivateKey(privateKeyStr);// SHA1withRSA算法进行签名Signature sign = Signature.getInstance("SHA1withRSA");sign.initSign(privateKey);byte[] data = signBody.getBytes();// 更新用于签名的数据sign.update(data);byte[] signature = sign.sign();String res = new String(Base64.encodeBase64(signature));return res;} catch (Exception e) {e.printStackTrace();}return null;}/*** 获取私钥* @param privateKey 私钥字符串* @return*/public static PrivateKey getPrivateKey(String privateKey) throws Exception {KeyFactory keyFactory = KeyFactory.getInstance("RSA");byte[] decodedKey = Base64.decodeBase64(privateKey.getBytes());PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);return keyFactory.generatePrivate(keySpec);}/*** 获取公钥* @param publicKey 公钥字符串* @return*/public static PublicKey getPublicKey(String publicKey) throws Exception {KeyFactory keyFactory = KeyFactory.getInstance("RSA");byte[] decodedKey = Base64.decodeBase64(publicKey.getBytes());X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedKey);return keyFactory.generatePublic(keySpec);}/*** 组建参数体* @param appId* @param storeSn* @param brandCode* @param checkSn* @param workstationSn* @return*/private static String createParamBody(Map<String,Object> param,String signature,String timestr){String result = null;try {JSONObject head = new JSONObject();head.put("sign_type", "SHA1");head.put("appid", APP_ID);head.put("request_time", timestr);head.put("version", "1.0.0");JSONObject body = new JSONObject();for (String key : param.keySet()) {body.put(key, param.get(key));}JSONObject request = new JSONObject();request.put("head", head);request.put("body", body);JSONObject res = new JSONObject();res.put("request", request);res.put("signature", signature);result = res.toJSONString();} catch (Exception e) {return null;}return result;}/*** 向指定 URL 发送POST方法的请求* @param url 发送请求的 URL* @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。* @return 所代表远程资源的响应结果*/public static String sendPost(String url, String param) {PrintWriter out = null;BufferedReader in = null;String result = "";try {URL realUrl = new URL(url);// 打开和URL之间的连接URLConnection conn = realUrl.openConnection();// 设置通用的请求属性conn.setRequestProperty("accept", "application/json");conn.setRequestProperty("Charset", "UTF-8");conn.setRequestProperty("Content-Type","application/json");conn.setRequestProperty("connection", "Keep-Alive");conn.setRequestProperty("user-agent","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");// 发送POST请求必须设置如下两行conn.setDoOutput(true);conn.setDoInput(true);// 获取URLConnection对象对应的输出流out = new PrintWriter(conn.getOutputStream());// 发送请求参数out.print(param);// flush输出流的缓冲out.flush();// 定义BufferedReader输入流来读取URL的响应in = new BufferedReader(new InputStreamReader(conn.getInputStream()));String line;while ((line = in.readLine()) != null) {result += line;}} catch (Exception e) {System.out.println("发送 POST 请求出现异常!"+e);e.printStackTrace();}//使用finally块来关闭输出流、输入流finally{try{if(out!=null){out.close();}if(in!=null){in.close();}}catch(IOException ex){ex.printStackTrace();}}return result;} /*** 获取返回参数 (返回内容格式请参考官方文档-“响应通用定义”)* @param result* @return* @author lan* @since 2020-7-17*/private static Map<String,Object> getResponseData(String result){if(result != null){JSONObject res = JSONObject.parseObject(result);if(res != null && res.get("response") != null){String resp = res.get("response").toString();JSONObject response = JSONObject.parseObject(resp);if(response != null && response.get("body") != null){Map map = JSONObject.parseObject(response.get("body").toString(), Map.class);return map;}else{return null;}}else{return null;}}else{return null;}}}
4、需要注意下的是签名体的格式问题及时间格式问题,走了些许弯路。另外,所有接口地址全部是小写地址,如果收钱吧技术人员提供的文档上写的是大写地址,请改为小写地址试一试。截止编写此篇文章之时,官方API已更新,处理了以上较为明显的问题。
仅作留存备忘,提供参考之用。
收钱吧-轻POS接口相关推荐
- 如何帮用户管好云账本?阿里云数据库助力收钱吧!
简介:"收钱吧到账100万"成为普通商家最想听到的声音. 你有多久没摸过现金了? 中国互联网络信息中心发布的第47次<中国互联网络发展状况统计报告>数据显示,截至202 ...
- 如何帮用户管好云账本?阿里云数据库助力收钱吧 | 甲子光年
简介: "收钱吧到账100万"成为普通商家最想听到的声音. 你有多久没摸过现金了? 中国互联网络信息中心发布的第47次<中国互联网络发展状况统计报告>数据显示,截至20 ...
- 你还在为“收钱”发愁吗?BeeCloud打造支付平台
移动互联网产业高速发展,据工信部相关数据统计,移动互联网用户已经超过4亿,相关产业规模更是超过9000亿元.中国,已经成为了第一大智能手机和平板市场,其中安卓与IOS系统占据了移动设备系统的主流市场. ...
- 路由器重温——POS接口配置管理——SDH
POS(Packet Over SONET/SDH)接口可利用SONET(Synchronous Optical Network,同步光纤网)或SDH(Synchronous Digital Hier ...
- 收钱吧的 Python 高效自动化测试实践
1. 背景 收钱吧业务服务千万级商家,业务庞大,产品背后有复杂的应用支撑.我们采用了微服务架构,有成百上千个不同类型的后端服务,使用了包括Node.js.Java.Go.Python等后端语言,还有M ...
- 快来被子里 看看我的夜光收钱码!
6月23日消息,根据支付宝发布的数据:截至6月22日,全国已超过600万家小店夜间收入超过去年同期,平均每天十多万人新开通收钱码做生意. 为了小店主在夜间更便捷的收钱,昨晚,支付宝紧急上线" ...
- jssdk 获取微信收货地址_微信收货地址共享开发接口讲解
写在前面的话:微信开发者文档写的比较清楚,也不容易出错,可是偏偏收货地址共享那儿写的比较绕,同时也会有很多坑,这里总结一下. ======正文开始====== 微信收货地址共享开发接口基本使用场景是: ...
- 如何打造一个让粉丝一见就能收钱的朋友圈
做微营销的人都知道打造朋友圈非常重要! 但也有人不这么认为,说现在形势变了,朋友圈都成了广告,都是垃圾,没人看朋友圈了,发朋友圈没有用了,果然是这样吗?对这个问题我通过对五行赚钱术的学习明白了,我们赚 ...
- 躺着收钱月入过万,怎样才能做到?
躺着收钱月入过万.怎样才能做到? 其实有很多方法. 比如今天举一个例子.你有资源.别人想要的商品,市场畅销的货,你能用低于大多数销售商的价格进到货,然后卖给销售商,其实基本就是躺着赚钱了.别说月入过万 ...
最新文章
- bireme数据源同步工具--debezium+kafka+bireme
- 应用开发者必须了解的Kubernetes网络二三事
- 电脑怎么打印文件步骤_电脑中毒后怎么办 电脑中毒后解决方法【详细步骤】...
- json 转换 java odl_JSON与JAVA数据的转换
- java取linux本地xml,java-使用apache poi读取.xlsx文件会在Linux机器...
- 浅谈CIVIL 3D
- java tree 表格_00030-layui+java 树形表格treeTable
- MapTask工作机制图解
- 华为悦盒EC6109u线刷救砖文件fastboot.bin bootargs.bin recovery
- VMware网络配置基础
- 命令提示符怎么以管理员方式打开
- Spark CASE WHEN 写法案例
- Modbus从站读写数据
- MFC CListCtrl修改表头字体、字体颜色、背景颜色、字体垂直居中、表头高度
- 写给那些进步缓慢却全然不知的IT人
- win7怎么修改服务器端口,教你在Win7中如何轻松修改3389远程桌面端口
- 小白学习Excel VBA (一)
- 利用组策略进行的一次Windows主机安全整改
- typedef 简介
- 网站部署详细流程(包括域名,服务器的配置等)