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登录账户扫码支付
在这里插入图片描述

在这里插入图片描述

希望对大家有所帮助!

posted @ 2021-02-13 23:54  起个名字都这么男  阅读(501)  评论(2编辑  收藏  举报