支付宝支付easysdk支付宝沙箱支付demo Java easysdk支付

java支付宝支付easysdk支付宝沙箱支付demo

文章目录

  • java支付宝支付easysdk支付宝沙箱支付demo
  • 总结
    • 1、下载密钥工具生成应用公钥、应用私钥
    • 2、异步回调地址需要公网地址,可以下载内网穿透工具natapp、花生壳等
  • 一、支付宝支付文档地址
  • 二、开发前的准备
    • 1.沙箱支付需要的配置情况
    • 2.沙箱找appid
    • 3.应用私钥、支付宝公钥
    • 3.内网穿透NATAPP下载(供异步通知等用)
  • 三 、Java完整代码如下
    • 1.Maven依赖
    • 2.工程目录
    • 3.AlipayConfig
    • 4.controller
    • 5.service
    • 6.serviceImpl
    • 最后丢个前端页面


总结

1、下载密钥工具生成应用公钥、应用私钥

应用私钥放代码里 merPrivateKey
应用公钥放沙箱保存得到支付宝公钥->支付宝公钥也是放代码里 alipayPublicKey

2、异步回调地址需要公网地址,可以下载内网穿透工具natapp、花生壳等

https://natapp.cn/

一、支付宝支付文档地址

https://opendocs.alipay.com/apis/00y8k9

支付宝支付easysdk支付宝沙箱支付demo Java easysdk支付_第1张图片

二、开发前的准备

1.沙箱支付需要的配置情况

alipay:
  appId: "2021000116662953"                     #沙箱的appid
  merPrivateKey: "MIIEvAIBADxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=" #商家应用私钥
  alipayPublicKey: "MIIBIjANBgxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"  #支付宝公钥
  gateway: "openapi.alipaydev.com"   #沙箱网关固定
  notifyUrl: "http://edrutb.natappfree.cc/alipay/notify"  #异步通知回调,用于用户支付成功后,支付宝调用的接口,会给我们返回订单的支付情况,以此修改我们的订单状态,或积分等等
  returnUrl: "http://edrutb.natappfree.cc/return_url.html" #这个地址配置是用来前端支付成功后的跳转地址
  errorUrl: "http://localhost:8720/error_url.html"  

支付宝支付easysdk支付宝沙箱支付demo Java easysdk支付_第2张图片回调接口如下:可在这里进行业务逻辑处理,支付状态的改变,积分等等

    /**
     * @param request: 请求
     * @return java.lang.String
     * @description: 支付宝异步回调
     */
    @PostMapping("/notify")
    public String notify(HttpServletRequest request) throws Exception {
        log.info("=========支付宝异步回调========");
        if ("TRADE_SUCCESS".equals(request.getParameter("trade_status"))) {
            Map<String, String> params = new HashMap<>();
            Map<String, String[]> requestParams = request.getParameterMap();
            for (String name : requestParams.keySet()) {
                params.put(name, request.getParameter(name));
                log.info(name + " = " + request.getParameter(name));
            }
            // 支付宝验签
            if (Factory.Payment.Common().verifyNotify(params)) {
                log.info("交易名称: " + params.get("subject"));
                log.info("交易状态: " + params.get("trade_status"));
                log.info("支付宝交易凭证号: " + params.get("trade_no"));
                log.info("商户订单号: " + params.get("out_trade_no"));
                log.info("交易金额: " + params.get("total_amount"));
                log.info("买家在支付宝唯一id: " + params.get("buyer_id"));
                log.info("买家付款时间: " + params.get("gmt_payment"));
                log.info("买家付款金额: " + params.get("buyer_pay_amount"));
            }
            return "success";
        }
        return "failed";
    }

2.沙箱找appid

支付宝支付easysdk支付宝沙箱支付demo Java easysdk支付_第3张图片支付宝支付easysdk支付宝沙箱支付demo Java easysdk支付_第4张图片如上找到appid
appId: “2021000116662953” #沙箱的appid

3.应用私钥、支付宝公钥

