支付宝:沙箱环境简单使用


参考文档:


一、沙箱环境

记录一下犯的错误.
二级标题与官方文档的二级标题一致:方便于自己对比

1. 配置密钥/证书

系统默认密钥

使用 API 在线调试工具 调试 OpenAPI 必须使用 系统默认密钥。

不需要再配置 获取加签密钥/证书,系统的默认密钥在支付宝API 在线调试工具中可以看到,具体如下所示:

私钥:
在这里插入图片描述
公钥:
在这里插入图片描述

自定义密钥

官网文档:自定义密钥 里面写的很详细。

普通公钥与公钥证书二选一就行普通公钥与公钥证书区别最主要区别是否涉及资金类支出接口接入。

需要注意的是:配置公钥证书组织与公司已经进行了更改
在这里插入图片描述
其他的与官方文档对应即可。

二、代码实现

2.1 项目总体结构

在这里插入图片描述

2.2 编码

省略了一个工具类:OrderCodeUtils:主要用于订单号生成。

1. 添加相关依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.19</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <!-- IJPay    -->
        <dependency>
            <groupId>com.github.javen205</groupId>
            <artifactId>IJPay-AliPay</artifactId>
            <version>2.8.0</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

2. 配置文件:支付宝应用参数

server:
  port: 1314

alipay:
  # 应用编号
  appId: 
  # 应用私钥
  privateKey: 
  # 支付宝公钥 (如果是证书模式,公钥与私钥在CSR目录)
  publicKey: 
  # 通知地址或回调地址  !回调地址一定是外网可以访问到的域名!
  domain: 
  # 支付宝支付网关
  serviceUrl: 
  # 应用公钥证书 (证书模式必须)
#  appCertPath:
  # 支付宝公钥证书 (证书模式必须)
#  aliPayCertPath:
  # 支付宝根证书 (证书模式必须)
#  aliPayRootCertPath:

3. 配置文件类

@Component
@Data
@ConfigurationProperties(prefix = "alipay")
public class AlipayProperties {

    private String appId;
    private String privateKey;
    private String publicKey;
    private String doMain;
    private String serviceUrl;
}

4. 初始化支付宝

为什么要初始化支付宝?
支付宝初始化的原因:IJPay 中默认是使用当前线程中的 appId 对应的配置

方法一:使用@PostConstruct注解

@PostConstruct注解原理解析:@PostConstruct注解的方法会在程序启动的时候执行

在启动类上添加@PostConstruct注解的方法:

@SpringBootApplication
public class AlipayApplication {
    public static void main(String[] args){
        SpringApplication.run(AlipayApplication.class, args);
    }

    @PostConstruct
    public void aliPayInit() {
        AlipayProperties aliPayProperties = SpringUtil.getBean(AlipayProperties.class);
        AliPayApiConfig aliPayApiConfig = AliPayApiConfig.builder()
                .setAppId(aliPayProperties.getAppId())
                .setAliPayPublicKey(aliPayProperties.getPublicKey())
                .setPrivateKey(aliPayProperties.getPrivateKey())
                .setServiceUrl(aliPayProperties.getServiceUrl())
                .setCharset("UTF-8")
                .setSignType("RSA2")
                .build();
        AliPayApiConfigKit.putApiConfig(aliPayApiConfig);
    }
}

方法二:使用方法拦截器

OrderController里面,添加初始化支付宝的方法

@RestController
@RequestMapping(value = "/aliPay")
@Slf4j
public class OrderController {

    @Autowired
    private AlipayProperties alipayProperties;
    
    public AliPayApiConfig getApiConfig() {
        AliPayApiConfig aliPayApiConfig = AliPayApiConfig.builder()
                .setAppId(alipayProperties.getAppId())
                .setAliPayPublicKey(alipayProperties.getPublicKey())
                .setPrivateKey(alipayProperties.getPrivateKey())
                .setServiceUrl(alipayProperties.getServiceUrl())
                .setCharset("UTF-8")
                .setSignType("RSA2")
                // 证书模式
                // .setAppCertPath(alipayProperties.getAppCertPath())
                // .setAliPayCertPath(alipayProperties.getAliPayCertPath())
                // .setAliPayRootCertPath(alipayProperties.getAliPayRootCertPath())
                // 普通公钥方式
                .build();
                // 证书模式
                // .buildByCert();
        return aliPayApiConfig;
    }
}    

设置OrderController的拦截器AliPayInterceptor

