百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

支付宝支付Java代码

toyiye 2024-06-06 22:11 10 浏览 0 评论

最近研究了一下支付宝的支付流程,其它的倒没感觉出来,唯一的感受就是微信支付和支付宝支付这两个官方文档写的真是无法描述,不好好研究还真看不明白.所以将自己理解的支付宝支付流程描述出来.一来将自己学的东西记录下来,另一方面避免做这方面的朋友们浪费过多的时间.

支付宝调用流程

开发前的准备工作

  • 配置应用网关
  • 应用网关里面填写的值就是商户后台的异步回调地址.也就是在支付宝付完款之后,由支付宝调用商户,便于商户验证订单各信息和更新订单状态
  • 授权回调地址
  • 授权回调地址的值是指用户在使用支付宝付款成功后从支付宝跳转到商户自己的页面.
  • 接口加密方式
  • 这个用于商户的签名加密,有RSA2和RSA两种算法类型,默认是RSA2.开发人员可以使用支付宝提供的生成方式自己生成,然后将公钥上传到支付宝开放平台.这里提供支付宝生成密钥的教程和下载地址
  • 现在提供一张的截图,显示配置的位置.到达方式:蚂蚁金服开放文档—> 右上角账户中的账号管理—>开发者中心—>我的应用(应用) —> 选择自己将要配置的应用名称点击右边的查看—>应用信息(就是截图看到的页面了)

支付宝支付流程:

  • 前端调用商户后台支付接口
  • 商户后台支付接口进行一些必要的业务逻辑上的处理之后调用支付宝的支付接口(原始支付API).需要的参数详见支付宝支付接口的参数说明.支付宝会返回一个form表单.商户后台支付接口将表单返回给前台.
  • 前台将表单提交给支付宝,唤起支付宝客户端进行支付.
  • 支付成功后支付宝会根据原始支付API中传入的异步通知地址notify_url,通过POST请求的方式将支付结果作为参数通知到商户后台系统.
  • 商户后台系统在接到支付宝的异步通知后要在验证自己本身业务逻辑之外严格验证通知数据的正确性.
  • 商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号
  • 判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额)
  • 校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email)
  • 验证app_id是否为该商户本身
  • 上述1、2、3、4有任何一个验证不通过,则表明本次通知是异常通知,务必忽略.详情参见https://docs.open.alipay.com/203/105286/ 异步返回的验签
  • 判断没有任何错误,打印success.否则支付宝服务器会不断重发通知,直至超过24小时22分钟.

开发需要准备的物料

pom.xml添加支付宝依赖

[java] view plain copy

  1. <dependency>
  2. <groupId>commons-logging</groupId>
  3. <artifactId>commons-logging</artifactId>
  4. <version>1.1.1</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>com.alipay</groupId>
  8. <artifactId>alipay-sdk</artifactId>
  9. <version>java20170307171631</version>
  10. </dependency>

支付宝方面的参数

代码展示

商户后台支付接口

[java] view plain copy

  1. /**
  2. * 支付宝支付
  3. * @param req
  4. * @param response
  5. * @throws OperationFailedException
  6. */
  7. @RequestMapping("alipay/Prepay")
  8. @ResponseBody
  9. public void aliPrepay(@RequestBody AliPrepayReq req, HttpServletResponse response) throws OperationFailedException {
  10. Set<ConstraintViolation<AliPrepayReq>> constraintViolationSet = validator.validate(req);
  11. if (constraintViolationSet.size() > 0) {
  12. throw new OperationFailedException(constraintViolationSet.iterator().next().getMessage());
  13. }
  14. LibraOrder libraOrder = libraService.findLibraOrderByHashCode(req.getOutTradeNo());
  15. Product product = productRepository.findOne(Long.valueOf(libraOrder.getProduct().getId()));
  16. if(product == null) { throw new OperationFailedException("该商品不存在"); }
  17. try{
  18. String form = aliPayService.generateAliPay(req);
  19. if(!"err".equals(form)){
  20. response.setContentType("text/html;charset=utf-8");
  21. response.getWriter().write(form);// 直接将完整的表单html输出到页面
  22. response.getWriter().flush();
  23. }
  24. }catch (Exception e){
  25. throw new OperationFailedException("支付失败");
  26. }
  27. }

