首页 > 分享 > [亲妈版]SpringBoot集成网页支付宝支付对接流程

[亲妈版]SpringBoot集成网页支付宝支付对接流程

场景:
针对PC网站支付场景

一、支付宝开放平台设置

1、登录支付宝开放平台

2、进入控制台,在【我的应用】选择【网页&移动应用】,然后点击【创建应用】

image.png

3、填写好响应的应用信息,点击【确认创建】

image.png

4、创建好之后,在控制台进入应用,添加"电脑网站支付能力"

说明:添加这个能力,会需要进行填写签约信息,按着步骤走就行,不过填写的网站必须和企业支付宝的营业执照一致
image.png

5、点击左侧【应用信息】,进行设置开发信息,只设置了接口加签

image.png

5.1、设置接口加签方式,有公钥证书和公钥两个选择,一般选择公钥5.2、然后需要生成密钥,才能生成支付宝公钥,生成密钥也有三种方式:

第一种:下载密钥生成工具
1、下载密钥生成工具:https://opendocs.alipay.com/o...
windows版本电脑下载windows版本工具。
mac版本电脑下载mac_osx版本工具。
image.png

2、运行安装密钥生成工具
点击下载的“AlipayDevelopmentAssistant-1.0.1.exe”(即支付宝开放平台开放助手)进行安装并运行。
说明:本工具只会记录上传点击事件操作行为,不会记录上传用户的任何用户信息以及公私钥等敏感信息。
image.png

3、生成密钥
选择密钥格式和密钥长度,点击“生成密钥”进行密钥生成 。
(1)密钥长度
RSA2:密钥长度为2048位。
注:开放平台从2018年1月5日开始创建的应用都没有RSA密钥的设置入口,只能上传RSA2格式密钥

RSA:密钥长度为1024位。
国密:目前暂不支持国密的加签方式,即使获取后也无法设置加签。

(2)密钥格式
PKCS8:JAVA开发语言适用。
PKCS1:非JAVA开发语言适用。
image.png
4、配置密钥
开放平台(open.alipay.com)选择要上传的应用,点击应用进入详细页,选择应用信息内的“接口加签方式”进行设置。

如应用未上线,需要选择概览里面的接口加签方式进行设置。
(1)应用私钥:开放平台没有上传设置的位置,需要自己进行保存并设置到代码中,且由于其涉及资金安全不能将其提供给他人,若不小心丢失或泄露,请及时进行更新修改。
(2)应用公钥:需要将其传入开放平台应用中(每次更换密钥时都要将其重新上传开放平台),如图:
image.png
5、接口中以及支付宝开放平台配置密钥
生成密钥后切记成对妥善保管,避免测试时由于公私钥不匹配导致签名验签等一系列不必要的错误产生。

(1)正式环境中配置密钥
开发技术人员在接口中配置正式环境配置密钥,需选择要上传的应用,点击应用进入详细页,选择应用信息内的“接口加签方式”进行设置。
image.png

(2)沙箱环境中配置密钥
沙箱环境配置密钥,需选择在沙箱应用中,选择应用信息内的“RSA2(SHA256)密钥(推荐)”进行设置。

沙箱环境应用配置点击沙箱应用了解。
image.png

第二种:web在线生成密钥
1、生成密钥
1.1、打开Web 在线加密(无下载,新上线)->选择“生成密钥”->选择“保存密钥”。
1.2、选择密钥格式和密钥长度,点击“生成密钥”进行密钥生成 。
(1)密钥长度
RSA2:密钥长度为2048位。
注:开放平台从2018年1月5日开始创建的应用都没有RSA密钥的设置入口,只能上传RSA2格式密钥
RSA:密钥长度为1024位。
(2)密钥格式
PKCS8:JAVA开发语言适用。
PKCS1:非JAVA开发语言适用。
2、配置密钥
配置密钥流程与“密钥生成工具生成密钥”的配置密钥流程相同。
将应用公钥上传到开放平台应用的接口加签中,应用私钥请放在接口代码私钥位置。
image.png