merPrivateKey: “MIIEvAIBADxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=” #商家应用私钥
alipayPublicKey: “MIIBIjANBgkqhkiG9xxxxxxxxxxxxxxxxxxxxxxxxxxxB” #支付宝公钥
支付宝支付easysdk支付宝沙箱支付demo Java easysdk支付_第5张图片支付宝支付easysdk支付宝沙箱支付demo Java easysdk支付_第6张图片下载密钥工具https://ideservice.alipay.com/ide/getPluginUrl.htm?clientType=assistant&platform=win&channelType=WEB
支付宝支付easysdk支付宝沙箱支付demo Java easysdk支付_第7张图片支付宝支付easysdk支付宝沙箱支付demo Java easysdk支付_第8张图片保存后得到支付宝公钥
支付宝支付easysdk支付宝沙箱支付demo Java easysdk支付_第9张图片

3.内网穿透NATAPP下载(供异步通知等用)

notifyUrl: “http://edrutb.natappfree.cc/alipay/notify”
natapp官网: https://natapp.cn/
注册实名后搞个免费隧道,注意设置端口号要与springboot程序启动的一致,或者用nginx监听转发
支付宝支付easysdk支付宝沙箱支付demo Java easysdk支付_第10张图片客户端下载后,在用一目录搞个config.ini配置文件,把上面复制的token放上去
支付宝支付easysdk支付宝沙箱支付demo Java easysdk支付_第11张图片

#将本文件放置于natapp同级目录 程序将读取 [default] 段
#在命令行参数模式如 natapp -authtoken=xxx 等相同参数将会覆盖掉此配置
#命令行参数 -config= 可以指定任意config.ini文件
[default]
authtoken=                    #对应一条隧道的authtoken
clienttoken=                    #对应客户端的clienttoken,将会忽略authtoken,若无请留空,
log=none                        #log 日志文件,可指定本地文件, none=不做记录,stdout=直接屏幕输出 ,默认为none
loglevel=ERROR                  #日志等级 DEBUG, INFO, WARNING, ERROR 默认为 DEBUG
http_proxy=                     #代理设置  非代理上网用户请务必留空

双击exe运行得到对应的公网域名,放入代码的配置文件即可

三 、Java完整代码如下

1.Maven依赖

			<dependency>
                <groupId>com.alipay.sdk</groupId>
                <artifactId>alipay-easysdk</artifactId>
                <version>2.1.0</version>
            </dependency>

2.工程目录

支付宝支付easysdk支付宝沙箱支付demo Java easysdk支付_第12张图片

3.AlipayConfig

alipay:
  appId: "2021000116662953"
  merPrivateKey: "MIIEvgIxxxxxxxxxxxxxxxxxxx"
  alipayPublicKey: "MIIBIjANBgxxxxxxxxxxxxxxxxxxxxxxx"
  gateway: "openapi.alipaydev.com"
  notifyUrl: "http://edrutb.natappfree.cc/alipay/notify"
  returnUrl: "http://localhost:8720/return_url.html"
  errorUrl: "http://localhost:8720/error_url.html"
/**
 * @author kamu
 * @date 2020-12-09 15:38
 */
@Log4j2
@Component
public class AlipayConfig implements ApplicationRunner {

    @Value("${alipay.appId}")
    private String appId;

    @Value("${alipay.merPrivateKey}")
    private String privateKey;

    @Value("${alipay.alipayPublicKey}")
    private String publicKey;

    @Value("${alipay.gateway}")
    private String gateway;

    @Value("${alipay.notifyUrl}")
    private String notifyUrl;

    @Override
    public void run(ApplicationArguments args){
        Factory.setOptions(getOptions());
        log.warn("==================================支付宝SDK初始化完成");
    }

    private Config getOptions() {
        Config config = new Config();
        config.protocol = "https";
        config.gatewayHost = this.gateway;
        config.signType = "RSA2";
        config.appId = this.appId;
        config.merchantPrivateKey = this.privateKey;
        config.alipayPublicKey = this.publicKey;
        config.notifyUrl = notifyUrl;
        return config;
    }

}

4.controller

/**
 * @author kamu
 * @date 2020-12-08 15:26
 */
@Log4j2
@Api(tags = "alipay")
@RestController
@RequestMapping("/alipay")
public class AliPayController {

