当前位置:

首页 > 编程开发 > Java中如何实现支付功能?

Java中如何实现支付功能?

史上最简单的支付SDK首先我们先看下API:packagecom.joe.pay;importcom.joe.pay.pojo.*;/***支付服务接口**@authorjoe*@version2018.06.2911:32*/publicinterfacePayService{/***调用第三方支付**@paramrequest支付参数*@return支付结果*/SysResponsepay(PayRequestrequest);/***申请退款**@paramrequest退款请求*@return退款

本文目录

    史上最简单的支付SDK

    首先我们先看下API:

    package com.joe.pay;
    
    import com.joe.pay.pojo.*;
    
    /**
     * 支付服务接口
     *
     * @author joe
     * @version 2018.06.29 11:32
     */
    public interface PayService {
        /**
         * 调用第三方支付
         *
         * @param request 支付参数
         * @return 支付结果
         */
        SysResponse pay(PayRequest request);
    
        /**
         * 申请退款
         *
         * @param request 退款请求
         * @return 退款响应
         */
        SysResponse refund(RefundRequest request);
    }
       

    可以看到,PayService接口提供了支付方法和退款方法,下面我们看下支付方法的参数定义:

    package com.joe.pay.pojo;
    
    import lombok.Data;
    
    /**
     * 支付参数,除了openid外所有参数必填
     *
     * @author joe
     * @version 2018.07.02 10:36
     */
    @Data
    public class PayRequest implements Request{
        /**
         * 商户网站唯一订单号
         */
        private String outTradeNo;
        /**
         * 对一笔交易的描述信息
         */
        private String body;
        /**
         * 商品的标题/交易标题/订单标题/订单关键字等。
         * 

         * 对于微信支付来说需传入应用市场上的APP名字-实际商品名称,天天爱消除-游戏充值。      */     private String subject;     /**      * 订单生成时间,格式为yyyy-MM-dd HH:mm:ss      */     private String createTime;     /**      * 支付时长,单位为秒,如果设置300就是五分钟,超过五分钟订单自动取消      */     private int expire = 300;     /**      * 订单金额,单位为分      */     private int totalAmount;     /**      * 发起请求的用户的实际IP      */     private String ip;     /**      * 支付类型:APP、WEB(微信对应公众号,支付宝对应网页支付)      */     private String tradeType = "APP";     /**      * 用户openid,只有在微信公众号支付时需要      */     private String openid;     /**      * 附加数据,会与结果一并返回      */     private String attach; }

       

    OK,上边的参数相信就算没做过支付的同学也能很清晰直观的看懂这些信息,都是一些订单基本信息,下面我们来看退款参数的定义:

    package com.joe.pay.pojo;
    
    import lombok.Data;
    import org.hibernate.validator.constraints.NotEmpty;
    
    import javax.validation.constraints.Size;
    
    /**
     * 退款请求
     *
     * @author joe
     * @version 2018.07.05 17:12
     */
    @Data
    public class RefundRequest {
        /**
         * 第三方账单ID,与outTradeNo不能同时为空
         */
        private String orderId;
        /**
         * 商户系统订单ID,与orderId不能同时为空
         */
        private String outTradeNo;
        /**
         * 商户退款单号
         * 

         * 退款支持单笔交易分多次退款,多次退款需要提交原支付订单的商户订单号和设置不同的退款单号。申请退款总金      * 

         * 额不能超过订单金额。 一笔退款失败后重新提交,请不要更换退款单号,请使用原商户退款单号。      */     @NotEmpty(message = "商户退款单号不能为空")     private String outRefundNo;     /**      * 订单总金额,单位为分      */     @Size(min = 1)     private int totalFee;     /**      * 退款金额,不能大于订单总金额      * 

         * 注:多次退款总金额不能大于订单总金额      */     @Size(min = 1)     private int refundFee;     /**      * 退款原因      * 

         * 可以为空      */     private String refundDesc; }

       

    退款参数就更简单了,需要的信息也是相当少。有了这些之后我们就可以来看支付测试代码了:

    package com.joe.pay;
    
    import com.joe.pay.pojo.*;
    import com.joe.pay.pojo.prop.PayProp;
    import com.joe.utils.common.DateUtil;
    import com.joe.utils.common.Tools;
    import org.junit.Assert;
    import org.junit.Before;
    import org.junit.Test;
    
    /**
     * 支付测试
     *
     * @author joe
     * @version 2018.07.02 14:38
     */
    public class PayServiceTest {
        /**
         * 微信配置
         */
        private PayProp wxProp;
        private PayProp aliProp;
        /**
         * 微信服务
         */
        private PayService wxPayService;
        private PayService aliPayService;
    
        @Before
        public void init() {
            //配置微信支付,需要将下列参数替换为自己的参数
            wxProp = PayProp.builder()
                    .appid("123123123")
                    .notifyUrl("http://www.baidu.com")
                    .useWxPay()
                    .certInput(null)
                    .key("123123123")
                    .mchId("123123123123")
                    .password("123123123123")
                    .build();
    
            wxPayService = PayServiceFactory.getInstance(wxProp);
    
            String privateKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDEuQvaAad8+PAUVLeh9tqNsWNDCiAXEal4krM0E1"
                    + "4oHiUvzOT8Xf5BYZeMmiA+G+Z4iT2dP6bNRBIth7W5COh51v8TDf4dYxqV3Jw7jyQF2K/p74izFXm96yDXz3cMotRdDW3JdcC"
                    + "ME2tgrlSjJxN26qPCrHh+OL9Y/yqJGhsAHKlaIYQ4S8F9B3rIPMAv6MbTuHFrFXkwuJqesupTwUqzmPgriy/2Au9ZApnpVCex"
                    + "sKIkjMwpmOe3FxaQ9U6271NA9jmzbg7ge5BlfblQL3lIkEQdoqPPKrfLbO3djN1ORn1vhKrIAUhIQAqWKDVdz9dGxrIZckGOe"
                    + "8iuUGOs8D4VAgMBAAECggEBAIzyuJcekE5uXjVy7Y9SOw1Ch5hE/PEKao5FLbimF9ROpP42o+pdvgpCTj8jPu7BNsQuMMM2E+"
                    + "EGYK/WiFFnHIlYIbIZWHTdyPKO+jGCQaEevAu04BDP1kZI7WMy9m1LTTTOplat06OJVmoS/flXyg5t159ny31EU3UEfgl1dts"
                    + "AayODTTRkRUjYXYXSOSDLZjlxSntNS9seklPgEeinc2umrdzJuzciKspK1XLqpCvc+1WA2NlTkoW6Hc9aj61ySCOTkF/3OVjj"
                    + "G58jiUMzSeRsG3gq3PEJfhw2FUiJxn04ZRId74tIKrjKV4Np97WdmFEkpTEUTqvSp3AUYm/wJ5ECgYEA9pzaM+dd7vacLbgkA"
                    + "e3N8dfyJggSJWm5TpangYIfQBXp+TiLhHFP6lhpCrs/qoxdsmM6LtzEkchvAQOA1kgNgRhm4s1pihKc7aAqK9YxE2tT5Z8XXd"
                    + "9SXdLoHXe7GW3Q2ivouMV+J31mhOwSlogR5q0AztXJCl0FH9HHehMyAC8CgYEAzDYJOTOiHm5xjAJ337dtVe1zGUUBwv58B2O"
                    + "wZXp129frnOepM+B663aMbrh+IUzVSQWqufGKUkLwjbRmwjrs9Lw4nFYtNGYVp1wnFawVOXy532tthYG5m3i/KcXjIRwnNHew"
                    + "9Xh5q9rDc30yPKMps+Uijrp7ktQIRfh+QbOi8PsCgYBQccXz3GsVwjgb6c9FGc9uLmT85vEUZzJdYmNtqYaMHxndhAZuw4+v/"
                    + "/rz1zTjazo9MIUQOE+exmT/Tac/Pu24yL73CM5+jafHE9HtzsbfcMlDQ+wZYPm7RUsWIbJUjy/rmxsk+rc2Jn/EqEU/+U7tkk"
                    + "2LKs2TpdhAEuwg9BYBXQKBgQCKAZKmJ7DOJBF0b06X0ByBz6DTWQFhyB4F2GcjjWkNE5TVSvHcbz5i1pD9Wo1S79vMJ5pDY2r"
                    + "5QOfUvDAd3zi4BGO1s7+FA+BqZCq9yLfnS9VJmg5ABXVsDmQSVPu0KpSMLr9WhP34FjW0XM2QkSvjuVxrXLeaeNTGhLK+sCnT"
                    + "9QKBgHfd3hhLWjO4zh99B+PRYFgpnJa9S5E1zzoejZVIJhK5q60KLV5n/HMxuHTGRZxpbfcH4/44d3Yz7ieccmCiPtqxFYUwP"
                    + "W0JukNWDL2tOzTSZ5ABAwqorV3bM67mLUSt0O5dL4YtSBJ2J3F6joO1fTZEcUCybO/A5J4wTZDOV1AR";
    
            //配置支付宝支付,需要将下列参数替换为自己的参数
            aliProp = PayProp.builder()
                    .appid("123123123")
                    .notifyUrl("http://www.baidu.com")
                    .useAliPay()
                    .publicKey("123123")
                    .privateKey(privateKey)
                    .build();
            aliPayService = PayServiceFactory.getInstance(aliProp);
        }
    
        /**
         * 测试微信支付
         */
        @Test
        public void doWxPay() {
            doPay(wxPayService);
        }
    
        /**
         * 测试支付宝支付
         */
        @Test
        public void doAliPay() {
            doPay(aliPayService);
        }
    
        /**
         * 测试微信退款
         * 

         * 注意:该测试当前通不过,因为没有提供正确的证书,若想要测试通过则需要在配置文件中提供正确的微信证书和单号      */     @Test     public void doWxRefund() {         doRefund(wxPayService);     }     /**      * 测试支付宝退款      * 

         * 注意:该测试当前通不过,若想要测试通过则需要提供正确的单号      */     @Test     public void doAliRefund() {         doRefund(aliPayService);     }     /**      * 校验响应      *      * @param response 响应      */     private void check(SysResponse response) {         Assert.assertTrue(response.isSuccess());         Assert.assertTrue(response.getData().isSuccess());     }     /**      * 发起支付请求      *      * @param service service      */     private void doPay(PayService service) {         SysResponse response = service.pay(buildPay());         check(response);     }     /**      * 发起退款请求      *      * @param service service      */     private void doRefund(PayService service) {         SysResponse response = service.refund(buildRefund());         System.out.println("结果是:" + response);     }     /**      * 构建一个支付订单      *      * @return 支付订单      */     private PayRequest buildPay() {         PayRequest payRequest = new PayRequest();         payRequest.setOutTradeNo(Tools.createUUID());         payRequest.setBody("天天爱消除-游戏充值");         payRequest.setSubject("天天爱消除-游戏充值");         payRequest.setCreateTime(DateUtil.getFormatDate(DateUtil.BASE));         payRequest.setTotalAmount(100 * 10);         payRequest.setIp("106.120.141.226");         return payRequest;     }     /**      * 构建一个退款订单      *      * @return 退款订单      */     private RefundRequest buildRefund() {         RefundRequest request = new RefundRequest();         request.setOutTradeNo("123456");         request.setOutRefundNo("123456");         request.setTotalFee(100 * 10);         request.setRefundFee(100);         return request;     } }

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发 Java
    相关文章 更多
    Java单元测试入门:使用JUnit 5编写第一个测试用例
    Java单元测试入门:使用JUnit 5编写第一个测试用例

    面向初学者的JUnit 5实用入门指南。从测试概念、Maven依赖配置,到手把手编写首个单元测试用例及断言验证,助你掌握Java单元测试的核心流程。

    Java变量未初始化报错解析:局部变量与成员变量默认值差异
    Java变量未初始化报错解析:局部变量与成员变量默认值差异

    深入解析Java中局部变量未初始化编译报错与成员变量自动赋予默认值的机制差异,涵盖JVM内存分配、编译期确定性赋值检查与实际排查修复方案。

    Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat
    Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat

    详细讲解在Java中获取当前系统时间并进行格式化输出的两种核心方案:基于Java 8全新日期时间API的DateTimeFormatter与传统遗留的SimpleDateFormat,包含完整代码示例、线程安全机制对比及生产选型建议。

    Java中final与static final常量的定义及初始化规则
    Java中final与static final常量的定义及初始化规则

    深入解析Java中final变量与static final常量的定义、内存语义、初始化时机及合法赋值路径,涵盖编译期常量优化与实战避坑指南。

    Java抽象方法与接口方法的区别及选型建议
    Java抽象方法与接口方法的区别及选型建议

    深入对比Java中抽象类抽象方法与接口方法的语法演进、设计意图及运行期差异,并提供清晰的架构选型决策流程与实战范例。

    Java实现HTTP请求与JSON解析的完整代码示例
    Java实现HTTP请求与JSON解析的完整代码示例

    本文提供Java标准库HttpClient发起HTTP GET/POST请求并结合Jackson进行JSON数据反序列化与序列化的完整代码示例与工程实践指南。

    Java递归出现StackOverflowError的原因分析及栈空间优化方案
    Java递归出现StackOverflowError的原因分析及栈空间优化方案

    详细分析Java递归调用出现StackOverflowError的原因,结合代码说明线程栈、栈帧和递归深度之间的关系,并介绍终止条件排查、迭代改写、减少栈帧开销以及通过-Xss调整JVM栈空间的方法。

    Java空指针异常(NPE)的代码排查与修复实例
    Java空指针异常(NPE)的代码排查与修复实例

    针对Java中常见的NullPointerException(NPE),本文从堆栈日志定位、典型代码触发场景、具体修复代码对比到防御体系进行系统讲解,提供实用且易上手的排查与修复方案。

    selenium上传文件教程本地文件路径设置方法
    selenium上传文件教程本地文件路径设置方法

    深入解析Selenium处理文件上传的技术细节,涵盖标准HTML控件的路径直接注入法与非标准控件的系统级模拟方案,提供Windows与Linux环境下的路径设置最佳实践及常见异常排查。

    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景
    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景

    针对大数据工程场景,系统对比Java、Scala与Python在执行性能、生态结合、开发效率和维护成本上的核心差异,给出清晰的架构选型依据与落地方案。

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程
    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    Mac软件 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    Aperty macOS版
    Aperty macOS版
    macOS

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    WINDOWS 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    PixTV 网页版
    PixTV 网页版
    Windows

    PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。