当前位置:   article > 正文

沙箱支付宝alipay-easysdk java 支付能力对接

alipay-easysdk java

1.配置沙箱密钥并获取沙箱账号密码
1)打开支付宝开放平台主页https://open.alipay.com/platform/home.htm并登陆
2)打开https://opendocs.alipay.com/open/291/105971下载密钥生成工具
3)生成密钥(应用私钥就是下面alipay.properties中的merchantPrivateKey)
在这里插入图片描述
4)打开https://openhome.alipay.com/platform/appDaily.htm?tab=info设置支付宝公钥
下面是我已经设置好的
在这里插入图片描述

将应用公钥复制上去生成的支付宝公钥就是alipay.properties中的alipayPublicKey
5)记住沙箱账号密码
在这里插入图片描述
准备工作完成,接下来创建java工程
工程目录结构
在这里插入图片描述

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.wl.alipay</groupId>
    <artifactId>alipay</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring-boot-version>2.0.8.RELEASE</spring-boot-version>
        <slf4j-api-version>1.7.5</slf4j-api-version>
        <commons-lang-version>3.6</commons-lang-version>
        <MainClass>com.wl.alipay.PayApplication</MainClass>
    </properties>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/com.alipay.sdk/alipay-easysdk -->
        <dependency>
            <groupId>com.alipay.sdk</groupId>
            <artifactId>alipay-easysdk</artifactId>
            <version>2.1.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${spring-boot-version}</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j-api-version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>${commons-lang-version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>${spring-boot-version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring-boot-version}</version>
                <configuration>
                    <mainClass>${MainClass}</mainClass>
                    <layout>JAR</layout>
                </configuration>
                <!-- repackage  生成两个 jar.original -->
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <!-- 指定maven 打包java 版本 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
        <!-- maven  编译打包resource 和 java 目录下所有文件  maven默认资源路径是resources -->
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.*</include>
                    <include>*.*</include>
                </includes>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.*</include>
                    <include>*.*</include>
                </includes>
            </resource>
        </resources>
    </build>

</project>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109

application.properties

server.port=80
  • 1

alipay.properties
在这里插入图片描述
启动类

package com.wl.alipay;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;

/**
 * Created by Administrator on 2020/12/9.
 */
@SpringBootApplication(exclude = {
        DataSourceAutoConfiguration.class,
        DataSourceTransactionManagerAutoConfiguration.class,
        HibernateJpaAutoConfiguration.class             //不使用数据库
},scanBasePackages = "com.wl")
public class PayApplication {

    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(PayApplication.class);
        app.setWebApplicationType(WebApplicationType.SERVLET);
        app.run(args);
    }

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

config

package com.wl.alipay.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;

import java.io.IOException;
import java.util.Properties;

/**
 * Created by Administrator on 2020/12/5.
 */
@Configuration
public class AliPayConfig {

    private static final Logger logger = LoggerFactory.getLogger(AliPayConfig.class);

    @Bean
    public Properties aliPayProperties() throws IOException{
        PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
        propertiesFactoryBean.setLocation(new ClassPathResource("/alipay.properties"));
        propertiesFactoryBean.afterPropertiesSet();
        return propertiesFactoryBean.getObject();

    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
package com.wl.alipay.config;

/**
 * Created by Administrator on 2020/12/5.
 */
public class AliPayConstant {

    public static final String appId = "appId";

    public static final String alipayPublicKey = "alipayPublicKey";

    public static final String merchantCertPath = "merchantCertPath";

    public static final String alipayCertPath = "alipayCertPath";

    public static final String alipayRootCertPath = "alipayRootCertPath";

    public static final String gatewayHost = "gatewayHost";

    public static final String protocol = "protocol";

    public static final String signType = "signType";

    public static final String merchantPrivateKey = "merchantPrivateKey";

    public static final String notifyUrl = "notifyUrl";

    public static final String encryptKey = "encryptKey";

    public static final String timeoutExpress = "timeoutExpress";

    public static final String webReturnUrl = "webReturnUrl";


}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

关键的服务类

package com.wl.alipay.service;

//import com.alipay.easysdk.payment.app.models.AlipayTradeAppPayResponse;

import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.Config;
import com.alipay.easysdk.payment.app.models.AlipayTradeAppPayResponse;
import com.alipay.easysdk.payment.common.models.*;
import com.alipay.easysdk.payment.page.models.AlipayTradePagePayResponse;
import com.alipay.easysdk.payment.wap.models.AlipayTradeWapPayResponse;
import com.wl.alipay.config.AliPayConstant;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Properties;

/**
 * Created by Administrator on 2019/8/2.
 */
@Service
public class AliPayService {

    private static final Logger logger = LoggerFactory.getLogger(AliPayService.class);

    private Properties aliPayProperties;

    @Autowired
    public AliPayService(Properties aliPayProperties){

        this.aliPayProperties =aliPayProperties;

        //设置Factory 全局参数
        {
            Config config = new Config();
            config.appId = aliPayProperties.getProperty(AliPayConstant.appId);

            if(StringUtils.isNotBlank(aliPayProperties.getProperty(AliPayConstant.alipayPublicKey))) {
                config.alipayPublicKey = aliPayProperties.getProperty(AliPayConstant.alipayPublicKey);
            }else{
                //如果采用非证书模式,则无需赋值下面的三个证书路径,改为赋值如上的支付宝公钥字符串即可
                String merchantCertPath = aliPayProperties.getProperty(AliPayConstant.merchantCertPath);
                String alipayCertPath = aliPayProperties.getProperty(AliPayConstant.alipayCertPath);
                String alipayRootCertPath = aliPayProperties.getProperty(AliPayConstant.alipayRootCertPath);

                if(StringUtils.isNotBlank(merchantCertPath) && StringUtils.isNotBlank(alipayCertPath)
                        && StringUtils.isNotBlank(alipayRootCertPath)){
                    config.merchantCertPath = merchantCertPath;
                    config.alipayCertPath = merchantCertPath;
                    config.alipayRootCertPath = alipayRootCertPath;
                }else {
                    logger.error("merchantCertPath:{},alipayCertPath:{},alipayRootCertPath:{}"
                            ,merchantCertPath,alipayCertPath,alipayRootCertPath);
                }
            }
            config.gatewayHost = aliPayProperties.getProperty(AliPayConstant.gatewayHost);
            config.protocol = aliPayProperties.getProperty(AliPayConstant.protocol);
            config.signType = aliPayProperties.getProperty(AliPayConstant.signType);
            config.merchantPrivateKey = aliPayProperties.getProperty(AliPayConstant.merchantPrivateKey);
            config.notifyUrl = aliPayProperties.getProperty(AliPayConstant.notifyUrl);
            //可设置AES密钥,调用AES加解密相关接口时需要(可选)
            config.encryptKey = aliPayProperties.getProperty(AliPayConstant.encryptKey);
            Factory.setOptions(config);
        }

    }

    /**
     * 对应 alipay.trade.app.pay 接口
     * 构造交易数据供商户app到支付宝下单
     */
    public AlipayTradeAppPayResponse createAppTradeForm(String subject ,String tradeNo,String totalAmount) throws Exception {

        return Factory.Payment.App()
                //单独设置超时时间 默认15分钟
                .optional("timeout_express",aliPayProperties.getProperty(AliPayConstant.timeoutExpress,"15m"))
                .pay(subject,tradeNo,totalAmount);
    }

    /**
     * 对应alipay.trade.page.pay 接口
     * 构造交易数据供pc端到支付宝下单
     */
    public AlipayTradePagePayResponse createWebTradeForm(String subject ,String tradeNo,String totalAmount,String returnUrl) throws Exception{
        return Factory.Payment.Page()
                //单独设置超时时间 默认15分钟
                .optional("timeout_express",aliPayProperties.getProperty(AliPayConstant.timeoutExpress,"15m"))
                .pay(subject,tradeNo,totalAmount, returnUrl);
    }

    /**
     *  alipay.trade.wap.pay
     *  构造交易数据供wap端到支付宝下单
     */
    public AlipayTradeWapPayResponse createWapTradeForm(String subject , String tradeNo, String totalAmount,String quitUrl, String returnUrl) throws Exception{
        return Factory.Payment.Wap()
                //单独设置超时时间 默认15分钟
                .optional("timeout_express",aliPayProperties.getProperty(AliPayConstant.timeoutExpress,"15m"))
                .pay(subject,tradeNo,totalAmount,quitUrl ,returnUrl);
    }

    /**
     * 对应alipay.trade.query(统一收单线下交易查询)
     */
    public AlipayTradeQueryResponse queryTrade(String tradeNo) throws Exception {

        return Factory.Payment.Common().query(tradeNo);
    }

    /**
     * alipay.trade.cancel
     */
    public AlipayTradeCancelResponse cancelTrade(String tradeNo) throws Exception{
        return Factory.Payment.Common().cancel(tradeNo);
    }

    /**
     * alipay.trade.close(统一收单交易关闭接口)
     */
    public AlipayTradeCloseResponse closeTrade(String tradeNo) throws Exception{
        return Factory.Payment.Common().close(tradeNo);
    }

    /**
     * alipay.trade.refund(统一收单交易退款接口)
     */
    public AlipayTradeRefundResponse refundTrade(String tradeNo,String refundAmount) throws Exception{
        return Factory.Payment.Common().refund(tradeNo,refundAmount);
    }

    /**
     * alipay.trade.fastpay.refund.query(统一收单交易退款查询)
     */
    public AlipayTradeFastpayRefundQueryResponse refundQuery(String tradeNo,String outRequestNo) throws Exception{
        return Factory.Payment.Common().queryRefund(tradeNo,outRequestNo);
    }


}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142

注意以上几个接口只带了几个必要的参数,如果想要设置更多的请求参数,可以使用对应Client的batchOptional或optional方法设置(在下面会讲如何设置复杂的参数)
下面仅以pc端支付测试(使用app端支付测试需要与app开发人员联调)
新建AliPayController

package com.wl.alipay.controller;

import com.alipay.easysdk.payment.page.models.AlipayTradePagePayResponse;
import com.wl.alipay.service.AliPayService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Created by Administrator on 2020/12/9.
 */
@RestController
@RequestMapping("/api/alipay/")
public class AliPayController {

    private AliPayService aliPayService;

    @Autowired
    public AliPayController(AliPayService aliPayService){
        this.aliPayService = aliPayService;
    }

    @RequestMapping("createWebTrade")
    public void createWebTrade(HttpServletResponse response) throws Exception{
        String tradeNo = "20150320011541010101";
        String subject = "iphone11 128G";
        String totalAmount = "0.1";
        String returnUrl =  "http://localhost/api/alipay/webReturnUrl";
        AlipayTradePagePayResponse pagePayResponse = aliPayService.createWebTradeForm(tradeNo,subject,totalAmount,returnUrl);
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().write(pagePayResponse.getBody());// 直接将完整的表单html输出到页面
        response.getWriter().flush();
        response.getWriter().close();
    }

    @RequestMapping(value = "webReturnUrl",method = RequestMethod.GET)
    public Object webTradeReturnUrl(HttpServletRequest request){
        System.out.println(request.getParameterMap());
        return request.getParameterMap();
    }

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

访问http://localhost/api/alipay/createWebTrade即可跳到支付页面
支付成功后同步返回数据到http://localhost/api/alipay/webReturnUrl(支付宝推荐以异步回调通知为准)
启动项目
访问http://localhost/api/alipay/createWebTrade 如下
在这里插入图片描述
使用之前的沙箱帐户名和密码登陆
在这里插入图片描述
输入支付密码并确认付款
最后跳转到后台页面返回数据
在这里插入图片描述
测试成功
上面AliPayService中的参数都是alipay-easysdk中必须的参数,众所周知alipay的参数少则几个多则数十个,显然上面的接口是没法满足我们个性化需求的。下面介绍如何设置可选的参数
还是以alipay.trade.page.pay接口为例,参考alipay文档 我们将所有参数封装到对象里面去
参考alipay-sdk-java jar包中 com.alipay.api.domain包下的AlipayTradePagePayModel类
新建注解

package com.wl.alipay.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Created by Administrator on 2020/12/5.
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface NameInMap {

    /**
     * 支付宝请求参数中可选map中的key 例如  totalAmount  对应  total_amount
     */
    String value();

    /**
     * 数据类型(默认String)
     */
    Class type() default String.class;

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

一个请求对象里面有十几个小的对象实在是多
在这里插入图片描述
这里只贴CreateWebTradeRequest

package com.wl.alipay.domain;


import com.wl.alipay.annotation.NameInMap;

import java.io.Serializable;
import java.util.List;

/**
 * Created by Administrator on 2020/12/8.
 */
public class CreateWebTradeRequest implements Serializable{

    /**
     * 支付成功后同步跳转的页面,是一个http/https开头的字符串(返回同步参数)
     *
     */
    private String returnUrl;

    /**
     * 商户订单号
     * 必填
     */
    private String tradeNo;

    /**
     * 销售产品码,与支付宝签约的产品码名称。注:目前电脑支付场景下仅支持FAST_INSTANT_TRADE_PAY
     * 必填
     */
    @NameInMap(value = "product_code")
    private String productCode;

    /**
     * 订单总金额,单位为元,精确到小数点后两位,取值范围为 [0.01,100000000]。金额不能为0
     * 必填
     */
    private String totalAmount;

    /**
     * 订单标题
     * 必填
     */
    private String subject;

    /**
     * 绝对超时时间,格式为 yyyy-MM-dd HH:mm:ss
     * 可选
     */
    @NameInMap(value = "time_expire")
    private String timeExpire;

    /**
     * 订单包含的商品列表信息,json数组格式,其它说明详见商品明细说明
     * 可选
     */
    @NameInMap(value = "goods_detail",type = List.class)
    private List<GoodsDetail> goodsDetail;

    /**
     * 公用回传参数,如果请求时传递了该参数,则返回给商户时会回传该参数。
     * 支付宝会在异步通知时将该参数原样返回。本参数必须进行 UrlEncode 之后才可以发送给支付宝。
     * 可选
     */
    @NameInMap(value = "passback_params")
    private String passbackParams;

    /**
     * 业务扩展参数 json对象
     * 可选
     */
    @NameInMap(value = "extend_params",type = ExtendParams.class)
    private ExtendParams extendParams;

    /**
     * 商品类型 0-虚拟类商品,1-实物类商品  注:虚拟类商品不支持使用花呗渠道
     * 可选
     */
    @NameInMap(value = "goods_type")
    private String goodsType;

    /**
     * 优惠参数   注:仅与支付宝协商后可用
     * 可选  maxLength 512
     */
    @NameInMap(value = "promo_params")
    private String promoParams;

    /**
     * 描述分账信息,json格式,详见分账参数说明
     */
    @NameInMap(value = "royalty_info",type = RoyaltyInfo.class)
    private RoyaltyInfo royaltyInfo;

    /**
     * 间连受理商户信息体,当前只对特殊银行机构特定场景下使用此字段
     */
    @NameInMap(value = "sub_merchant",type = SubMerchant.class)
    private SubMerchant subMerchant;

    /**
     * 商户原始订单号,最大长度限制32位
     */
    @NameInMap(value = "merchant_order_no")
    private String merchantOrderNo;

    /**
     * 可用渠道,用户只能在指定渠道范围内支付,多个渠道以逗号分割
     * 注,与disable_pay_channels互斥
     * 渠道列表:https://docs.open.alipay.com/common/wifww7
     */
    @NameInMap(value = "enable_pay_channels")
    private String enablePayChannels;

    /**
     * 商户门店编号
     */
    @NameInMap(value = "store_id")
    private String storeId;

    /**
     * 禁用渠道,用户不可用指定渠道支付,多个渠道以逗号分割
     * 注,与enable_pay_channels互斥
     * 渠道列表:https://docs.open.alipay.com/common/wifww7
     */
    @NameInMap(value = "disable_pay_channels")
    private String disablePayChannels;

    /**
     *PC扫码支付的方式,支持前置模式和
     * 跳转模式。
     * 前置模式是将二维码前置到商户
     * 的订单确认页的模式。需要商户在
     * 自己的页面中以 iframe 方式请求
     * 支付宝页面。具体分为以下几种:
     * 0:订单码-简约前置模式,对应 iframe 宽度不能小于600px,高度不能小于300px;
     * 1:订单码-前置模式,对应iframe 宽度不能小于 300px,高度不能小于600px;
     * 3:订单码-迷你前置模式,对应 iframe 宽度不能小于 75px,高度不能小于75px;
     * 4:订单码-可定义宽度的嵌入式二维码,商户可根据需要设定二维码的大小。
     *
     * 跳转模式下,用户的扫码界面是由支付宝生成的,不在商户的域名下。
     * 2:订单码-跳转模式
     */
    @NameInMap(value = "qr_pay_mode")
    private String qrPayMode;

    /**
     * 商户自定义二维码宽度
     * 注:qr_pay_mode=4时该参数生效
     */
    @NameInMap(value = "qrcode_width")
    private String qrcodeWidth;

    /**
     * 描述结算信息,json格式,详见结算参数说明
     */
    @NameInMap(value = "settle_info",type = SettleInfo.class)
    private SettleInfo settleInfo;

    /**
     * 开票信息
     */
    @NameInMap(value = "invoice_info",type = InvoiceInfo.class)
    private InvoiceInfo invoiceInfo;

    /**
     * 签约参数,支付后签约场景使用	与app的SingParams 参数大致相同
     */
    @NameInMap(value = "agreement_sign_params",type = AgreementSignParams.class)
    private AgreementSignParams agreementSignParams;

    /**
     * 请求后页面的集成方式。
     * 取值范围:
     * 1. ALIAPP:支付宝钱包内
     * 2. PCWEB:PC端访问
     * 默认值为PCWEB。
     */
    @NameInMap(value = "integration_type")
    private String integrationType;

    /**
     * 请求来源地址。如果使用ALIAPP的集成方式,用户中途取消支付会返回该地址。
     */
    @NameInMap(value = "request_from_url")
    private String requestFromUrl;

    /**
     * 商户传入业务信息,具体值要和支付宝约定,应用于安全,营销等参数直传场景,格式为json格式
     * https://opendocs.alipay.com/open/204/fx8ebu#%E9%9B%86%E6%88%90%E6%96%B9%E5%BC%8F
     */
    @NameInMap(value = "business_params")
    private String businessParams;

    /**
     * 外部指定买家
     * 可选
     */
    @NameInMap(value = "ext_user_info",type = ExtUserInfo.class)
    private ExtUserInfo extUserInfo;

    public String getReturnUrl() {
        return returnUrl;
    }

    public void setReturnUrl(String returnUrl) {
        this.returnUrl = returnUrl;
    }

    public String getTradeNo() {
        return tradeNo;
    }

    public void setTradeNo(String tradeNo) {
        this.tradeNo = tradeNo;
    }

    public String getProductCode() {
        return productCode;
    }

    public void setProductCode(String productCode) {
        this.productCode = productCode;
    }

    public String getTotalAmount() {
        return totalAmount;
    }

    public void setTotalAmount(String totalAmount) {
        this.totalAmount = totalAmount;
    }

    public String getSubject() {
        return subject;
    }

    public void setSubject(String subject) {
        this.subject = subject;
    }

    public String getTimeExpire() {
        return timeExpire;
    }

    public void setTimeExpire(String timeExpire) {
        this.timeExpire = timeExpire;
    }

    public List<GoodsDetail> getGoodsDetail() {
        return goodsDetail;
    }

    public void setGoodsDetail(List<GoodsDetail> goodsDetail) {
        this.goodsDetail = goodsDetail;
    }

    public String getPassbackParams() {
        return passbackParams;
    }

    public void setPassbackParams(String passbackParams) {
        this.passbackParams = passbackParams;
    }

    public ExtendParams getExtendParams() {
        return extendParams;
    }

    public void setExtendParams(ExtendParams extendParams) {
        this.extendParams = extendParams;
    }

    public String getGoodsType() {
        return goodsType;
    }

    public void setGoodsType(String goodsType) {
        this.goodsType = goodsType;
    }

    public String getPromoParams() {
        return promoParams;
    }

    public void setPromoParams(String promoParams) {
        this.promoParams = promoParams;
    }

    public RoyaltyInfo getRoyaltyInfo() {
        return royaltyInfo;
    }

    public void setRoyaltyInfo(RoyaltyInfo royaltyInfo) {
        this.royaltyInfo = royaltyInfo;
    }

    public SubMerchant getSubMerchant() {
        return subMerchant;
    }

    public void setSubMerchant(SubMerchant subMerchant) {
        this.subMerchant = subMerchant;
    }

    public String getMerchantOrderNo() {
        return merchantOrderNo;
    }

    public void setMerchantOrderNo(String merchantOrderNo) {
        this.merchantOrderNo = merchantOrderNo;
    }

    public String getEnablePayChannels() {
        return enablePayChannels;
    }

    public void setEnablePayChannels(String enablePayChannels) {
        this.enablePayChannels = enablePayChannels;
    }

    public String getStoreId() {
        return storeId;
    }

    public void setStoreId(String storeId) {
        this.storeId = storeId;
    }

    public String getDisablePayChannels() {
        return disablePayChannels;
    }

    public void setDisablePayChannels(String disablePayChannels) {
        this.disablePayChannels = disablePayChannels;
    }

    public String getQrPayMode() {
        return qrPayMode;
    }

    public void setQrPayMode(String qrPayMode) {
        this.qrPayMode = qrPayMode;
    }

    public String getQrcodeWidth() {
        return qrcodeWidth;
    }

    public void setQrcodeWidth(String qrcodeWidth) {
        this.qrcodeWidth = qrcodeWidth;
    }

    public SettleInfo getSettleInfo() {
        return settleInfo;
    }

    public void setSettleInfo(SettleInfo settleInfo) {
        this.settleInfo = settleInfo;
    }

    public InvoiceInfo getInvoiceInfo() {
        return invoiceInfo;
    }

    public void setInvoiceInfo(InvoiceInfo invoiceInfo) {
        this.invoiceInfo = invoiceInfo;
    }

    public AgreementSignParams getAgreementSignParams() {
        return agreementSignParams;
    }

    public void setAgreementSignParams(AgreementSignParams agreementSignParams) {
        this.agreementSignParams = agreementSignParams;
    }

    public String getIntegrationType() {
        return integrationType;
    }

    public void setIntegrationType(String integrationType) {
        this.integrationType = integrationType;
    }

    public String getRequestFromUrl() {
        return requestFromUrl;
    }

    public void setRequestFromUrl(String requestFromUrl) {
        this.requestFromUrl = requestFromUrl;
    }

    public String getBusinessParams() {
        return businessParams;
    }

    public void setBusinessParams(String businessParams) {
        this.businessParams = businessParams;
    }

    public ExtUserInfo getExtUserInfo() {
        return extUserInfo;
    }

    public void setExtUserInfo(ExtUserInfo extUserInfo) {
        this.extUserInfo = extUserInfo;
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
  • 397
  • 398
  • 399
  • 400
  • 401
  • 402
  • 403
  • 404
  • 405
  • 406
  • 407
  • 408
  • 409

在这里插入图片描述
NameInMap中的value就是对应文档的字段
在这里插入图片描述
如果是List集合 NameInMap中需要设置type=List.class

在这里插入图片描述
如果是复杂对象需要设置type=Class.class

将对象转换为Map<String,Object>的集合的工具类(Map中的key 就是上面NameInMap中value的值)

package com.wl.alipay.util;

import com.wl.alipay.annotation.NameInMap;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Administrator on 2020/12/5.
 */
public class AliPayUtil {

    public static Map<String,Object> genBatchOptionals(Object request) throws Exception{
        Map<String,Object> optionals = new HashMap<>();
        Class<?> clazz = request.getClass();
        convertMap(optionals,clazz,request);
        return optionals;
    }

    //只有特定类型的clazz 才能调用此方法,这里没有校验类型
    private static void convertMap(Map<String,Object> options,Class clazz,Object target) throws Exception{
        //todo   缓存field
        Field[] fields = clazz.getDeclaredFields();
        for(Field field : fields){
            NameInMap nameInMap = field.getAnnotation(NameInMap.class);
            if(nameInMap != null){
                field.setAccessible(true);
                String key = nameInMap.value();
                Object value = field.get(target);
                if(value != null) {
                    if (nameInMap.type() == String.class) {
                        options.put(key, value);
                    } else if (nameInMap.type() == List.class) {     //集合
                        List<Object> values = (List<Object>) value;   //
                        List<Object> list = new ArrayList<>();
                        options.put(key,list);
                        for(Object o : values){
                            if(isBasicType(o)){                       //基本数据类型或者String
                                list.add(o);
                            }else{
                                Map<String, Object> innerOptions = new HashMap<>();
                                list.add(innerOptions);
                                convertMap(innerOptions, o.getClass(), o);
                            }
                        }
                    } else {
                        //对象
                        Map<String, Object> innerOptions = new HashMap<>();
                        options.put(key, innerOptions);
                        convertMap(innerOptions, nameInMap.type(), value);
                    }
                }
            }
        }
    }

    //String 也算
    private static boolean isBasicType(Object o) {
        return o instanceof String || o instanceof Character || o instanceof Integer || o instanceof Long || o instanceof Byte
                || o instanceof Double || o instanceof Float || o instanceof Boolean;
    }

    
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68

修改上面createWebTradeForm接口如下

/**
     * 对应alipay.trade.page.pay 接口
     * 构造交易数据供pc端到支付宝下单
     */
    public AlipayTradePagePayResponse createWebTradeForm(CreateWebTradeRequest request) throws Exception{
        return Factory.Payment.Page().batchOptional(AliPayUtil.genBatchOptionals(request))
                //单独设置超时时间 默认15分钟
                .optional("timeout_express",aliPayProperties.getProperty(AliPayConstant.timeoutExpress,"15m"))
                .pay(request.getSubject(),request.getTradeNo(),request.getTotalAmount(), 
                        "http://localhost/api/alipay/webReturnUrl");
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

batchOptional就是批量设置请求可选参数的方法
测试genBatchOptionals方法
测试数据

package com.wl.alipay;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.wl.alipay.domain.*;
import com.wl.alipay.util.AliPayUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by Administrator on 2020/12/10.
 */
public class Test {

    public static void main(String[] args) throws Exception{
        CreateWebTradeRequest request = new CreateWebTradeRequest();
        request.setTimeExpire("2016-12-31 10:05");
        {
            ExtendParams extendParams = new ExtendParams();
            extendParams.setSysServiceProviderId("2088511833207846");
            extendParams.setHbFqSellerPercent("100");
            extendParams.setHbFqNum("3");
            extendParams.setCardType("S0JP0000");
            request.setExtendParams(extendParams);
        }
        {
            SettleInfo settleInfo = new SettleInfo();
            settleInfo.setSettlePeriodTime("7d");
            List<SettleDetailInfo> list = new ArrayList<>();
            SettleDetailInfo detailInfo = new SettleDetailInfo();
            detailInfo.setAmount("0.1");
            detailInfo.setSettleEntityId("2088****;st_001");
            detailInfo.setTransInType("cardAliasNo");
            detailInfo.setTransIn("A0001");
            list.add(detailInfo);
            settleInfo.setSettleDetailInfos(list);
            request.setSettleInfo(settleInfo);
        }
        request.setSubject("iphone11");

        request.setMerchantOrderNo("20161008001");
        {
            InvoiceInfo invoiceInfo = new InvoiceInfo();
            invoiceInfo.setDetails("invoiceInfo");
            {
                InvoiceKeyInfo keyInfo = new InvoiceKeyInfo();
                keyInfo.setInvoiceMerchantName("merchantName");
                keyInfo.setTaxNum("10");
                keyInfo.setSupportInvoice(true);
                invoiceInfo.setKeyInfo(keyInfo);
            }
            request.setInvoiceInfo(invoiceInfo);
        }
        {
            RoyaltyInfo royaltyInfo = new RoyaltyInfo();
            royaltyInfo.setRoyaltyType("ROYALTY");
            {
                List<RoyaltyDetailInfos> list = new ArrayList<>();
                {
                    RoyaltyDetailInfos infos = new RoyaltyDetailInfos();
                    infos.setAmount("0.1");
                    infos.setSerialNo(1L);
                    infos.setTransIn("wwwwwww");
                    list.add(infos);
                    list.add(infos);
                }
                royaltyInfo.setRoyaltyDetailInfos(list);
            }
            request.setRoyaltyInfo(royaltyInfo);
        }
        {
            List<GoodsDetail> list = new ArrayList<>();
            GoodsDetail goodsDetail = new GoodsDetail();
            goodsDetail.setPrice("15.15");
            goodsDetail.setGoodsName("iphone11");
            list.add(goodsDetail);
            list.add(goodsDetail);
            request.setGoodsDetail(list);
        }
        Map<String,Object> map = AliPayUtil.genBatchOptionals(request);
        System.out.println(map);
        System.out.println(new ObjectMapper().writeValueAsString(map));
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85

输出数据(转换为json)

{
	"royalty_info": {
		"royalty_type": "ROYALTY",
		"royalty_detail_infos": [{
			"amount": "0.1",
			"trans_in": "wwwwwww",
			"serial_no": 1
		}, {
			"amount": "0.1",
			"trans_in": "wwwwwww",
			"serial_no": 1
		}]
	},
	"invoice_info": {
		"key_info": {
			"tax_num": "10",
			"is_support_invoice": true,
			"invoice_merchant_name": "merchantName"
		},
		"details": "invoiceInfo"
	},
	"time_expire": "2016-12-31 10:05",
	"extend_params": {
		"sys_service_provider_id": "2088511833207847",
		"hb_fq_seller_percent": "100",
		"hb_fq_num": "3",
		"card_type": "S0JP0000"
	},
	"settle_info": {
		"settle_period_time": "7d",
		"settle_detail_info": [{
			"amount": "0.1",
			"trans_in": "A0001",
			"settle_entity_id": "2088****;st_001",
			"trans_in_type": "cardAliasNo"
		}]
	},
	"goods_detail": [{
		"goods_name": "iphone11",
		"price": "15.15"
	}, {
		"goods_name": "iphone11",
		"price": "15.15"
	}],
	"merchant_order_no": "20161008001"
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

如果嫌使用对象麻烦,可以直接使用封装好的Map

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/在线问答5/article/detail/742807
推荐阅读
相关标签
  

闽ICP备14008679号