public class AliPayInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws AlipayApiException {
        if (HandlerMethod.class.equals(handler.getClass())) {
            HandlerMethod method = (HandlerMethod) handler;
            Object methodBean = method.getBean();
            AliPayApiConfigKit.setThreadLocalAliPayApiConfig(((OrderController) methodBean).getApiConfig());
            return true;
        }
        return false;
    }
}

AlipayConfig 继承WebMvcConfigurationSupport类,并配置拦截器

@Configuration
public class AlipayConfig extends WebMvcConfigurationSupport {

    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AliPayInterceptor()).addPathPatterns("/aliPay/**");
        super.addInterceptors(registry);
    }
}

5. 调用 AliPayApi 中的接口

OrderController里面,编写URL请求方法。

此处,以调用 付款码支付 为例子。

扫码支付

这里会返回一个URL,到 二维码制作 中生成二维码,使用支付宝提供的 沙箱版支付宝钱包 ,登录买家账号,发起购买。

特别注意: 回调地址一定是外网可以访问到的域名,可以使用外网端口映射相关的工具来处理。(我买的是花生壳Http,6元),也可以找度娘。

    /**
     * 扫码支付
     *
     * @return java.lang.String
     * @date 2022/2/9 11:34
     */
    @GetMapping(value = "/tradePreCreatePay")
    public String tradePreCreatePay() {

        String notifyUrl = alipayProperties.getDoMain() + "/aliPay/aliPayNotifyUrl";

        AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
        model.setSubject("Javen 支付宝扫码支付测试");
        model.setTotalAmount("10");
        model.setStoreId("123");
        model.setTimeoutExpress("5m");
        String orderNo = OrderCodeUtils.getRandom();
        model.setOutTradeNo(orderNo);
        try {
            AlipayTradePrecreateResponse response = AliPayApi.tradePrecreatePayToResponse(model, notifyUrl);
            String resultStr = response.getBody();
            JSONObject jsonObject = JSONObject.parseObject(resultStr);
            return jsonObject.getJSONObject("alipay_trade_precreate_response").getString("qr_code");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
支付回调
    /**
     * 支付回调
     *
     * @param request 请求体
     * @return java.lang.String
     * @date 2022/2/9 11:34
     */
    @PostMapping(value = "/aliPayNotifyUrl")
    public String aliPayNotifyUrl(HttpServletRequest request) {
        try {
            // 获取支付宝POST过来反馈信息
            Map<String, String> params = AliPayApi.toMap(request);
            // 遍历打印出反馈信息
            // for (Map.Entry<String, String> entry : params.entrySet()) {
            //     System.out.println(entry.getKey() + " = " + entry.getValue());
            // }

            boolean verifyResult = AlipaySignature.rsaCheckV1(params, alipayProperties.getPublicKey(), "UTF-8", "RSA2");

            if (verifyResult) {
                // TODO 请在这里加上商户的业务逻辑程序代码 异步通知可能出现订单重复通知 需要做去重处理
                System.out.println("notify_url 验证成功succcess");
                return "success";
            } else {
                System.out.println("notify_url 验证失败");
                // TODO
                return "failure";
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
            return "failure";
        }
    }
订单关闭
    /**
     * 关闭订单
     *
     * @param outTradeNo 商家内部订单号
     * @date 2022/2/9 11:53
     * @return java.lang.String
     */
    @GetMapping(value = "/tradeClose")
    public String tradeClose(@RequestParam("outTradeNo") String outTradeNo){
        try {
            AlipayTradeCloseModel closeModel = new AlipayTradeCloseModel();
            closeModel.setOutTradeNo(outTradeNo);
            return AliPayApi.tradeCloseToResponse(closeModel).getBody();
        } catch (AlipayApiException e){
            e.printStackTrace();
        }
        return null;
    }
支付退款
    /**
     * 支付退款
     *
     * @param outTradeNo 商家内部订单号
     * @date 2022/2/9 15:38
     * @return java.lang.String
     */
    @GetMapping(value = "/tradeRefund")
    public String tradeRefund(@RequestParam("outTradeNo") String outTradeNo){
        try {
            AlipayTradeRefundModel refundModel = new AlipayTradeRefundModel();
            refundModel.setOutTradeNo(outTradeNo);
            refundModel.setRefundAmount("10");
            refundModel.setRefundReason("退款测试");
            return AliPayApi.tradeRefundToResponse(refundModel).getBody();
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return null;
    }
订单查询
    /**
     * 订单查询
     *
     * @param outTradeNo 商家内部订单号
     * @date 2022/2/9 15:37
     * @return java.lang.String
     */
    @GetMapping(value = "/tradeQuery")
    public String tradeQuery(@RequestParam("outTradeNo") String outTradeNo){
        AlipayTradeQueryModel queryModel = new AlipayTradeQueryModel();
        queryModel.setOutTradeNo(outTradeNo);
        try {
            AlipayTradeQueryResponse queryResponse = AliPayApi.tradeQueryToResponse(queryModel);
            return queryResponse.getBody();
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return null;
    }
退款查询
    /**
     * 退款查询
     *
     * @param outTradeNo 商户内部交易号
     * @date 2022/2/9 15:47
     * @return java.lang.String
     */
    @GetMapping(value = "/refundQuery")
    public String refundQuery(@RequestParam("outTradeNo") String outTradeNo){
        AlipayTradeFastpayRefundQueryModel refundQueryModel = new AlipayTradeFastpayRefundQueryModel();
        refundQueryModel.setOutTradeNo(outTradeNo);
        refundQueryModel.setOutRequestNo(outTradeNo);
        try {
            return AliPayApi.tradeRefundQueryToResponse(refundQueryModel).getBody();
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return null;
    }

2.3 测试

### 扫码支付
GET http://localhost:1314/aliPay/tradePreCreatePay

### 关闭订单
GET http://localhost:1314/aliPay/tradeClose?outTradeNo=1491259312927019008

### 支付退款
GET http://localhost:1314/aliPay/tradeRefund?outTradeNo=1491238575935721472

### 订单查询
GET http://localhost:1314/aliPay/tradeQuery?outTradeNo=1491259312927019008

### 退款查询
GET http://localhost:1314/aliPay/refundQuery?outTradeNo=1491238575935721472

三、总结

  1. 相比较于微信支付,阿里的支付宝开发文档支付实在是太友好了。
  2. 支付流程的话,与微信支付差不多。
  3. 写的有错误的地方,欢迎指正。
  4. 附上:微信支付总结
  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的Spring Boot和Vue.js应用程序中的支付沙箱支付代码示例: 在Spring Boot项目中: 1. 添加以下依赖: ``` <dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alipay-sdk-java</artifactId> <version>4.3.0.ALL</version> </dependency> ``` 2. 创建一个包含支付配置信息的类,例如: ``` @Configuration public class AlipayConfig { private String appId; private String privateKey; private String publicKey; private String notifyUrl; private String returnUrl; private String gatewayUrl; // getters and setters } ``` 3. 创建一个返回AlipayClient的方法: ``` @Bean public AlipayClient getAlipayClient() { return new DefaultAlipayClient( alipayConfig.getGatewayUrl(), alipayConfig.getAppId(), alipayConfig.getPrivateKey(), "json", "UTF-8", alipayConfig.getPublicKey(), "RSA2" ); } ``` 4. 在控制器中创建支付接口,例如: ``` @Autowired private AlipayClient alipayClient; @Autowired private AlipayConfig alipayConfig; @PostMapping("/pay") public String pay(@RequestParam String orderNo, @RequestParam String amount) throws AlipayApiException { AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest(); alipayRequest.setReturnUrl(alipayConfig.getReturnUrl()); alipayRequest.setNotifyUrl(alipayConfig.getNotifyUrl()); alipayRequest.setBizContent("{\"out_trade_no\":\"" + orderNo + "\"," + "\"total_amount\":\"" + amount + "\"," + "\"subject\":\"" + "测试订单" + "\"," + "\"body\":\"" + "测试订单" + "\"," + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}"); String form = alipayClient.pageExecute(alipayRequest).getBody(); return form; } ``` 在Vue.js中: 1. 创建一个按钮来启动支付流程: ``` <template> <div> <button @click="pay">Pay Now</button> </div> </template> ``` 2. 在脚本部分中创建一个调用支付接口的方法: ``` <script> export default { methods: { pay() { axios.post('/api/pay', { orderNo: '123456', amount: '0.01' }) .then(response => { let form = response.data; document.write(form); // 打开支付页面 }) .catch(error => { console.log(error); }); } } } </script> ``` 请注意,以上示例只适用于测试环境,如果您想在生产环境使用支付支付,您需要进行更多的测试和配置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值