    private AliPayService alipayService;

    @Autowired
    public void AlipayController(AliPayService alipayService) {
        this.alipayService = alipayService;
    }

    /**
     * app支付
     */
    @PostMapping("/app")
    public String app() {
        String subject = "测试支付";
        String total = "0.03";
        return alipayService.app(subject, total);
    }

    /**
     * 支付宝电脑网页支付
     */
    @PostMapping("/page")
    public String page() {
        String subject = "page";
        String total = "0.02";
        return alipayService.page(subject, total);
    }

    /**
     * 支付宝手机网页支付
     */
    @PostMapping("/wap")
    public String wap() {
        String subject = "wap";
        String total = "0.01";
        return alipayService.wap(subject, total);
    }

    /**
     * 查询交易
     */
    @GetMapping("/getTrade/{outTradeNo}")
    public String getTrade(@PathVariable String outTradeNo) {
        return alipayService.getTrade(outTradeNo);
    }

    /**
     * 支付宝异步回调
     */
    @PostMapping("/notify")
    public String notify(HttpServletRequest request) throws Exception {
        log.info("=========支付宝异步回调========");
        if ("TRADE_SUCCESS".equals(request.getParameter("trade_status"))) {
            Map<String, String> params = new HashMap<>();
            Map<String, String[]> requestParams = request.getParameterMap();
            for (String name : requestParams.keySet()) {
                params.put(name, request.getParameter(name));
                log.info(name + " = " + request.getParameter(name));
            }
            // 支付宝验签
            if (Factory.Payment.Common().verifyNotify(params)) {
                log.info("交易名称: " + params.get("subject"));
                log.info("交易状态: " + params.get("trade_status"));
                log.info("支付宝交易凭证号: " + params.get("trade_no"));
                log.info("商户订单号: " + params.get("out_trade_no"));
                log.info("交易金额: " + params.get("total_amount"));
                log.info("买家在支付宝唯一id: " + params.get("buyer_id"));
                log.info("买家付款时间: " + params.get("gmt_payment"));
                log.info("买家付款金额: " + params.get("buyer_pay_amount"));
            }
            return "success";
        }
        return "failed";
    }

    /**
     * 支付宝退款
     */
    @PostMapping("/refund")
    public String refund(String outTradeNo, String refundAmount) {
        return alipayService.refund(outTradeNo, refundAmount);
    }

    /**
     * 下载账单
     */
    @PostMapping("/downloadBill")
    public String downloadBill(String billType, String billDate) {
        billType = "trade";
        billDate = "2020-11";
        return alipayService.downloadBill(billType, billDate);
    }

}

5.service


/**
 * @author kamu
 * @date 2020-12-09 14:36
 */
public interface AliPayService {

    /**
     *  支付宝电脑网页支付
     */
    String page(String subject, String total);

    /**
     *  支付宝手机网页支付
     */
    String wap(String subject, String total);

    /**
     * 支付宝退款
     */
    String refund(String outTradeNo, String refundAmount);

    /**
     * app支付
     */
    String app(String subject, String total);

    String getTrade(String outTradeNo);

    String downloadBill(String billType, String billDate);
}

6.serviceImpl

/**
 * @author kamu
 * @date 2020-12-09 14:37
 */
@Log4j2
@Service
public class AliPayServiceImpl implements AliPayService {

    // 支付成功后要跳转的页面
    @Value("${alipay.returnUrl}")
    private String returnUrl;

    @Value("${alipay.errorUrl}")
    private String errorUrl;

