目录

一、支付系统介绍

二、代码解析

1、支付宝支付参数配置

2、controller类

3、service类

4、dao类

三、支付演示


一、支付系统介绍

该支付系统实现了支付宝的网站支付功能(微信支付没有沙盒测试所以无法实现),系统接到支付需求后,将支付订单存入数据库,同时向支付宝发起支付请求,支付宝返回一个网站的xml,将其解析到浏览器中,即为网站支付页面,通过手机扫码完成支付,完成支付后,支付宝发起异步通知,支付系统接收到该通知,进行校验,确保用户支付成功,同时更新数据库,如下图所示为整个项目的结构。

二、代码解析

1、支付宝支付参数配置

支付宝支付的一些参数,如应用ID、商户私钥、支付宝公钥等参数,最好能够配置到application.yml中去,这样方便之后项目的多环境开发。

建一个包含需要用到的参数的配置类,加上@Component、@ConfigurationProperties(prefix = "alipay")、@Data注解

@Component
@ConfigurationProperties(prefix = "alipay")
@Data
public class AlipayAccountConfig {private String appId;private String privateKey;private String aliPayPublicKey;private String returnUrl;private String notifyUrl;private boolean sandbox;
}

在application.yml中进行配置,returnUrl是同步通知,是支付成功后跳转的页面,notifyUrl是异步通知,是用户支付后支付宝传过来的通知,切记不要弄反了,sandbox为是否是沙盒支付。

alipay:appId: 2021000117610811privateKey: "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCVoyWjqCdRlgbGsKMDCM/NwCQF3OXEbPJAb8wT2PKTtG4hRidy6MxUb/YcCZOgqY/8vh1fJHO1pmyuyySQc4i4HxNJIYHlmw0RCFWNGmMWZDXuPnF+81WUASLyG9k5+36qU9S+oLefVOnKwlEwF9i+Y0Ko3JV1catCW3TJ2VgfPxwUI8lO6HRDKl1kQeFf+bD2VWilNRMKtMYBQd/UagY+vNR7psYgDpeewrgxvQRFFxMeB2+ypcr+3IU4X3QI7gBV4h1KyJhWn3FO2taYnxkRIQ6CPajBy7dZ4NnjJk9T4vJ2eReiLgpVBCVC/2fUghO/S1ERtGwN3ikQiCfO0Xk9AgMBAAECggEAYfZ6GMdoXlBCxWc0gTMOoFuu+auhPNQ6UJcgWsoIHUzdYKlGAEOKKalWzQoz/NWlb0ijf/skSYLX2iMiH/OTST8G6DSojsHQbxsurv7cafdXG08EDKGPoCKSV0CGGSCdzzKsr9QWApibqmNGtZ6XBiWDqXsn2ch93yZysga5W1J2UfCRRhxqtCNdsJN5zFuB+KW4h6fqMAj50l8PC89g99IRxp7UKBC5AAiE03C/y5iZS/jmlCSGahSeyw3Zkr+kYkBqIteierVQB27SXbvj22BfULbFi3Hmz359lETbNYGZJ0CgpiE0w8Uamk2BEyKUUbkvLfBUj91ti2XOGJhfHQKBgQDzb6XQ8E6UkL9ZnBTUSoW6TpYGU8ZUm2gNHP/5Umv2bxlHFE1VH7/TTmjLm6sljvpm2SW96FKaVoM7sBH2CoIv/eOvvAH/nHvzLI5kCsmz6L+b5VvRrsdGmfuAEUlQCPbkJJ7qaekx8QEnCo3GnilQBgbisElDCUfbzN6q135OPwKBgQCdXDNYAVgG2NAprTYsApKWpQdUQJ2pJuYuDRUEQiWCPRvxvDEbqRl77XyFDwpl9ji2ANYm04lxEfbwedFYix6zJkHD9yuFWe1k/GlBeZAyNnRkyyKi+l3KMAgeQwxkxALHb8O07V081vdiugP0QKpI0ganIPm7F8CLHCF7HTLRgwKBgCAdjJyh91v2NKhXxQ+0vSu1DmnLR5EF55ZDSynTS9b5FTahYQpn4+C2qXCjGtMbp8FFyIrjSXJ/E1Ueh2AURtSaBB29Ce508I1GRYrBOZb4j767ZX+mNTgFPH7KyQc8B4ZVpnl6e39RMju6UrXvS7f485OYejHT2Z0PzBhx0YH1AoGAMlky0GC1spMin4MdRx2Xm324B5wZFestUOS8qb0kVTSKQWFOcSQ81CsbYVN7pz4NzSYdXxTl7/iogy7m7aatrvJ5rmLiWOt6Coq8fsePfJFx0mIwdecXpT6TCmO3jnIs1XUMMFKWN4YsZzlPVJJwKZaRrF3fqZ4i7B+XEtY30VMCgYEA5VnrvxB9EvALgenwjxQSCWCZIw9/QgeEJdRecN7LSGS4OuxDAQqyDF8tTTlcklFTK0R84Bdd7WBQNQbCZ4AHxse5dRHoA9a5+MAuJNrP0Llln2O1It86pMyc9qJsKGo0+g1kq/nuvu72G0Bbg8JWhK0TdqFY11yPXVMhqBs3XKs="aliPayPublicKey: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArVVWL5IjmmhlEkwgDHJGCPOS7gfnfThPw/+fTX7FQoFGHQUH2ZkyGXWY3sGaRV2UzrEKbYuapfGtEKYzKuidMTgYCsyTIIpnmJEWXtFT8YjHSPCyh0Cb1SYl4kQPvZi02zKuNWLtT+ZZDTsmXcgt2IYvoFajqoFeOhrgOgAzEvi0cg/iVMPDuST78Df/mR0WfPHfUqzXfu4wO4wXMJKWRKjeF44NuC9valuxzn/G9InHCj1DEXjW4iQq2F4OZTkrXdYmxqblBD2xwJdNSLo0sb5LlvOn8jIHhowLsMXWuwn8f6z+wudebahSbyk8FrUq4G5FZ44h7idCsnBWe000gQIDAQAB"returnUrl: http://127.0.0.1notifyUrl: http://67dg79.natappfree.cc/pay/notifysandbox: true