第三种:使用OpenSSL生成
除了使用支付宝提供的一键生成工具外,也可以使用OpenSSL工具命令生成密钥。

使用OpenSSL工具命令生成,命令语句如下:
1、生成RSA2私钥(2048位)命令: genrsa -out app_private_key.pem 2048 ;

2、把私钥转换成PKCS8格式并输出新文件命令: pkcs8 -topk8 -inform PEM -in app_private_key.pem -outform PEM -nocrypt -out app_private_key_pkcs8.pem;

3、生成公钥命令: rsa -in app_private_key.pem -pubout -out app_public_key.pem;
之后把生成的公钥上传给支付宝,并获取支付宝公钥(ALIPAY_PUBLIC_KEY)。

详细见使用OpenSSL工具生成密钥在线文档。

注:生成密钥后切记成对妥善保管,若不小心丢失或泄露,请及时进行生成生成并重新上传到支付宝开放平台,避免出现损失。

6、配置好开发信息,然后再编辑应用信息,发布上线,即可开始开发正式环境

image.png

二、Springboot代码编写

1、首先添加maven依赖

<dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alipay-sdk-java</artifactId> <version>4.10.209.ALL</version> </dependency>

2、创建支付宝支付工具类

public class ALiPayUtils { private static final String RETURN_URL = PropertiesValues.getPropertiesValue("pay.service.return_url", "application.properties"); private static final String NOTIFY_URL = PropertiesValues.getPropertiesValue("pay.service.notify_url", "application.properties"); private static final String GATEWAY_URL = "https://openapi.alipay.com/gateway.do"; public static final String APP_ID = "换成自己正式APPID"; private static final String PRIVATE_KEY = "生成的应用私钥"; private static final String PUBLIC_KEY = "生成的支付宝公钥"; private static final String FORMAT = "json"; private static final String CHART_TYPE = "utf-8"; private static final String SIGN_TYPE = "RSA2"; public static final String PRODUCT_CODE = "FAST_INSTANT_TRADE_PAY"; private static AlipayClient alipayClient = null; public static final String PID = "换成自己商户PID"; public ALiPayUtils(){ if(alipayClient == null){ alipayClient = new DefaultAlipayClient( GATEWAY_URL, APP_ID, PRIVATE_KEY, FORMAT, CHART_TYPE, PUBLIC_KEY, SIGN_TYPE); } }; public Map<String, Object> placeOrderAndPayForPCWeb(String outTradeNo, float totalAmount, String subject){ AlipayTradePagePayRequest request = new AlipayTradePagePayRequest(); request.setNotifyUrl(RETURN_URL); request.setReturnUrl(NOTIFY_URL); JSONObject bizContent = new JSONObject(); bizContent.put("out_trade_no", outTradeNo); bizContent.put("total_amount", totalAmount); bizContent.put("subject", subject); bizContent.put("product_code", PRODUCT_CODE); request.setBizContent(bizContent.toString()); AlipayTradePagePayResponse response = null; try { response = alipayClient.pageExecute(request); } catch (AlipayApiException e) { e.printStackTrace(); } Map<String, Object> resultMap = new HashMap<>(); resultMap.put("isSuccess", response.isSuccess()); if(response.isSuccess()){ System.out.println("调用成功"); System.out.println(JSON.toJSONString(response)); resultMap.put("body", response.getBody()); } else { System.out.println("调用失败"); System.out.println(response.getSubMsg()); resultMap.put("subMsg", response.getSubMsg()); } return resultMap; } public Map<String, Object> tradeQueryForPCWeb(String out_trade_no){ AlipayTradeQueryRequest request = new AlipayTradeQueryRequest(); JSONObject bizContent = new JSONObject(); bizContent.put("trade_no", out_trade_no); request.setBizContent(bizContent.toString()); AlipayTradeQueryResponse response = null; try { response = alipayClient.execute(request); } catch (AlipayApiException e) { e.printStackTrace(); } Map<String, Object> resultMap = new HashMap<>(); resultMap.put("isSuccess", response.isSuccess()); if(response.isSuccess()){ System.out.println("调用成功"); System.out.println(JSON.toJSONString(response)); resultMap.put("status", response.getTradeStatus()); } else { System.out.println("调用失败"); System.out.println(response.getSubMsg()); resultMap.put("subMsg", response.getSubMsg()); } return resultMap; } public static boolean CheckSignIn(String sign, String content){ try { return AlipaySignature.rsaCheck(content, sign, PUBLIC_KEY, CHART_TYPE, SIGN_TYPE); } catch (AlipayApiException e) { e.printStackTrace(); } return false; } public static Map<String, String> paramstoMap(HttpServletRequest request) throws UnsupportedEncodingException { Map<String, String> params = new HashMap<String, String>(); Map<String, String[]> requestParams = request.getParameterMap(); for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) { String name = (String) iter.next(); String[] values = (String[]) requestParams.get(name); String valueStr = ""; for (int i = 0; i < values.length; i++) { valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ","; } params.put(name, valueStr); } return params; } }