[java] view plain copy

  1. /**
  2. * 支付宝方面订单号获取
  3. * @param aliPrepayReq
  4. * @return
  5. * @throws OperationFailedException
  6. */
  7. public String generateAliPay(AliPrepayReq aliPrepayReq) throws OperationFailedException {
  8. AlipayClient alipayClient = new DefaultAlipayClient(aliPayUrl,
  9. appId, rsaPrivateKey, "json", "UTF-8", rsaPublicKey, "RSA2"); //获得初始化的AlipayClient
  10. Map<String, String> param = new HashMap<>();
  11. AlipayTradeWapPayRequest alipay_request = new AlipayTradeWapPayRequest();
  12. // 封装请求支付信息
  13. AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
  14. model.setOutTradeNo(aliPrepayReq.getOutTradeNo());
  15. model.setSubject(aliPrepayReq.getSubject());
  16. Integer totalAmount = aliPrepayReq.getTotalAmount();
  17. model.setTotalAmount(String.valueOf(totalAmount / 100.0));
  18. model.setBody(aliPrepayReq.getBody());
  19. model.setProductCode(aliPrepayReq.getProductCode());
  20. alipay_request.setBizModel(model);
  21. // 设置异步通知地址
  22. alipay_request.setNotifyUrl(notifyUrl);
  23. // 设置同步地址
  24. alipay_request.setReturnUrl(returnUrl);
  25. String form = "";
  26. try {
  27. LOGGER.info("alipay_request = "+jsonService.toJson(alipay_request));
  28. // 调用SDK生成表单
  29. form = alipayClient.pageExecute(alipay_request).getBody();
  30. LOGGER.info("form = "+form);
  31. } catch (Exception e) {
  32. throw new OperationFailedException("支付出错");
  33. }
  34. return form;
  35. }

异步回调接口

[java] view plain copy

  1. /**
  2. * 支付宝方面异步回调
  3. * @param request
  4. * @return
  5. * @throws OperationFailedException
  6. */
  7. @RequestMapping("alipay/notifyCallback")
  8. public String AlipayCallBack(HttpServletRequest request) throws OperationFailedException {
  9. //获取支付宝POST过来反馈信息
  10. Map<String,String> params = new HashMap<String,String>();
  11. Map requestParams = request.getParameterMap();
  12. for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
  13. String name = (String) iter.next();
  14. String[] values = (String[]) requestParams.get(name);
  15. String valueStr = "";
  16. for (int i = 0; i < values.length; i++) {
  17. valueStr = (i == values.length - 1) ? valueStr + values[i]
  18. : valueStr + values[i] + ",";
  19. }
  20. //乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
  21. //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
  22. params.put(name, valueStr);
  23. }
  24. LOGGER.info("params = "+jsonService.toJson(params));
  25. boolean verify_result = aliPayService.rsaCheck(params);
  26. if(verify_result && aliPayService.dealWithAliPayChargeOrder(params)){
  27. return "success";
  28. }
  29. return "false";
  30. }

[java] view plain copy

  1. /**
  2. * 订单验证
  3. * @param params
  4. * @return
  5. */
  6. @Transactional
  7. public boolean dealWithAliPayChargeOrder(Map<String, String> params) {
  8. String outTradeNo = params.get("out_trade_no");
  9. LibraOrder libraOrder = libraOrderRepository.findByHashCode(outTradeNo);
  10. if (libraOrder == null) {
  11. LOGGER.info("订单" + outTradeNo + "不存在");
  12. return false;
  13. }
  14. boolean locked = distributeLocker.lock(USER_ALIPAY_DEAL_LOCK_KEY);
  15. try {
  16. if (locked) {
  17. String totalAmount = params.get("total_amount");
  18. double totalPrice = Double.parseDouble(totalAmount) * 100;
  19. if(libraOrder.getTotalPrice() != Math.round(totalPrice)){
  20. LOGGER.info("alipay和订单金额不一致");
  21. return false;
  22. }
  23. if(totalPrice < 0 || libraOrder.getTotalPrice() < 0){
  24. LOGGER.info("alipay或订单金额为负");
  25. return false;
  26. }
  27. //set done
  28. libraOrder.setPayAt(new Date());
  29. libraOrder.setUpdateAt(new Date());
  30. libraOrder.setStatus(ClientOrderStatus.PAYED);
  31. //后台订单状态初始化为 等待接待
  32. libraOrder.setServiceStatus(ServiceStatus.SERVICE_WAIT);
  33. libraOrderRepository.save(libraOrder);
  34. }
  35. } finally {
  36. if (locked) {
  37. //TODO + order.getUserId()
  38. distributeLocker.unlock(USER_ALIPAY_DEAL_LOCK_KEY);
  39. }
  40. }
  41. return false;
  42. }

[java] view plain copy

  1. /**
  2. * 验证RSA签名
  3. * @param params
  4. * @return
  5. * @throws OperationFailedException
  6. */
  7. public boolean rsaCheck(Map<String, String> params) throws OperationFailedException {
  8. try {
  9. boolean verify_result = AlipaySignature.rsaCheckV1(params, rsaPublicKey, charset, signType);
  10. LOGGER.info("verify_result = "+verify_result);
  11. return verify_result;
  12. } catch (AlipayApiException e) {
  13. throw new OperationFailedException("验证签名失败");
  14. }
  15. }

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码