支付宝支付场景是在pc网站中下单后,点击支付调起支付宝支付接口,然后再网站中显示支付二维码,用户扫码后支付。
支付流程:
在支付宝开放平台助手中获取应用私钥和应用公钥。支付宝采用的是非对称加密算法RSA。获取公钥后,将应用公钥和支付宝公钥互换。
商家使用支付宝公钥对订单信息加密,同时使应用私钥签名。支付宝收到订单信息后使用支付宝私钥解密,同时使用应用公钥对签名验签。
支付宝接收到请求后,进行验签。调起支付接口,用户扫码下单。
支付宝返回响应,异步回调,页面跳转return_url,跳转到前端页面,notify_url支付宝主动回调服务器后端方法。
项目中并没有使用支付宝SDK签名, 而是实现的自行签名。自行签名的步骤如下:
筛选并排序
获取所有请求参数,不包括字节类型参数,如文件、字节流,剔除 sign 字段,剔除值为空的参数,并按照第一个字符的键值 ASCII 码递增排序(字母升序排序),如果遇到相同字符则按照第二个字符的键值 ASCII 码递增排序,以此类推。
拼接
将排序后的参数与其对应值,组合成“参数=参数值”的格式,并且把这些参数用 & 字符连接起来,此时生成的字符串为待签名字符串
调用签名函数
使用各自语言对应的 SHA256WithRSA(对应sign_type为RSA2)或SHA1WithRSA(对应sign_type为RSA)签名函数利用商户私钥对待签名字符串进行签名,并进行 Base64 编码。
把生成的签名赋值给 sign 参数,拼接到请求参数中。
即:将所有需要发送的参数,sign除外,作为签名的内容。生成sign后,再将sign拼接到请求参数中。参数分为公共参数和请求参数,其中公共参数中的biz_content参数存放的是所有请求参数。biz_content是一个json字符串。
支付宝文档:
https://opendocs.alipay.com/apis/api_1/alipay.trade.page.pay
支付
@RequestMapping(value = "/toform",method = RequestMethod.POST)@ResponseBodypublic Result toform(InfoBean map) throws Exception {//应用公钥String appPublicKey = "马赛克";//应用私钥String privateKey = "马赛克";//支付宝公钥String aliPayPublicKey = "马赛克";// 公共参数Map<String, String> treeMap = new TreeMap<>();treeMap.put("app_id","2021000116692708");treeMap.put("method","alipay.trade.page.pay");treeMap.put("charset","utf-8");treeMap.put("sign_type","RSA2");Date date = new Date();SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String format = sdf.format(date);treeMap.put("timestamp",format);treeMap.put("version","1.0");treeMap.put("notify_url","http://da61669ae53d.ngrok.io/aliReturnPay");//支付宝回调接口treeMap.put("return_url","http://127.0.0.1:8080/paysuccess.jsp");String biz_content="{\"out_trade_no\":\""+ map.getOut_trade_no() +"\","+ "\"total_amount\":\""+ map.total_amount +"\","+ "\"subject\":\""+ map.getSubject() +"\","+ "\"body\":\""+ "body" +"\","+ "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}";treeMap.put("biz_content",biz_content);// 将排序后的参数与其对应值,组合成“参数=参数值”的格式,并且把这些参数用 & 字符连接起来,此时生成的字符串为待签名字符串。String mapToString = SignUtil.map_to_string(treeMap);System.out.println(mapToString);// String encrypt = SignUtil.encrypt(mapToString, aliPayPublicKey);//使用支付宝公钥对数据进行加密// 使用私钥对数据进行签名String signqm = SignUtil.signqm(mapToString, privateKey);treeMap.put("sign",signqm);String from = ToForm.from("https://openapi.alipaydev.com/gateway.do", treeMap);System.out.println(from);Map<String,String> maps=new ConcurrentHashMap<>();Result result=new Result();result.setCode("200");result.setMsg("success");result.setData(from);System.out.println(result.toString());return result;}
验签方法:
@RequestMapping(value = "/toform",method = RequestMethod.POST)@ResponseBodypublic Result toform(InfoBean map) throws Exception {//应用公钥String appPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn0L4oDCBqCaUQzuKFD/lcF3vZU5q3Mg6tb2er6ttHfxiICnCMRtv5AxmZ0z3kj5x5XDrucO6ldVM9GuCEqC2SnZBSoknDD+Vn/AASOhG5BJ+MG2h2YeLXrbfwghYUINqEMqeA57HpDPy9IS6kAuDbUi0ga2LCxUahHl8ncvd4vaTFRAkZvpvldHWThP1+KTQoCzn75H0giInDYuXQjsi4Lh/B3vwEfQViLzCbfqfV2phruUv1lS6d0pwF1t8QtbLXyGxova520iNCtIkna6l6WrkPkX59j16/RIFuzWEd3WVbDHZj0eDXfUJmLU3tsQjCKWFTeoRYLpOb2ayG0EVFwIDAQAB";//应用私钥String privateKey = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCfQvigMIGoJpRDO4oUP+VwXe9lTmrcyDq1vZ6vq20d/GIgKcIxG2/kDGZnTPeSPnHlcOu5w7qV1Uz0a4ISoLZKdkFKiScMP5Wf8ABI6EbkEn4wbaHZh4tett/CCFhQg2oQyp4DnsekM/L0hLqQC4NtSLSBrYsLFRqEeXydy93i9pMVECRm+m+V0dZOE/X4pNCgLOfvkfSCIicNi5dCOyLguH8He/AR9BWIvMJt+p9XamGu5S/WVLp3SnAXW3xC1stfIbGi9rnbSI0K0iSdrqXpauQ+Rfn2PXr9EgW7NYR3dZVsMdmPR4Nd9QmYtTe2xCMIpYVN6hFguk5vZrIbQRUXAgMBAAECggEARAfcorj1ubl5HdsiGZJN1RkbOSAtP9B8W8P7NDk7LFLyK6EK5eU9f6HYYIodOyhXiNYaq8izPGvYKpR+BK0IEXjAXTGHL5E9vgtMY9hs5+IKa295cq2W2Eev/3eHGiV4umGC7DL4Puk+ADtuYje41Yb4LGjQe1RxdmNa2yEJ0HgqRqlbENf+K66s02GX07IBiXjo3E94QsofIPGfJ9JburvEsbqiCcUyCu4hyeCDqCseTunmJdgqI7ZDBZWmtaAr/7/Rk9jygabhPyqsGzG9S9301PfmRxNA9JxU8KuBd15rFKyW7l/4NzzM1RHAZ7J0ZkmopH7Vnr8CUvLONRbWmQKBgQDzauqLZ1+XTp/0Fl05ExtwP3L3iudSJst5kBBZ+UqJb0ZUO7BsUzc0fZqPXeMzUXCqJ5tUSydI7p/52ZJ812UFNYvchW9XS3TAIv2ZeaNqSeBz3F9yHh6uNRWcof3s9oNPHO3EFQlqOHrHukFgwYyosZERqvzN/DT7HdNIXuEzmwKBgQCnfnCHtFOuqhy6UdhOLoCFwZJQG0nC6v66C4G7J58r+5ZUaHlDFv+P+ffA2RyvLvHgL0CqtI2wfFOHE+gIDLC4Ek4ZoQDnJG5Q14RoaUc5tNqxnFrDld0WW+eVYEi326kpC+IaswfgCYN5bETg3cyIPfyj3PG5hmePO9aT8EmSNQKBgF5b+tHRX8fqrazUIo0mcAOCRRHaobNB4KyeAQivz4oZPZ0XiltjosnRSuH6lkFld5QuSFNT0sW94vvasKN+Z+WuDSqN+0xOrtJwffhJo+RnAQBI1CMLs/76Cwet8B40rVA0uaLCOOUZQdc8x203ekxGkSLVMqyy8OLLfATY6tmzAoGBAIelqtT8gdkvA90Rc7C9kHDC+A/QSciGMI3Ty9kamZoxQupRQgPHmGmt86xHKSfnSRRasHCPkUChL7RxtrTuMiChEodHEUghBQaLxDwbJwfhJEw7aHaF5Gu7Oq6LL9lXGISZjyA4ZeRXUBcCTDYg6whby0OaKFosM6qYt4tQSwURAoGAYtYw+6EzDDIWH3X9IdGp60XmIUdI562TS/8V19TKTGvUQ3LzPLpBn3ZElGYPabKTKH4SxQEAqnuk8RY7sQFYkS7Y4uxFynw7aEvVQpLgNGZx96ZjKjoAjGy6hsbnASe2MzE0Weh9CWqaMhV0nmCRzjXZSUBZd3iXKp6WzTEWudM=";//支付宝公钥String aliPayPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgizoJrPZVvPvE6nQ4pBxgmyj0uqyx+c5SsvLjiG9A0ZfD6Nt0aLvj5/MnYtCgHIzeh22sXIEEOsQobARfd9zByE7vTEwBWpUIt4BOCGeUWGepZJ76ErtHYSr3ntAHftA6JA11wBNdP9MZUCh4h5tf1NEXYfGIt+mIMVoUdLnxCZh7U29N+aJRfToTdK3vHJMixewULv/+mc2ImmFYL+HmQqQxbR82Z9Jeu96Hf6FYx4zf6AVBRHpA2hH1yefnZEBgvq6bb9K4M27jEwakJlQ8Dfz+9LPTc6mcWCQv3tApSj/AY/uBXgMO2+ttM5xmQoRtOT1aLscGlWFpDnAZSc/wwIDAQAB";// 公共参数Map<String, String> treeMap = new TreeMap<>();treeMap.put("app_id","2021000116692708");treeMap.put("method","alipay.trade.page.pay");treeMap.put("charset","utf-8");treeMap.put("sign_type","RSA2");Date date = new Date();SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String format = sdf.format(date);treeMap.put("timestamp",format);treeMap.put("version","1.0");treeMap.put("notify_url","http://da61669ae53d.ngrok.io/aliReturnPay");//支付宝回调接口treeMap.put("return_url","http://127.0.0.1:8080/paysuccess.jsp");String biz_content="{\"out_trade_no\":\""+ map.getOut_trade_no() +"\","+ "\"total_amount\":\""+ map.total_amount +"\","+ "\"subject\":\""+ map.getSubject() +"\","+ "\"body\":\""+ "body" +"\","+ "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}";treeMap.put("biz_content",biz_content);// 将排序后的参数与其对应值,组合成“参数=参数值”的格式,并且把这些参数用 & 字符连接起来,此时生成的字符串为待签名字符串。String mapToString = SignUtil.map_to_string(treeMap);System.out.println(mapToString);// String encrypt = SignUtil.encrypt(mapToString, aliPayPublicKey);//使用支付宝公钥对数据进行加密// 使用私钥对数据进行签名String signqm = SignUtil.signqm(mapToString, privateKey);treeMap.put("sign",signqm);String from = ToForm.from("https://openapi.alipaydev.com/gateway.do", treeMap);System.out.println(from);Map<String,String> maps=new ConcurrentHashMap<>();Result result=new Result();result.setCode("200");result.setMsg("success");result.setData(from);System.out.println(result.toString());return result;}




