Springboot整合支付宝沙箱支付

我们在写支付系统的时候,大致的流程是这样

关于订单超时的问题,可以看我的另一篇博文,下面来介绍以下项目整合支付宝沙箱支付

支付宝沙箱支付

正常使用的情况下是需要向支付宝发申请,支付宝会帮你开通服务,对于我们开发者来说,可以使用支付宝沙箱支付来模拟支付
1、进入支付宝开放平台 支付宝开放平台,找到沙箱环境 沙箱环境地址
2.使用秘钥工具,生成我们的私钥-公钥对 https://miniu.alipay.com/keytool/create

3.设置我们的应用公钥

4.引入依赖

<dependency>
            <groupId>com.alipay.sdk</groupId>
            <artifactId>alipay-sdk-java</artifactId>
            <version>3.0.0</version>
 </dependency>

5.编写配置类

public class AlipayConfig {
    // 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号,开发时使用沙箱提供的APPID,生产环境改成自己的APPID
    public static String APP_ID = "";
    // 商户私钥,您的PKCS8格式RSA2私钥
    public static String APP_PRIVATE_KEY = "";
    // 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
    public static String ALIPAY_PUBLIC_KEY = "";
    // 服务器异步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
    public static String notify_url = "http://localhost:80/paysuccess";
    // 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,我们本地的话只需要这个即可(其实就是支付成功后返回的页面)
    public static String return_url = "http://localhost:80/paysuccess";
    // 签名方式
    public static String sign_type = "RSA2";
    // 字符编码格式
    public static String CHARSET = "utf-8";
    // 支付宝网关,这是沙箱的网关
    public static String gatewayUrl = "https://openapi.alipaydev.com/gateway.do";
}

6.编写controller

    @ResponseBody
    @GetMapping("/order/pay/{id}")
    public String addOrder(@PathVariable("id") String id) throws AlipayApiException, IOException {
        Order order = orderService.selectById(id);
        Commodity commodity = commodityService.LookCommodity(new Commodity().setCommid(order.getGoodsId()));
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.APP_ID, AlipayConfig.APP_PRIVATE_KEY , "json", AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.sign_type);
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        //商户订单号,商户网站订单系统中唯一订单号,必填
        String out_trade_no = order.getId();
        //付款金额,必填
        String total_amount = String.valueOf(order.getPrice());
        //订单名称,必填
        String subject = commodity.getCommname();
        alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
                + "\"total_amount\":\""+ total_amount +"\","
                + "\"subject\":\""+ subject +"\","
                + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
        alipayRequest.setReturnUrl("http://localhost");
        String body= alipayClient.pageExecute(alipayRequest).getBody();
        return body;
    }

7.成功回调

    @GetMapping("/paysuccess")
    public String paySuccess(PayAsyncVo vo,HttpServletRequest request) throws AlipayApiException {
        boolean signVerified = checkV1(request);
        if(signVerified){
            String out_trade_no = vo.getOut_trade_no();
            Order order = orderService.selectById(out_trade_no);
            orderService.updateStatus(order.getId());
            return "/index";
        }else{
            return "error";
        }
    }

    private boolean checkV1(HttpServletRequest request) throws AlipayApiException {
        /*
         * 支付宝验证签名
         * 获取支付宝POST过来反馈信息
         */
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            // 乱码解决,这段代码在出现乱码时使用
            // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }
        // 调用SDK验证签名
        return AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, AlipayConfig.sign_type);
    }

//PayAsyncVo类是为了方便注入支付宝返回的参数,具体可一件支付宝的开发文档
@ToString
@Data
public class PayAsyncVo {
    private String gmt_create;
    private String charset;
    private String gmt_payment;
    private String notify_time;
    private String subject;
    private String sign;
    /** 支付者的id */
    private String buyer_id;
    /** 订单的信息 */
    private String body;
    /** 支付金额 */
    private String invoice_amount;
    private String version;
    /** 通知id */
    private String notify_id;
    private String fund_bill_list;
    /** 通知类型; trade_status_sync */
    private String notify_type;
    /** 订单号 */
    private String out_trade_no;
    /** 支付的总额 */
    private String total_amount;
    /** 交易状态  TRADE_SUCCESS */
    private String trade_status;
    /** 流水号 */
    private String trade_no;
    private String auth_app_id;
    /** 商家收到的款 */
    private String receipt_amount;
    private String point_amount;
    /** 应用id */
    private String app_id;
    /** 最终支付的金额 */
    private String buyer_pay_amount;
    /** 签名类型 */
    private String sign_type;
    /** 商家的id */
    private String seller_id;
}

基本完成了,后面还有退款什么的,就懒得写了,基本思路差不多

posted @ 2021-05-05 20:28  刚刚好。  阅读(556)  评论(0)    收藏  举报