3、编写下单接口以及回调处理接口

@RestController @CrossOrigin @RequestMapping("lcAliPay") public class LcALiPayController { @Autowired LcAliPayService lcAliPayService; @Autowired LcGoodsOrderService lcGoodsOrderService; @PostMapping("/tradeOrderForPCWeb") @NoVerify public ResultMap tradeOrderForPCWeb(@RequestBody LcGoodsOrder lcGoodsOrder){ return lcAliPayService.tradeOrderForPCWeb(lcGoodsOrder); } @RequestMapping("/notifyForPCWeb") @NoVerify public String notifyForPCWeb(HttpServletRequest request){ try { Map<String, String> map = ALiPayUtils.paramstoMap(request); String tradeNo = map.get("trade_no"); String sign = map.get("sign"); String content = AlipaySignature.getSignCheckContentV1(map); boolean signVerified = ALiPayUtils.CheckSignIn(sign, content); if(!lcAliPayService.checkData(map)){ System.out.println("返回业务数据验证失败,订单:" + tradeNo ); return "fail"; } if(signVerified){ System.out.println("支付宝签名验证成功,订单:" + tradeNo); String tradeStatus = request.getParameter("trade_status"); if(tradeStatus.equals("TRADE_SUCCESS")){ System.out.println("支付成功,订单:"+tradeNo); LcGoodsOrder lcGoodsOrder = new LcGoodsOrder(); lcGoodsOrder.setTradeNo(map.get("trade_no")); lcGoodsOrder.setSellerId(map.get("seller_id")); lcGoodsOrder.setOrderStatus("2"); lcGoodsOrderService.updateById(lcGoodsOrder); return "success"; }else{ System.out.println("支付失败,订单:" + tradeNo ); return "fail"; } }else{ System.out.println("签名验证失败,订单:" + tradeNo ); } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return "fail"; } }

4、service层代码

@Service public class LcAliPayServiceImpl implements LcAliPayService { @Resource LcGoodsOrderMapper lcGoodsOrderMapper; private static Logger logger = LoggerFactory.getLogger(LcAliPayServiceImpl.class); @Override public ResultMap tradeOrderForPCWeb(LcGoodsOrder lcGoodsOrder) { logger.info("【请求开始-在线购买-交易创建】*********统一下单开始*********"); ALiPayUtils aLiPayUtils = new ALiPayUtils(); String tradeNo = ALiPayUtils.generateOrderNum(); Map<String, Object> map = aLiPayUtils.placeOrderAndPayForPCWeb(tradeNo, Float.parseFloat(lcGoodsOrder.getTotalAmount()), lcGoodsOrder.getSubject()); ResultMap resultMap = new ResultMap(); if(Boolean.parseBoolean(String.valueOf(map.get("isSuccess")))){ logger.info("【请求开始-在线购买-交易创建】统一下单成功,开始保存订单数据"); resultMap.setCode("200"); resultMap.setData(map.get("body")); String lcGoodsOrderId = UUID.getRandom(); lcGoodsOrder.setOrderId(lcGoodsOrderId); lcGoodsOrder.setOrderCreateTime(DateTime.getNowDateStamp()); lcGoodsOrder.setOutTradeNo(tradeNo); lcGoodsOrder.setOrderStatus("1"); lcGoodsOrder.setProductCode(ALiPayUtils.PRODUCT_CODE); int count = lcGoodsOrderMapper.insert(lcGoodsOrder); if(count > 0){ logger.info("【成功-在线购买-交易创建】保存订单数据成功,添加条数:{}", count); resultMap.setCode(ResponseCodeUtis.SERVER_TRUE_200); resultMap.setMsg(ResponseCodeUtis.MSG_TRUE_InsertById); resultMap.setData(map.get("body")); }else{ logger.error("【失败-在线购买-交易创建】保存订单数据失败"); resultMap.setCode(ResponseCodeUtis.SERVER_ERROR_500); resultMap.setMsg("添加数据失败"); } logger.info("【请求成功-在线购买-交易创建】*********统一下单结束*********"); return resultMap; }else{ resultMap.setCode("501"); resultMap.setMsg(String.valueOf(map.get("subMsg"))); logger.info("【失败:请求失败-在线购买-交易创建】*********统一下单结束*********"); } return resultMap; } @Override public boolean checkData(Map<String, String> map) { logger.info("【请求开始-交易回调-订单确认】*********校验订单确认开始*********"); LcGoodsOrder lcGoodsOrder2 = lcGoodsOrderMapper.selectByOutTradeNo(map.get("out_trade_no")); if(lcGoodsOrder2 != null && lcGoodsOrder2.getOrderStatus().equals("1")){ float amount1 = Float.parseFloat(map.get("total_amount")); float amount2 = Float.parseFloat(lcGoodsOrder2.getTotalAmount()); if(amount1 == amount2){ if(map.get("seller_id").equals(ALiPayUtils.PID)){ if(map.get("app_id").equals(ALiPayUtils.APP_ID)){ logger.info("【成功:请求开始-交易回调-订单确认】*********校验订单确认成功*********"); return true; } } } } logger.info("【失败:请求开始-交易回调-订单确认】*********校验订单确认失败*********"); return false; } }

5、网站页面支付下单请求代码

function aliPay(data){ var url = "服务器接口"; $.ajax({ url: url, type: 'post', data: JSON.stringify({ payUserName: data.payUserName, payUserPhone: data.payUserPhone, payMessage: data.payMessage, goodsId: data.goodsId, totalAmount: data.totalAmount, subject: data.subject, }), contentType: "application/json", dataType: 'json', success: function(res){ if(res.code == "200"){ const div=document.createElement('divform'); div.innerHTML=res.data; document.body.appendChild(div); document.forms[0].setAttribute('target', '_blank') document.forms[0].submit(); }else{ alert("网络异常"); alert(res.msg); } }, fail: function(res){ console.log("失败") console.log(res); } }) }

6、下单接口回调,处理返回表单处理问题

if(res.code == "200"){ const div=document.createElement('divform'); div.innerHTML=res.data; document.body.appendChild(div); document.forms[0].setAttribute('target', '_blank') document.forms[0].submit(); }else{ alert("网络异常"); alert(res.msg); }

7、请求成功图

image.png

8、支付完成回调

这里跳转回去的页面就是之前AlipayUtils类中的return_url 在这之前需要进入notify_url 接口进行验签.
image.png

相关知识

对接支付宝、微信、第三方支付,超详细讲解+demo演示
web支付基础教程
支付宝花呗/花呗分期支付说明
app调起支付宝-后端预支付
详解网联付款,揭开在线支付背后的安全机制与操作流程
支付宝口碑门店收款二维码下载使用流程及“蚂蚁花呗”信用支付说明
网上花店网页模板
网站开发网页
一文看“透”你所不知道在线支付
医院移动支付结算 你需要了解的几件事

网址: [亲妈版]SpringBoot集成网页支付宝支付对接流程 https://m.huajiangbk.com/newsview948998.html

所属分类:花卉
上一篇: 牵牛花的花色有哪些
下一篇: Spring Boot集成微信支