在bestPayService方法中完成支付宝配置,并在方法上加上@Bean注解,项目启动自动运行该方法,其他类可以通过自动注入得到该bean。

@Component
public class BestPayConfig {@AutowiredAlipayAccountConfig alipayAccountConfig;@Beanpublic BestPayService bestPayService(){//支付宝配置AliPayConfig aliPayConfig = new AliPayConfig();aliPayConfig.setAppId(alipayAccountConfig.getAppId());aliPayConfig.setPrivateKey(alipayAccountConfig.getPrivateKey());aliPayConfig.setAliPayPublicKey(alipayAccountConfig.getAliPayPublicKey());aliPayConfig.setReturnUrl(alipayAccountConfig.getReturnUrl());aliPayConfig.setNotifyUrl(alipayAccountConfig.getNotifyUrl());aliPayConfig.setSandbox(alipayAccountConfig.isSandbox());//支付类, 所有方法都在这个类里BestPayServiceImpl bestPayService = new BestPayServiceImpl();bestPayService.setAliPayConfig(aliPayConfig);return bestPayService;}
}

2、controller类

创建一个PayController类,create方法为发起支付,支付宝返回一个网站的xml,存放在body中,用map将其读出并解析成一个网站,asyncNotify方法为异步通知,即扫码支付后支付宝发送给我们的通知。

@Controller
@RequestMapping("/pay")
@Slf4j
public class PayController {@AutowiredPayService payService;@GetMapping("/create")public ModelAndView create(@RequestParam("orderId") String orderId,@RequestParam("amount")BigDecimal amount){PayResponse response = payService.create(orderId, amount);Map<String, String> map = new HashMap<>();map.put("body", response.getBody());return new ModelAndView("createForAlipayPC", map);}@PostMapping("/notify")@ResponseBodypublic String asyncNotify(@RequestBody String notifyData){log.info("返回参数={}", notifyData);return payService.asyncNotify(notifyData);}
}

对传回来的xml进行解析

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>支付</title>
</head>
<body>
${body}
</body>
</html>

3、service类

在create方法中设置一些支付参数,生成支付请求,将其存入数据库中,发起支付。在asyncNotify方法中进行签名校验、金额校验,校验通过后修改数据库中订单状态为支付成功,返回“success”通知支付宝本次交易完成,否则支付宝会24小时内一直发异步通知。

@Service
@Slf4j
public class PayService implements IPayService {@AutowiredBestPayService bestPayService;@AutowiredPayInfoMapper payInfoMapper;@Overridepublic PayResponse create(String orderId, BigDecimal amount) {Date date = new Date();PayInfo payInfo = new PayInfo(Long.parseLong(orderId), OrderStatusEnum.NOTPAY.name(), amount, date, date);payInfoMapper.insertSelective(payInfo);PayRequest payRequest = new PayRequest();payRequest.setPayTypeEnum(BestPayTypeEnum.ALIPAY_PC);payRequest.setOrderId(orderId);payRequest.setOrderName("支付宝支付测试");payRequest.setOrderAmount(amount.doubleValue());PayResponse response = bestPayService.pay(payRequest);log.info("发起支付 response={}", response);return response;}@Overridepublic String asyncNotify(String notifyData) {//1、签名检验PayResponse response = bestPayService.asyncNotify(notifyData);log.info("异步通知 response={}", response);//2、金额校验PayInfo payInfo = payInfoMapper.selectByOrderNo(Long.parseLong(response.getOrderId()));if(payInfo == null){throw new RuntimeException("通过OrderNo查询到的结果为null");}if(!payInfo.getPlatformStatus().equals(OrderStatusEnum.SUCCESS.name())){if(payInfo.getPayAmount().compareTo(BigDecimal.valueOf(response.getOrderAmount())) != 0){throw new RuntimeException("异步通知中的金额与数据库不一致,orderNo=" + response.getOrderId());}//3、修改订单状态payInfo.setPlatformStatus(OrderStatusEnum.SUCCESS.name());payInfo.setPlatformNumber(response.getOutTradeNo());payInfo.setUpdateTime(new Date());payInfoMapper.updateByPrimaryKeySelective(payInfo);}return "success";}
}

4、dao类

通过生成器生成

@Mapper
public interface PayInfoMapper {int deleteByPrimaryKey(Integer id);int insert(PayInfo record);int insertSelective(PayInfo record);PayInfo selectByPrimaryKey(Integer id);int updateByPrimaryKeySelective(PayInfo record);int updateByPrimaryKey(PayInfo record);PayInfo selectByOrderNo(Long orderNo);
}

三、支付演示

1、启动项目

2、启动natapp进行内网穿透,得到临时公网域名(因为我是免费账号每次启动时的域名都不同,记得修改yml配置)

为什么要内网穿透:支付宝异步通知时要访问到我们内网,外网无法直接访问到内网,需要进行内网穿透

内网穿透如何配置参考:https://blog.csdn.net/qq464383828/article/details/113837504

3、打开网页发送支付请求,格式如下,建议换个不常用的浏览器,我用chrome,支付宝将我的请求检测为有钓鱼风险(可能是我之前测试的时候短时间多次访问失败导致的)

http://67dg79.natappfree.cc/pay/create?orderId=239123&amount=0.01

成功后得到如下页面

4、用开发平台上的用户账号在手机上登录沙箱版钱包,进行扫码支付,支付成功页面如下

支付+电商双系统项目笔记(七)支付系统:支付宝支付开发相关推荐

