100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > 支付+电商双系统项目笔记(七)支付系统:支付宝支付开发

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

时间:2018-08-12 03:48:45

相关推荐

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

目录

一、支付系统介绍

二、代码解析

1、支付宝支付参数配置

2、controller类

3、service类

4、dao类

三、支付演示

一、支付系统介绍

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

二、代码解析

1、支付宝支付参数配置

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

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

@Component@ConfigurationProperties(prefix = "alipay")@Datapublic 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: 000117610811privateKey: "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: /pay/notifysandbox: true

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

@Componentpublic 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")@Slf4jpublic 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@Slf4jpublic 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类

通过生成器生成

@Mapperpublic 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配置)

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

内网穿透如何配置参考:/qq464383828/article/details/113837504

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

/pay/create?orderId=239123&amount=0.01

成功后得到如下页面

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

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。