zoukankan      html  css  js  c++  java
  • Java第三方支付接入案例(支付宝)

    原文:https://docs.open.alipay.com/291/105971

    开源项目链接

    Kitty 开源权限管理系统

    项目地址:https://gitee.com/liuge1988/kitty

    演示地址:http://139.196.87.48:9002/kitty

    用户名:admin 密码:admin

    注册沙箱账号

    到蚂蚁金服注册开发者账号,注册地址:https://open.alipay.com,用你的 支付宝 账号扫码登录,完善个人信息,选择服务类型。

    根据情况选择接入方式,我们这里选择自研开发者,如果已经注册过的省略。

    选择 开发者中心 --> 研发服务 --> 沙箱,进入沙箱管理界面。

    进入沙箱,第一次需要填写信息,记下appId,公钥设置处需要把下面步骤生成的公钥设置到这里。

    生成公私秘钥

    本人linux系统用不了支付宝官方的秘钥生成器,用了ubuntu系统自带的openssl生成了秘钥 https://i.cnblogs.com/EditPosts.aspx?postid=11044089

    登录官方地址: https://docs.open.alipay.com/291/105971,进入秘钥生成页面。

    打开下载的工具,运行程序,选择 JAVA 2048 方式,点击生成秘钥。

    把此处生成的公钥复制设置到沙箱环境,就是上面的设置公钥配置,然后把公私秘钥保存起来,以备后用。

    创建项目

    登录 https://start.spring.io/,输入项目信息,生成 Spring Boot 项目并下载到本地。

    使用开发工具导入项目,我们这里使用的是 Eclipse ,导入和清理后项目结构如下图。

    添加依赖

    添加项目依赖,主要是引入 alipay-sdk-java,提供支付宝支付支持。

    pom.xml

     <!-- alipay -->
            <dependency>    
                <groupId>com.alipay.sdk</groupId>
                <artifactId>alipay-sdk-java</artifactId>
                <version>3.1.0</version>
            </dependency>
      <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.58</version>
    </dependency>

    配置文件

    在 resources 目录下添加一个 alipay.properties 文件,用于写入支付宝配置信息。

    alipay.properties

    # 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
    appId:2016092900622443
    # 商户私钥,您的PKCS8格式RSA2私钥
    privateKey:M.......秘钥不便显示.......9vdkUTw=
    # 支付宝公钥,查看地址:https://openhome.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
    publicKey:MI.......秘钥不便显示.......AB
    # 服务器异步通知页面路径需http://格式的完整路径,不能加?id=123这类自定义参数 
    notifyUrl: http://localhost/error.html
    # 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数 
    returnUrl: http://localhost/shop/sccess.html
    # 签名方式
    signType: RSA2
    # 字符编码格式
    charset: utf-8
    # 支付宝网关
    gatewayUrl: https://openapi.alipaydev.com/gateway.do
    # 支付宝网关
    logPath: "/home/"

    增加一个 PropertiesListener 监听器用于在应用启动时加载配置文件属性。

    PropertiesListener.java

    package com.feilong.shop.config;
    
    import org.springframework.context.event.ContextRefreshedEvent;
    import org.springframework.context.event.ContextStartedEvent;
    import org.springframework.context.ApplicationListener;
    import org.springframework.stereotype.Component;
    
    
    
    /**
     * 配置文件监听器,用来加载自定义配置文件
     * @author Louis
     * @date Dec 12, 2018
     */
    @Component
    public class PropertiesListener implements ApplicationListener<ContextRefreshedEvent> {
    
        @Override
        public void onApplicationEvent(ContextRefreshedEvent event) {
            AlipayProperties.loadProperties();
        }
    }

    上面的监听器加载属性,是通过具体的属性加载器加载的,比如支付宝支付属性加载类如下。

    AlipayProperties.java

    package com.feilong.shop.config;
    
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Properties;
    
    import org.springframework.beans.factory.config.PropertiesFactoryBean;
    import org.springframework.core.io.Resource;
    import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
    import org.springframework.stereotype.Component;
    
    /**
     * 应用启动加载文件
     * @author Louis
     * @date Dec 12, 2018
     */
    @Component
    public class AlipayProperties {
        
        public static final String APP_ID = "appId";
        public static final String PRIVARY_KEY = "privateKey";
        public static final String PUBLIC_KEY = "publicKey";
        public static final String NOTIFY_URL = "notifyUrl";
        public static final String RETURN_URL = "returnUrl";
        public static final String SIGN_TYPE = "signType";
        public static final String CHARSET = "charset";
        public static final String GATEWAY_URL = "gatewayUrl";
        public static final String LOG_PATH = "logPath";
        
        /**
         * 保存加载配置参数
         */
        private static Map<String, String> propertiesMap = new HashMap<String, String>();
    
        /**
         * 加载属性
         */
        public static void loadProperties() {
            // 获得PathMatchingResourcePatternResolver对象
            PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
            try {
                // 加载resource文件(也可以加载resources)
                Resource resources = resolver.getResource("classpath:alipay.properties");
                PropertiesFactoryBean config = new PropertiesFactoryBean();
                config.setLocation(resources);
                config.afterPropertiesSet();
                Properties prop = config.getObject();
                // 循环遍历所有得键值对并且存入集合
                for (String key : prop.stringPropertyNames()) {
                    propertiesMap.put(key, (String) prop.get(key));
                }
            } catch (Exception e) {
                new Exception("配置文件加载失败");
            }
        }
        
        /**
         * 获取配置参数值
         * @param key
         * @return
         */
        public static String getKey(String key) {
            return propertiesMap.get(key);
        }
    
        public static String getAppId() {
            return propertiesMap.get(APP_ID);
        }
    
        public static String getPrivateKey() {
            return propertiesMap.get(PRIVARY_KEY);
        }
    
        public static String getPublicKey() {
            return propertiesMap.get(PUBLIC_KEY);
        }
    
        public static String getNotifyUrl() {
            return propertiesMap.get(NOTIFY_URL);
        }
    
        public static String getReturnUrl() {
            return propertiesMap.get(RETURN_URL);
        }
    
        public static String getSignType() {
            return propertiesMap.get(SIGN_TYPE);
        }
    
        public static String getCharset() {
            return propertiesMap.get(CHARSET);
        }
    
        public static String getGatewayUrl() {
            return propertiesMap.get(GATEWAY_URL);
        }
    
        public static String getLogPath() {
            return propertiesMap.get(LOG_PATH);
        }
        
    }

    支付宝支付接口封装

    接口调用参数封装对象如下。

    AlipayBean.java

    package com.feilong.shop.entity;
    
    import org.springframework.stereotype.Component;
    
    /**
     * 支付实体对象
     * 根据支付宝接口协议,其中的属性名,必须使用下划线,不能修改
     * @author Louis
     * @date Dec 12, 2018
     */
    @Component
    public class AlipayBean {
        
        /**
         * 商户订单号,必填
         * 
         */
        private String out_trade_no;
        /**
         * 订单名称,必填
         */
        private String subject;
        /**
         * 付款金额,必填
         * 根据支付宝接口协议,必须使用下划线
         */
        private String total_amount;
        /**
         * 商品描述,可空
         */
        private String body;
        /**
         * 超时时间参数
         */
        private String timeout_express= "10m";
        /**
         * 产品编号
         */
        private String product_code= "FAST_INSTANT_TRADE_PAY";
    
        public String getOut_trade_no() {
            return out_trade_no;
        }
        public void setOut_trade_no(String out_trade_no) {
            this.out_trade_no = out_trade_no;
        }
        public String getSubject() {
            return subject;
        }
        public void setSubject(String subject) {
            this.subject = subject;
        }
        public String getTotal_amount() {
            return total_amount;
        }
        public void setTotal_amount(String total_amount) {
            this.total_amount = total_amount;
        }
        public String getBody() {
            return body;
        }
        public void setBody(String body) {
            this.body = body;
        }
        public String getTimeout_express() {
            return timeout_express;
        }
        public void setTimeout_express(String timeout_express) {
            this.timeout_express = timeout_express;
        }
        public String getProduct_code() {
            return product_code;
        }
        public void setProduct_code(String product_code) {
            this.product_code = product_code;
        }
    
    }

    订单业务封装

    订单业务提供支付宝支付接口 alipay,内部通过调用 PayService 完成订单支付。

    OrderRestController

    package com.feilong.shop.controller;
    
    import java.util.List;
    import java.util.Map;
    
    import javax.servlet.http.HttpSession;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.ModelAttribute;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import com.alipay.api.AlipayApiException;
    import com.feilong.shop.dto.OrderDetailListDTO;
    import com.feilong.shop.entity.AlipayBean;
    import com.feilong.shop.entity.Order;
    import com.feilong.shop.entity.OrderDetail;
    import com.feilong.shop.entity.User;
    import com.feilong.shop.service.OrderService;
    import com.feilong.shop.service.PayService;
    import com.mysql.cj.Session;
    
    
    /**
     * 订单接口
     * 
     * @author Louis
     * @date Dec 12, 2018
     */
    
     @RestController()
     @RequestMapping("order")
    
    public class OrderRestController {
    
        @Autowired
        private PayService payService;
        @Autowired
        private OrderService orderService;
        /**
         * 阿里支付
         * @param tradeNo
         * @param subject
         * @param amount
         * @param body
         * @return
         * @throws AlipayApiException
         */
        @PostMapping(value = "alipay")
        public String alipay(HttpSession session,Order order, String body,OrderDetailListDTO orderDetailListDTO) throws AlipayApiException {
            User user = (User) session.getAttribute("user");
            if(orderDetailListDTO==null||user==null) {
                return "error";
            }
            List<OrderDetail> orderDetails = orderDetailListDTO.getOrderDetailList();
            order.setUserId(user.getId());
            orderService.addOrder(order, orderDetails);
            
            AlipayBean alipayBean = new AlipayBean();
            alipayBean.setOut_trade_no(order.getId());
            alipayBean.setSubject(user.getName());
            String TotalMone = String.valueOf(0.1);
            alipayBean.setTotal_amount(TotalMone);
            alipayBean.setBody(body);
            return payService.aliPay(alipayBean);
        }
    }

    PayService 封装了 Alipay, 统一对外提供的支付服务接口。

    PayService.java 

    package com.feilong.shop.service;
    
    import com.alipay.api.AlipayApiException;
    import com.feilong.shop.entity.AlipayBean;
    
    
    /**
     * 支付服务
     * @author Louis
     * @date Dec 12, 2018
     */
    public interface PayService {
    
        /**
         * 支付宝支付接口
         * @param alipayBean
         * @return
         * @throws AlipayApiException
         */
        String aliPay(AlipayBean alipayBean) throws AlipayApiException;
    
    }

    支付服务的实现类,通过对各种支付代码的调用,统一对外提供支付服务。

    它接收一个 AlipayBean 为参数,最终通过调用 AlipayClient 的 pageExecute 方法返回支付页面。

    PayServiceImpl.java

    package com.feilong.shop.service.impl;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import com.alibaba.fastjson.JSON;
    import com.alipay.api.AlipayApiException;
    import com.alipay.api.AlipayClient;
    import com.alipay.api.DefaultAlipayClient;
    import com.alipay.api.request.AlipayTradePagePayRequest;
    
    import com.feilong.shop.config.AlipayProperties;
    import com.feilong.shop.entity.AlipayBean;
    import com.feilong.shop.service.PayService;
    
    
    @Service
    public class PayServiceImpl implements PayService {
    
        /*
         * @Autowired private Alipay alipay;
         */
        @Override
        public String aliPay(AlipayBean alipayBean) throws AlipayApiException {
            return pay(alipayBean);
        }
        
        /**
         * 支付接口
         * @param alipayBean
         * @return
         * @throws AlipayApiException
         */
        public static String pay(AlipayBean alipayBean) throws AlipayApiException {
            // 1、获得初始化的AlipayClient
            String serverUrl = AlipayProperties.getGatewayUrl();
            String appId = AlipayProperties.getAppId();
            String privateKey = AlipayProperties.getPrivateKey();
            String format = "json";
            String charset = AlipayProperties.getCharset();
            String alipayPublicKey = AlipayProperties.getPublicKey();
            String signType = AlipayProperties.getSignType();
            String returnUrl = AlipayProperties.getReturnUrl();
            String notifyUrl = AlipayProperties.getNotifyUrl();
            AlipayClient alipayClient = new DefaultAlipayClient(serverUrl, appId, privateKey, format, charset, alipayPublicKey, signType);
            // 2、设置请求参数
            AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
            // 页面跳转同步通知页面路径
            alipayRequest.setReturnUrl(returnUrl);
            // 服务器异步通知页面路径
            alipayRequest.setNotifyUrl(notifyUrl);
            // 封装参数
            alipayRequest.setBizContent(JSON.toJSONString(alipayBean));
            // 3、请求支付宝进行付款,并获取支付结果
            String result = alipayClient.pageExecute(alipayRequest).getBody();
            // 返回付款信息
            return result;
        }
    
    }

    测试页面

    在 static 目录下创建一个 index.html 页面,用于输入订单信息,并进行支付。

    index.html

    复制代码
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <H1>支付测试</H1>
    <hr>
    <div class="form-container">
        <form id="form" action="order/alipay" method="post">
            *商户订单 :
            <input type="text" name="outTradeNo" value="dzcp100010001"><br>
            *订单名称 :
            <input type="text" name="subject" value="红魔手机"><br>
            *付款金额 :
            <input type="text" name="totalAmount" value="0.1" ><br>
            *商品描述 :
            <input type="text" name="body" value="红魔手机 努比亚出品游戏手机"><br>
            <input type="button" value="支付宝支付" onclick="submitForm('order/alipay')"> 
            <input type="button" value=" 微信支付  " onclick="submitForm('order/wexpay')"> 
        </form>
    </div>
    </body>
    
    <script language="javascript">
    function submitForm(action) {
        document.getElementById("form").action = action
        document.getElementById("form").submit()
    }
    </script>
    
    <style>
    .form-container {
        padding-top:10px;
    }
    input {
        margin:10px;
        
    }
    </style>
    </html>
    复制代码

    点击支付宝支付,调用 order/alipay 接口,如果调用成功,则返回支付宝支付页面。

    到此,支付宝支付的实现案例就完成了。

    源码下载

    码云:https://gitee.com/liuge1988/epay.git

  • 相关阅读:
    [牛客]十二桥问题 解题报告
    [NOIP2017 逛公园] 解题报告
    [JSOI2008]最小生成树计数 解题报告
    类欧几里得算法
    概率与期望题目列表
    [SCOI2008]配对 解题报告
    拦截导弹
    牛客网-约数的个数
    牛客网-成绩排名
    最大连续区间和的算法总结
  • 原文地址:https://www.cnblogs.com/jiangfeilong/p/11062905.html
Copyright © 2011-2022 走看看