  1. 小型电商平台的项目估算

    小型电商平台的项目估算 四.项目估算 4.1 简介 4.2 规模估算 4.2.1 代码行估算方法 4.2.2 功能点分析方法 4.3 工作量估算 4.3.1 COCOMO方法 4.3.2 基于用例的工 ...

  2. 电商双11已臻巅峰,众筹的双11才刚刚开始

    电商双11已臻巅峰,众筹的双11才刚刚开始 双11战火蔓延至众筹领域,说明经过几年的酝酿和发展,众筹已经开始进入电商和消费者的视野,行业规模处于急剧扩大之中. 零壹研究院/李耀东 杨才勇 今年的&qu ...

  3. 抢跑直播电商双11,快手电商帝国雏形初显

    文 | 陈小江 来源 | 螳螂财经(ID:TanglangFin) 在双十一如火如荼的时候,快手吹响了IPO的号角. 11月5日晚,快手正式向港交所递交了IPO招股书.招股书显示,2020年上半年快手 ...

  4. 02-Flutter移动电商实战-建立项目和编写入口文件

    02-Flutter移动电商实战-建立项目和编写入口文件 环境搭建请参考之前写的一篇文章:Flutter_初体验_创建第一个应用 1.创建项目 采用AndroidStudio构建本项目,FIle> ...