    @Override
    public String page(String subject, String total) {
        try {
            String orderId = getOrderId();
            AlipayTradePagePayResponse response = Factory.Payment
                    // 选择电脑网站
                    .Page()
                    // 调用支付方法(订单名称, 商家订单号, 金额, 成功页面)
                    .pay(subject + orderId, orderId, total, returnUrl);

            return response.body;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    public String wap(String subject, String total) {
        try {
            String orderId = getOrderId();
            AlipayTradeWapPayResponse response = Factory.Payment
                    //选择手机网站
                    .Wap()
                    // 调用支付方法(订单名称, 商家订单号, 金额, 中途退出页面, 成功页面)
                    .pay(subject + orderId, orderId, total, errorUrl, returnUrl);

            return response.body;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "付款失败";
    }

    @Override
    public String refund(String outTradeNo, String refundAmount) {
        try {
            AlipayTradeRefundResponse response = Factory.Payment
                    .Common()
                    // 调用交易退款(商家订单号, 退款金额)
                    .refund(outTradeNo, refundAmount);
            if ("Success".equals(response.getMsg())) {
                return "退款成功";
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "退款失败";
    }

    @Override
    public String app(String subject, String total) {
        try {
            AlipayTradeAppPayResponse response = Factory.Payment.App().pay(subject, getOrderId(), total);
            return response.body;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public String getTrade(String outTradeNo) {
        AlipayTradeQueryResponse query = null;
        try {
            query = Factory.Payment.Common().query(outTradeNo);
            String httpBody = query.getHttpBody();
            if ("10000".equals(query.getCode()))
                return httpBody;
            else
                return query.getMsg() + query.getSubMsg();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "failed";
    }

    @Override
    public String downloadBill(String billType, String billDate) {
        return "";
    }

    public String getOrderId() {
        String idStr = IdWorker.getIdStr().substring(15);
        log.info("========================  " + idStr);
        return idStr;
    }
}

最后丢个前端页面

支付宝支付easysdk支付宝沙箱支付demo Java easysdk支付_第13张图片
引用的js文件自己搞,上传不了

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>测试支付</title>
    <script src="./js/vue.min.js"></script>
    <script src="./js/axios.min.js"></script>
    <script src="./js/vue-resource.min.js"></script>
    <!-- 引入样式 -->
    <link rel="stylesheet" href="https://unpkg.com/[email protected]/lib/theme-chalk/index.css">
    <!-- 引入组件库 -->
    <script src="https://unpkg.com/[email protected]/lib/index.js"></script>
    <script src="https://cdn.staticfile.org/jquery/3.4.0/jquery.min.js"></script>
    <script src="https://cdn.staticfile.org/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>
    <link rel="stylesheet" href="./css/bootstrap.min.css">
    <link rel="stylesheet" href="./css/style.css">
</head>
<body>
<div id="app">
    <h2>测试支付</h2>

    <form enctype="multipart/form-data" action="/alipay/page" method="post">
        <button type="submit">电脑确认支付</button>
    </form>
    <form enctype="multipart/form-data" action="/alipay/wap" method="post">
        <button type="submit">手机确认支付</button>
    </form>
    <form enctype="multipart/form-data" action="/alipay/app" method="post">
        <button type="submit">app确认支付</button>
    </form>

    <el-button type="primary" @click="downloadBill">账单</el-button>

    <!--搜索条 start-->
    <div class="searchBar">
        <div class="form-group">
            <label>单号:</label>
            <label>
                <input type="text" class="form-control" v-model="outTradeNo"
                       placeholder="单号">
            </label>
        </div>
        <el-button type="primary" @click="filterBtn">交易查询</el-button>
        <el-button type="info" @click="clearSearch">重 置</el-button>
    </div>
    <!--搜索条 end-->

    <div class="orderInfo">
        <dl class="dl-horizontal">
            <dt>buyer_logon_id</dt>
            <dd>{{orderList.buyer_logon_id}}</dd>
        </dl>
        <dl class="dl-horizontal">
            <dt>buyer_pay_amount</dt>
            <dd>{{orderList.total_amount}}</dd>
        </dl>
        <dl class="dl-horizontal">
            <dt>buyer_user_id</dt>
            <dd>{{orderList.buyer_user_id}}</dd>
        </dl>
        <dl class="dl-horizontal">
            <dt>out_trade_no</dt>
            <dd>{{orderList.out_trade_no}}</dd>
        </dl>
        <dl class="dl-horizontal">
            <dt>trade_no</dt>
            <dd>{{orderList.trade_no}}</dd>
        </dl>
        <dl class="dl-horizontal">
            <dt>trade_status</dt>
            <dd>{{orderList.trade_status}}</dd>
        </dl>
    </div>

    <!-- <div class="cantainer">
         <el-table style="width: 100%;"
                   :data="orderList"
                   :row-class-name="tableRowClassName"
                   :header-cell-style="{background:'#eef1f6',color:'#606266'}"
         >
             <el-table-column label="buyer_logon_id" prop="buyer_logon_id" width="200">
             </el-table-column>
             <el-table-column label="buyer_pay_amount" prop="buyer_pay_amount" width="200">
             </el-table-column>
             <el-table-column label="buyer_user_id" prop="buyer_user_id" width="200">
             </el-table-column>
             <el-table-column label="out_trade_no" prop="out_trade_no" width="200">
             </el-table-column>
             <el-table-column label="total_amount" prop="total_amount" width="200">
             </el-table-column>
             <el-table-column label="trade_no" prop="trade_no" width="200">
             </el-table-column>
             <el-table-column label="trade_status" prop="trade_status" width="200">
             </el-table-column>
                      <el-table-column label="操作">
                             <template slot-scope="scope">
                                 <el-popover
                                         placement="right"
                                         width="100%"
                                         trigger="click">
                                     <el-table :data="orderLotList" :row-class-name="tableOrderLotList"
                                               :header-cell-style="{background:'#eef1f6',color:'#606266'}"
                                               :row-style="{background:'#eef1f6',color:'#606266'}"
                                     >
                                         <el-table-column width="160" property="productionTime"
                                                          label="生产日期"></el-table-column>
                                         <el-table-column width="160" property="lotNo" label="批次号"></el-table-column>
                                         <el-table-column width="160" property="expiredTime"
                                                          label="有效期"></el-table-column>
                                         <el-table-column width="160" property="qty" label="数量"></el-table-column>
                                         <el-table-column width="160" property="price" label="单价"></el-table-column>
                                         <el-table-column width="160" property="purchasePrice"
                                                          label="采购价"></el-table-column>
                                     </el-table>
                                     <el-button type="primary" slot="reference" @click="getLotList(scope.row)">批号详情
                                     </el-button>
                                 </el-popover>
                             </template>
                         </el-table-column>&ndash;&gt;
         </el-table>
            <el-pagination
                    background
                    @size-change="handleSizeChange"
                    @current-change="handleCurrentChange"
                    :current-page="searchBarParams.pageIndex"
                    :page-sizes="[10, 20, 50, 80, 100]"
                    :page-size="searchBarParams.pageSize"
                    layout="total, sizes, prev, pager, next, jumper"
                    :total="totalCount">
            </el-pagination>
     </div>-->
</div>
</body>
<script type="text/javascript">
    window.onload = function () {
        var api = ''
        var app = new Vue({
            el: '#app',
            data: {
                outTradeNo: '2',
                orderList: [],//列表数据
            },
            methods: {
                clearSearch() {
                    this.outTradeNo = '';
                },
                filterBtn() {
                    this.getorderList(this.outTradeNo)
                },
                getorderList(outTradeNo) {
                    axios({
                        method: 'get',
                        url: '/alipay/getTrade/'+outTradeNo
                    }).then(res => {
                        console.log(res)
                        this.orderList = res.data.alipay_trade_query_response
                        console.log("==========================")
                        console.log(this.orderList)
                        console.log("==========================")
                    }).catch(error => {
                        console.log('请求失败 ', error)
                    })
                },
                tableRowClassName({row, rowIndex}) {
                    if (rowIndex % 2 === 0) {
                        return 'warning-row';
                    } else if (rowIndex % 2 === 1) {
                        return 'success-row';
                    }
                    return '';
                },
                downloadBill() {
                    axios({
                        method: 'post',
                        url: '/alipay/downloadBill',
                        data: {billType: 'billType', billDate: 'billDate'}
                    }).then(res => {
                        console.log(res)
                    }).catch(error => {
                        console.log('请求失败 ', error)
                    })
                }
            },
            created() {
                // this.getorderList(this.outTradeNo)
            }
        })
    }
</script>
</html>

你可能感兴趣的:(支付,支付,支付宝支付easysdk,支付宝沙箱支付,Java,easysdk支付)