zoukankan      html  css  js  c++  java
  • SpringBoot接入支付沙箱返回支付二维码

    支付宝开放平台

    扫码登录支付宝开放平台

    沙箱环境

    沙箱环境介绍
    沙箱控制台
    应用网关:该地址用于接收开放平台的异步通知。目前沙箱环境不需要配置此参数;

    在这里插入图片描述

    授权回调地址;第三方应用授权或获取用户信息中用于接收授权回调信息的地址。使用相关产品时需进行配置:

    第三方应用授权:授权 url 中的 redirect_uri 必须与此值相同。

    获取用户信息:授权 url 中的 redirect_uri 的域名必须与此值相同(例如:授权回调地址配置:https://auth.example.com/authCallBack 高亮部分需和授权url相同)。

    RSA(SHA1)密钥:配置 RSA2(SHA256) 的应用公钥后,不需要配置 RSA(SHA1) 密钥。

    AES 密钥:目前不再使用。
    扫码测试的时候需要沙箱版支付宝App,目前只有安卓版
    下载

    配置

    首先导入支付宝的依赖

    <!--ali pay-->
            <dependency>
                <groupId>com.alipay.sdk</groupId>
                <artifactId>alipay-sdk-java</artifactId>
                <version>3.1.0</version>
            </dependency>
    

    配置文件

    alipay:
      app-id: # AppID
      private-key: # 应用私匙 需要用支付宝助手生成
      public-key: # 支付宝公匙
      gateway: https://openapi.alipaydev.com/gateway.do
    

    支付宝公匙点击RSA2(SHA256)密钥设置,然后查看
    在这里插入图片描述
    应用私匙:
    会生成txt文件,然后复制到配置文件中
    在这里插入图片描述
    APPID和网关就不说了,需要注意的是正式接入支付宝的网关和沙箱环境的应用网关,区分是alipay.com/alipaydev.com

    代码实现

    构建支付信息视图对象PayInfoVO.java

    @Data
    @AllArgsConstructor
    @ToString
    @EqualsAndHashCode
    @NoArgsConstructor
    @ApiModel("支付信息")
    public class PayInfoVO implements Serializable {
        @ApiModelProperty("二维码URL")
        private String url;
        @ApiModelProperty("订单编号")
        private String orderId;
        @ApiModelProperty("商家名称")
        private String shopName;
    
    }
    

    PayServiceImpl

    @Service("PayServiceImpl")
    @Slf4j
    public class PayServiceImpl implements PayService {
    
        @Autowired
        private OrderMapper orderMapper;
        @Autowired
        private ShopMapper shopMapper;
    
        @Value("${alipay.app-id}")
        private String appId;
    
        @Value("${alipay.private-key}")
        private String privateKey;
    
        @Value("${alipay.public-key}")
        private String publicKey;
    
        @Value("${alipay.gateway}")
        private String gateway;
    
        private AlipayClient alipayClient;
    
        @PostConstruct
        public void init() {
            alipayClient = new DefaultAlipayClient(gateway,
                    appId, privateKey, "json", "utf-8", publicKey, "RSA2");
        }
    
        @Override
        public PayInfoVO getPayInfo(String orderId) {
            log.info("info ============= {}",orderId);
            // 根据订单id得到订单详情
            Order order = orderMapper.selectById(orderId);
            String sellId = order.getSellId();
            // 根据商家ID获取商家信息
            Shop shop = shopMapper.selectById(sellId);
            String shopSellName = shop.getSellName();
            AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
            // 支付请求
            request.setBizContent("{" +
                    "    "out_trade_no":"" + orderId + ""," +//商户订单号
                    "    "total_amount":"" + order.getOrderPrice().setScale(2, RoundingMode.CEILING) + ""," +
                    "    "subject":"" + shopSellName + "当面付" + ""," +
                    "    "store_id":"00100"," + // (必填) 商户门店编号,通过门店号和商家后台可以配置精准到门店的折扣信息,详询支付宝技术支持
                    "    "timeout_express":"5m"}");//订单允许的最晚付款时间
            AlipayTradePrecreateResponse response = null;
            //支付宝二维码URL
            String qrCode = "";
            try {
                response = alipayClient.execute(request);
                if (!response.isSuccess()) {
                    throw new CustomException("生成支付宝订单失败:" + response.getMsg());
                }
                qrCode = response.getQrCode();
            } catch (AlipayApiException e) {
                throw new CustomException(e.getMessage());
            }
            // 封装支付信息 返回
            PayInfoVO payInfoVO = new PayInfoVO();
            payInfoVO.setOrderId(order.getOrderId());
            payInfoVO.setShopName(shopSellName);
            payInfoVO.setUrl(qrCode);
            log.info("payInfo: {}",payInfoVO);
            return payInfoVO;
        }
    }
    

    controller

       	@Autowired
        @Qualifier("PayServiceImpl")
        private PayService payService;
        
     	@ApiOperation("返回支付二维码和支付信息")
        @GetMapping("/qr/{orderId}")
        public AjaxResult getPayInfo(@PathVariable String orderId) {
            PayInfoVO payInfoVO = payService.getPayInfo(orderId);
            return AjaxResult.success("支付成功", payInfoVO);
        }
    

    支付状态

    @AllArgsConstructor
    @Getter
    public enum PayStatusEnum {
        /** 等待扫码 */
        WAIT_SCANNED(0,"等待扫码"),
        /** 等待支付(已扫码,未支付) */
        UN_PROCESSED(1,"等待支付"),
        /** 商家已完成,等待骑手取餐 */
        PROCESSED(2,"已支付"),
        /** 订餐者关闭或者超时关闭 */
        SHIPPING(3,"已取消"),
        ;
        private Integer code;
        private String msg;
    
        public static PayStatusEnum valueOf(Integer code){
            for (PayStatusEnum value : values()) {
                if (value.code.equals(code)) {
                    return value;
                }
            }
            return null;
        }
    }
    

    支付结果对象

    @Data
    @ToString
    public class PayResultDTO implements Serializable {
        //支付ID
        private Long payId;
        // 支付状态
        private Integer status;
        // 支付金额
        private BigDecimal amount;
        // 支付信息
        private String msg;
    }
    

    获取支付状态

    // 根据orderId获取支付状态
        public PayResultDTO getPayStatus(String orderId) {
            log.info("status: ========= {}",orderId);
            //创建API对应的request类
            AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
            request.setBizContent("{" +
                    "    "out_trade_no":"" + orderId + ""}");
            AlipayTradeQueryResponse response = null;
            Order order = new Order();
            order.setOrderId(orderId);
            PayResultDTO payResultDTO = new PayResultDTO();
            try {
                response = alipayClient.execute(request);
                if (!response.isSuccess()) {
                    // 获取支付信息失败
                    payResultDTO.setStatus(PayStatusEnum.WAIT_SCANNED.getCode());
                    payResultDTO.setMsg("等待扫码");
                    return payResultDTO;
                }
                payResultDTO.setThirdPartId(response.getTradeNo());
                switch (response.getTradeStatus()) {
                    case "WAIT_BUYER_PAY":
                        payResultDTO.setStatus(PayStatusEnum.UN_PROCESSED.getCode());
                        payResultDTO.setMsg("已扫码,等待用户支付");
                        break;
                    case "TRADE_CLOSED":
                        payResultDTO.setStatus(PayStatusEnum.SHIPPING.getCode());
                        payResultDTO.setMsg("支付已关闭");
                        break;
                    case "TRADE_SUCCESS":
                        payResultDTO.setStatus(PayStatusEnum.PROCESSED.getCode());
                        payResultDTO.setAmount(new BigDecimal(response.getTotalAmount()));
                        payResultDTO.setMsg("支付成功");
                        order.setPayStatus(Constants.PAY_STATUS_PAID);
                        // 这里写支付成功的逻辑,例如设置支付时间,订单状态什么的
                        break;
                    default:
                        break;
                }
                return payResultDTO;
            } catch (AlipayApiException e) {
                payResultDTO.setStatus(-1);
                payResultDTO.setMsg("查询订单状态错误:" + e.getErrMsg());
                return payResultDTO;
            }
        }
    

    controller
    获取支付状态

      
        @ApiOperation("获取支付状态")
        @GetMapping("/status/{orderId}")
        public AjaxResult getPayStatus(@PathVariable String orderId){
            PayResultDTO payStatus = payService.getPayStatus(orderId);
            return AjaxResult.success("支付状态对象",payStatus);
        }
    

    最终测试

    在这里插入图片描述
    使用沙箱版App登录账户扫码支付
    在这里插入图片描述

    在这里插入图片描述

    希望对大家有所帮助!

  • 相关阅读:
    .net 存储过程中的 output参数取值问题
    【从零开始学Servlet笔记】Servelet入门
    【从零开始学Servlet笔记】Web资源
    【从零开始学Servlet笔记】Http协议
    【从零开始学Mybatis笔记】SqlMapConfig.xml配置文件
    【从零开始学Mybatis笔记】Dao开发方法
    【从零开始学Mybatis笔记】Mybatis入门
    【从零开始学SpringMVC笔记】SpringMVC进阶
    【从零开始学SpringMVC笔记】SpringMVC与struts2不同
    【从零开始学SpringMVC笔记】参数绑定
  • 原文地址:https://www.cnblogs.com/dataoblogs/p/14401339.html
Copyright © 2011-2022 走看看