  5. Vue全家桶 - 电商后台管理系统项目开发实录(详)

    目录 1. 项目概述 1.1 电商项目基本业务概述 1.2 电商后台管理系统的功能 1.3 电商后台管理系统的开发模式(前.后端分离) 2. 项目初始化 2.1 前端项目初始化步骤 码云相关操作 2. ...

  6. 抖音电商“双11”:品质国货和地方农特产成亮点

    10月27日消息,抖音电商"双11"今日正式开启,在线上特设"抖音双11好物节"专区,通过短视频和直播推介国货.地方农特产等优价好物. 据悉,该活动为期16天, ...

  7. 电商“双11”or直播“双11”?

    2020双十一,电商玩法变了.双十一,直播电商已成主流. 日渐普及的直播电商,正在重构零售. 01 双十一,直播电商成主流 2020年,直播电商无疑是消费领域最火爆的话题.疫情之下,各行业争相入局,企 ...

  8. spark企业级电商分析平台项目实践(一)项目介绍和需求分析

    前言 这个专栏的系列文章,是一个电商分析平台项目实践过程中的记录和总结. 基于 spark2.4.x 和 scala2.11.x 一. 项目概述 访问电商网站时,我们的一些访问行为会产生相应的埋点日志 ...

  9. 电商运营裂变新玩法—分销渠道系统模式

    电商运营裂变新玩法-分销渠道系统模式 简单地说,分销,在我看来,就是"分散化+销售",通过分散化终端尽可能地占领市场,销售产品,从而实现利润.确实,需要更多的人,更多的终端,分销的 ...

最新文章

  1. C++调用Python Py_Initialize失败
  2. linux运维学了又忘记,Linux运维工程师经常忘记的10个实用Linux命令
  3. 利用cors,实现js跨域访问Tomcat下资源
  4. latex 小于_数学公式怎么快速输入?Latex语法了解一下
  5. 草稿 0242 ktv第一个页面
  6. mysql5.5从零开始_【MySQL函数】MySQL 5.5从零开始学第六章
  7. java池_java中的各种池
  8. spring boot初体验(三)Spring AOP
  9. Ubuntu vi命令
  10. 如何在Mac设置开机自启程序项,教程在这!
  11. 读《我喜欢生命本来的样子》记(三)
  12. jquery-question
  13. linux连接mssql数据库,在Centos7下为PHP安装mssql扩展
  14. mysql 1265错误_Mysql出现ERROR 1265: Data truncated for
  15. 2022-2028年中国宠物罐头行业市场全景调查及投资策略研究报告
  16. 左程云算法笔记总结-基础提升篇
  17. 苹果手机数据线充不了电_深圳苹果手机数据线多少钱一条
  18. 许佳佳的2020,疫情下格外有意义的一年
  19. 你真的了解Filter过滤器 ?
  20. 【DCIC2022】科技金融子赛道验证码识别0.65+ baseline

热门文章

  1. 为什么PBFT中需要2f+1
  2. java中如何改变包结构_修改jar包package目录结构操作方法
  3. 将微信、58、高德和大众点评一站拿下,“大热度”用统一后台让商家实现多渠道信息同步...
  4. matlab循环读取有序文件名数据
  5. 按头安利 好看又实用的日式虚幻UE4素材看这里
  6. echart柱状图、折线图自动滚动
  7. 【每日一练】倒计时小案例
  8. 5年海外工作经验,硕士归国没有适合我的位置???
  9. 如何白嫖world.js、china.js以及各个省的js和json文件
  10. 记事本写的html文件保存到c:\inetpub\wwwroot失败