Springboot集成手機網站支付

一:簡介

手機網站支付常用於HTML5應用,常見於微信公衆號上的應用。手機網站支付文檔,其實當我們下載下來demo的時候,基本上所有的代碼都已經有了,我們所要做的就是集成到自己的項目裏面

二:集成步驟

創建應用、配置密鑰,這些準備步驟請看我先前寫的準備集成支付寶的準備工作
1.創建項目,集成依賴

	<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        
<!-- alipay begin -->
<dependency>
    <groupId>com.alipay</groupId>
    <artifactId>alipay-sdk-java</artifactId>
    <version>20170725114550</version>
</dependency>
<dependency>
    <groupId>com.alipay</groupId>
    <artifactId>alipay-trade-sdk</artifactId>
    <version>20161215</version>
</dependency>
<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
</dependency>
<dependency>
    <groupId>commons-configuration</groupId>
    <artifactId>commons-configuration</artifactId>
    <version>1.10</version>
</dependency>
<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>core</artifactId>
    <version>3.2.1</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>
<!-- alipay end -->

這裏有支付包的jar,我們首先需要將jar包添加到我們的maven中,這裏可以查看Maven添加本地jar包,這裏我再告訴大家一個方法,直接將jar包拷貝到resources中,新建lib,將jar包放入lib中,然後將jar導入
在這裏插入圖片描述

2.yml配置
這裏的公鑰私鑰肯定是要換成你自己對應的,異步訪問地址必須是外網可訪問的,所以這裏可以使用natapp,可以參考Natapp使用

# 沙箱賬號
pay:
  alipay:
    gatewayUrl: https://openapi.alipaydev.com/gateway.do
    appid: 2016091500517039
    appPrivateKey: MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCveherLJtuz6kaIpjqK5UoIjCru4jLeCx9rCYDFGN8FIQEh0iHEHbEvZ15zb50wkuhBEFEoRkPLrsg/CdaYl2qQly+OoPqNqFgQhcRu1qYAjO8aJAlajOYaJkcrC67DUlAIsU/yl8j5tc8Ik5RYzN9BjT2zNIXRoxhwytCX5STJT2ZEvQfkFdG0Hduud5eFLGFuC/mhJU+rdP2i6KZsDluf73VYmqC0JUs3pX+bVS1IV85cWpS/7F7mNR7t9hYCMZ9UJa7NLxJhh5JElwgZRozF0rLIkSN4K04VL9IHxwBQU6mFvnyxLzpF9P4HdPbq3w1AVEGUWcF3OGnOS7qCNBTAgMBAAECggEAMmNp1oJ5o6lH0rRqmpunOh4PQdEZJ+w7Ql8jjzDUnHW7rx01y2sD39zfEnHtJdQBKZxyLYXhD0YJACDIICEs6k4iGZHt/VxwnJZ9z16wVgQT3R9dfRDw/evTQ7OBu77F8P/LClVPWpzX43GqcZ5904HrxY7tKTfd6djEXEvb+yB00ErHisCLvaC2QNDq5kXBqNc9qNdULfWEvHOnALdgw39Qk5cIaGLSs/y9L67RtqN0SwdxZDViJkKsf9uhgHvjPfeGJvmT8nsOZpwT/9Woh0BdHPkbpiyocBUf/XVUSjqWzG8PS0Hj/FGac3M4y2yYN68a8LziapT7wUkoty3RsQKBgQDwP3YhPeWgMnXaa9vySUXVdT8O7b7Vv8XGrnfV6P4nlUmgLQaej2l8ju2YqnfbDXOMpWN8r6TSMhaUlwXFFhEL5yllcSFenk42O3VPYqOhkJK2YhIEkFC2+nH8DpXl7m1Tp8U0D/wxMddFccW+oiUHwGL72T0GZZiAvttBD5bGaQKBgQC6+3TOIHHcQUCQjpjuJXoLTOZ3ENY4p/qVbGuFWYHMfLHIPnZgpHkv8vum9H205Bo6XV9ybKVKdWU1uXZu/yEnkHhZGW8bgG+giB432efT2JQqA75IIo8frkuriJSL0ixfx59iJHGhks0N8ieLCKuqK8u35a2rrrxM6D7i7N7hWwKBgGq954BxfdqlUNOQ5JJLl+l1RGUfoJBbukXCMqAp+vIfVC0ElFJSqa2b21jfNI1w9ovg18kISRTTCFFQoFGmskA1nqDhmM/vShSyajaxPr6D+4tpG1RHwnTp5Ub2PAeC3bQzcFznVUeOO3UxTYibhhRhmBkJtiFndlCNe+D2SikxAoGAQFKahwJQSPXFkTUM1PfdeR+2NIV9PDZFFLwcbN4ysba/reQW8v4BloYfHfsDd4P0pdlTKVjIr8mczJOFc3+e1y5yyCvgtfRD8lSBGLOEdbMOnTl2bvg8hih+bX7powPlMfnJEYj58hw/ICoKgmC0NTElvphrWyEcM9S9NXFI5vsCgYEAxnYChqJ+4VXuNBF9wc6oebRYgGYWMEv0uhqa/7A0o6vsvXrd7QtQTdyeYxpBQLcsFJkKc1n5MFsrSY6FAFTVmBPMnYfQwH0OAYxKfytles3wMVxWbAwJwtxhZ1n3nGFHCES8rwPSa+5xZe6vzpYVUTgnjBfr4QL3dlQJKj51a+0=
    alipayPublicKey: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtHjQ2gD1juu9F5Hxr1oy5c8So9EC7G6OlK4rJf98kvFj1GaDxUp9/WY7YMThC1VqTZn+T9FiEO7CI8/EXjiF/4n64NYtJFOtT7dplmQwoVHE5dOvprfR1ugUbeHLcQlUvbctKELCDrUHTe3/p2rCIH7TwKQoUOpP6yunyHardPOddUJEC4C7wZ11KwzTDaa1pU3kLb0Z/0DEte63aEq3fyt1M5UFD5sQgN7FZuW3s7sy5jaIJgkZbNTIl/lpcrNjPGXxZmK6qfiiA8LSFgQj2A0UPSNtDLdUnO0I211tWRfUVVDzviIdV1T9k+JhlPhLsYGRFTvsa9cRgwWL/lt7BQIDAQAB
    returnUrl: http://zhouguoqing.natapp1.cc/alipay/wap/returnUrl
    notifyUrl: http://zhouguoqing.natapp1.cc/alipay/notify


spring:
  thymeleaf:
    prefix: classpath:/templates/
    suffix: .html
    mode: HTML5
    encoding: UTF-8

3.AlipayProperties的基礎文件
這是我們需要用到的基本參數,參數已經放在yml配置文件中,這裏我們使用註解去獲取,以及前面的註解Data,是使用了lombok插件,這裏可以查看使用lombok

@Data
@Slf4j
@ConfigurationProperties(prefix = "pay.alipay")
public class AlipayProperties {

    /** 支付寶gatewayUrl */
    private String gatewayUrl;
    /** 商戶應用id */
    private String appid;
    /** RSA私鑰,用於對商戶請求報文加簽 */
    private String appPrivateKey;
    /** 支付寶RSA公鑰,用於驗籤支付寶應答 */
    private String alipayPublicKey;
    /** 簽名類型 */
    private String signType = "RSA2";

    /** 格式 */
    private String formate = "json";
    /** 編碼 */
    private String charset = "UTF-8";

    /** 同步地址 */
    private String returnUrl;

    /** 異步地址 */
    private String notifyUrl;

    /** 最大查詢次數 */
    private static int maxQueryRetry = 5;
    /** 查詢間隔(毫秒) */
    private static long queryDuration = 5000;
    /** 最大撤銷次數 */
    private static int maxCancelRetry = 3;
    /** 撤銷間隔(毫秒) */
    private static long cancelDuration = 3000;

    private AlipayProperties() {}

    /**
     * PostContruct是spring框架的註解,在方法上加該註解會在項目啓動的時候執行該方法,也可以理解爲在spring容器初始化的時候執行該方法。
     */
    @PostConstruct
    public void init() {
        log.info(description());
    }

    public String description() {
        StringBuilder sb = new StringBuilder("\nConfigs{");
        sb.append("支付寶網關: ").append(gatewayUrl).append("\n");
        sb.append(", appid: ").append(appid).append("\n");
        sb.append(", 商戶RSA私鑰: ").append(getKeyDescription(appPrivateKey)).append("\n");
        sb.append(", 支付寶RSA公鑰: ").append(getKeyDescription(alipayPublicKey)).append("\n");
        sb.append(", 簽名類型: ").append(signType).append("\n");

        sb.append(", 查詢重試次數: ").append(maxQueryRetry).append("\n");
        sb.append(", 查詢間隔(毫秒): ").append(queryDuration).append("\n");
        sb.append(", 撤銷嘗試次數: ").append(maxCancelRetry).append("\n");
        sb.append(", 撤銷重試間隔(毫秒): ").append(cancelDuration).append("\n");
        sb.append("}");
        return sb.toString();
    }

    private String getKeyDescription(String key) {
        int showLength = 6;
        if (StringUtils.isNotEmpty(key) && key.length() > showLength) {
            return new StringBuilder(key.substring(0, showLength)).append("******")
                    .append(key.substring(key.length() - showLength)).toString();
        }
        return null;
    }
}


4.將基礎的配置文件加入到Spring的Bean容器中
創建AlipayConfiguration

@Configuration
@EnableConfigurationProperties(AlipayProperties.class)
public class AlipayConfiguration {

    @Autowired
    private AlipayProperties properties;

    @Bean
    public AlipayTradeService alipayTradeService() {
        return new AlipayTradeServiceImpl.ClientBuilder()
                .setGatewayUrl(properties.getGatewayUrl())
                .setAppid(properties.getAppid())
                .setPrivateKey(properties.getAppPrivateKey())
                .setAlipayPublicKey(properties.getAlipayPublicKey())
                .setSignType(properties.getSignType())
                .build();
    }

    @Bean
    public AlipayClient alipayClient(){
        return new DefaultAlipayClient(properties.getGatewayUrl(),
                properties.getAppid(),
                properties.getAppPrivateKey(),
                properties.getFormate(),
                properties.getCharset(),
                properties.getAlipayPublicKey(),
                properties.getSignType());
    }
}


5.創建支付需要的Controller層
新建AlipayWAPPayController,這裏我們只使用付款功能,其實其他的功能都類似

/**
 * @ Author     :Zgq
 * @ Date       :Created in 9:47 2019/5/31
 * @ Description:手機網站支付
 * @ Modified By:
 * @Version: $
 */

@RequestMapping("/phone")
@Controller
public class PhonePayController {

    @Autowired
    private AlipayConfig properties;


    /**
     * 跳轉到支付頁面
     * @param request
     * @param response
     * @throws Exception
     */
    @RequestMapping("goPay")
    public void goPay(HttpServletRequest request, HttpServletResponse response) throws Exception{
        if(request.getParameter("WIDout_trade_no")!=null){
            // 商戶訂單號,商戶網站訂單系統中唯一訂單號,必填
            String out_trade_no = new String(request.getParameter("WIDout_trade_no").getBytes("ISO-8859-1"),"UTF-8");
            // 訂單名稱,必填
            String subject = new String(request.getParameter("WIDsubject").getBytes("ISO-8859-1"),"UTF-8");
            System.out.println(subject);
            // 付款金額,必填
            String total_amount=new String(request.getParameter("WIDtotal_amount").getBytes("ISO-8859-1"),"UTF-8");
            // 商品描述,可空
            String body = new String(request.getParameter("WIDbody").getBytes("ISO-8859-1"),"UTF-8");
            // 超時時間 可空
            String timeout_express="2m";
            // 銷售產品碼 必填
            String product_code="QUICK_WAP_WAY";
            /**********************/
            // SDK 公共請求類,包含公共請求參數,以及封裝了簽名與驗籤,開發者無需關注簽名與驗籤
            //調用RSA簽名方式
            //獲得初始化的AlipayClient
            AlipayClient client = new DefaultAlipayClient(properties.getGatewayUrl(), properties.getApp_id(), properties.getMerchant_private_key(), "json", properties.getCharset(), properties.getAlipay_public_key(), properties.getSign_type());


            AlipayTradeWapPayRequest alipay_request=new AlipayTradeWapPayRequest();

            // 封裝請求支付信息
            AlipayTradeWapPayModel model=new AlipayTradeWapPayModel();
            model.setOutTradeNo(out_trade_no);
            model.setSubject(subject);
            model.setTotalAmount(total_amount);
            model.setBody(body);
            model.setTimeoutExpress(timeout_express);
            model.setProductCode(product_code);
            alipay_request.setBizModel(model);
            // 設置異步通知地址
            alipay_request.setNotifyUrl(properties.getNotify_url());
            // 設置同步地址
            alipay_request.setReturnUrl(properties.getReturn_url());

            // form表單生產
            String form = "";
            try {
                // 調用SDK生成表單
                form = client.pageExecute(alipay_request).getBody();
                response.setContentType("text/html;charset=" + properties.getCharset());
                response.getWriter().write(form);//直接將完整的表單html輸出到頁面
                response.getWriter().flush();
                response.getWriter().close();
            } catch (AlipayApiException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    /**
     * 交易查詢
     * @param request
     * @param trade_no
     * @param out_trade_no
     * @return
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping("query")
    public String query(HttpServletRequest request,String trade_no,String out_trade_no) throws Exception{

            //商戶訂單號,商戶網站訂單系統中唯一訂單號,必填
            String out_trade_no1 = new String(out_trade_no.getBytes("ISO-8859-1"),"UTF-8");
            //支付寶交易號
            String trade_no1 = new String(trade_no.getBytes("ISO-8859-1"),"UTF-8");
            /**********************/
            // SDK 公共請求類,包含公共請求參數,以及封裝了簽名與驗籤,開發者無需關注簽名與驗籤
            //獲得初始化的AlipayClient
            AlipayClient client = new DefaultAlipayClient(properties.getGatewayUrl(), properties.getApp_id(), properties.getMerchant_private_key(), "json", properties.getCharset(), properties.getAlipay_public_key(), properties.getSign_type());

            AlipayTradeQueryRequest alipay_request = new AlipayTradeQueryRequest();

            AlipayTradeQueryModel model=new AlipayTradeQueryModel();
            model.setOutTradeNo(out_trade_no1);
            model.setTradeNo(trade_no1);
            alipay_request.setBizModel(model);

            AlipayTradeQueryResponse alipay_response =client.execute(alipay_request);
            System.out.println(alipay_response.getBody());

        return alipay_response.getBody();
    }


    /**
     * 退款
     * @param request
     * @return
     */
    @ResponseBody
    @RequestMapping("return")
    public String tui(HttpServletRequest request,
                      String out_trade_no,String trade_no
            ,String refund_amount, String refund_reason,
                      String out_request_no) throws Exception{

            //商戶訂單號和支付寶交易號不能同時爲空。 trade_no、  out_trade_no如果同時存在優先取trade_no
            //商戶訂單號,和支付寶交易號二選一
            String out_trade_no1 = new String(out_trade_no.getBytes("ISO-8859-1"),"UTF-8");
            //支付寶交易號,和商戶訂單號二選一
            String trade_no1 = new String(trade_no.getBytes("ISO-8859-1"),"UTF-8");
            //退款金額,不能大於訂單總金額
            String refund_amount1=new String(refund_amount.getBytes("ISO-8859-1"),"UTF-8");
            //退款的原因說明
            String refund_reason1=new String(refund_reason.getBytes("ISO-8859-1"),"UTF-8");
            //標識一次退款請求,同一筆交易多次退款需要保證唯一,如需部分退款,則此參數必傳。
            String  out_request_no1=new String(out_request_no.getBytes("ISO-8859-1"),"UTF-8");
            /**********************/
            // SDK 公共請求類,包含公共請求參數,以及封裝了簽名與驗籤,開發者無需關注簽名與驗籤
            //獲得初始化的AlipayClient
            AlipayClient client = new DefaultAlipayClient(properties.getGatewayUrl(), properties.getApp_id(), properties.getMerchant_private_key(), "json", properties.getCharset(), properties.getAlipay_public_key(), properties.getSign_type());

            AlipayTradeRefundRequest alipay_request = new AlipayTradeRefundRequest();

            AlipayTradeRefundModel model=new AlipayTradeRefundModel();
            model.setOutTradeNo(out_trade_no1);
            model.setTradeNo(trade_no1);
            model.setRefundAmount(refund_amount1);
            model.setRefundReason(refund_reason1);
            model.setOutRequestNo(out_request_no1);
            alipay_request.setBizModel(model);

            AlipayTradeRefundResponse alipay_response =client.execute(alipay_request);
            System.out.println(alipay_response.getBody());

            return alipay_response.getBody();
    }




    /**
     * 退款交易查詢
     * @param request
     * @param trade_no
     * @param out_trade_no
     * @return
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping("Tkquery")
    public String Tkquery(HttpServletRequest request,String trade_no,
                          String out_trade_no,
                          String out_request_no) throws Exception{

            //商戶訂單號和支付寶交易號不能同時爲空。 trade_no、  out_trade_no如果同時存在優先取trade_no
            //商戶訂單號,和支付寶交易號二選一
            String out_trade_no1 = new String(out_trade_no.getBytes("ISO-8859-1"),"UTF-8");
            //支付寶交易號,和商戶訂單號二選一
            String trade_no1 = new String(trade_no.getBytes("ISO-8859-1"),"UTF-8");
            //請求退款接口時,傳入的退款請求號,如果在退款請求時未傳入,則該值爲創建交易時的外部交易號
            String out_request_no1 = new String(out_request_no.getBytes("ISO-8859-1"),"UTF-8");
            /**********************/
            // SDK 公共請求類,包含公共請求參數,以及封裝了簽名與驗籤,開發者無需關注簽名與驗籤
            //獲得初始化的AlipayClient
            AlipayClient client = new DefaultAlipayClient(properties.getGatewayUrl(), properties.getApp_id(), properties.getMerchant_private_key(), "json", properties.getCharset(), properties.getAlipay_public_key(), properties.getSign_type());


            AlipayTradeFastpayRefundQueryRequest alipay_request = new AlipayTradeFastpayRefundQueryRequest();

            AlipayTradeFastpayRefundQueryModel model=new AlipayTradeFastpayRefundQueryModel();
            model.setOutTradeNo(out_trade_no1);
            model.setTradeNo(trade_no1);
            model.setOutRequestNo(out_request_no1);
            alipay_request.setBizModel(model);

            AlipayTradeFastpayRefundQueryResponse alipay_response=client.execute(alipay_request);
            System.out.println(alipay_response.getBody());

            return alipay_response.getBody();

    }


    /**
     * 關閉交易
     * @param request
     * @param trade_no
     * @param out_trade_no
     * @return
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping("close")
    public String close(HttpServletRequest request,String trade_no,
                        String out_trade_no) throws Exception{

            //商戶訂單號和支付寶交易號不能同時爲空。 trade_no、  out_trade_no如果同時存在優先取trade_no
            //商戶訂單號,和支付寶交易號二選一
            String out_trade_no1 = new String(out_trade_no.getBytes("ISO-8859-1"),"UTF-8");
            //支付寶交易號,和商戶訂單號二選一
            String trade_no1 = new String(trade_no.getBytes("ISO-8859-1"),"UTF-8");
            /**********************/
            // SDK 公共請求類,包
            // 含公共請求參數,以及封裝了簽名與驗籤,開發者無需關注簽名與驗籤
            //獲得初始化的AlipayClient
            AlipayClient client = new DefaultAlipayClient(properties.getGatewayUrl(), properties.getApp_id(), properties.getMerchant_private_key(), "json", properties.getCharset(), properties.getAlipay_public_key(), properties.getSign_type());

            AlipayTradeCloseRequest alipay_request=new AlipayTradeCloseRequest();

            AlipayTradeCloseModel model =new AlipayTradeCloseModel();
            model.setOutTradeNo(out_trade_no1);
            model.setTradeNo(trade_no1);
            alipay_request.setBizModel(model);

            AlipayTradeCloseResponse alipay_response=client.execute(alipay_request);
            System.out.println(alipay_response.getBody());

        return alipay_response.getBody();
    }



    @ResponseBody
    @RequestMapping("url")
    public String url(HttpServletRequest request,String bill_type,String bill_date) throws Exception{

            // 賬單類型,商戶通過接口或商戶經開放平臺授權後其所屬服務商通過接口可以獲取以下賬單類型:trade、signcustomer;
            // trade指商戶基於支付寶交易收單的業務賬單;signcustomer是指基於商戶支付寶餘額收入及支出等資金變動的帳務賬單;
            String bill_type1 = new String(bill_type.getBytes("ISO-8859-1"),"UTF-8");
            // 賬單時間:日賬單格式爲yyyy-MM-dd,月賬單格式爲yyyy-MM。
            String bill_date1 = new String(bill_date.getBytes("ISO-8859-1"),"UTF-8");
            /**********************/
            // SDK 公共請求類,包含公共請求參數,以及封裝了簽名與驗籤,開發者無需關注簽名與驗籤
            //獲得初始化的AlipayClient
            AlipayClient client = new DefaultAlipayClient(properties.getGatewayUrl(), properties.getApp_id(), properties.getMerchant_private_key(), "json", properties.getCharset(), properties.getAlipay_public_key(), properties.getSign_type());
            AlipayDataDataserviceBillDownloadurlQueryRequest alipay_request = new AlipayDataDataserviceBillDownloadurlQueryRequest();

            AlipayDataDataserviceBillDownloadurlQueryModel model =new AlipayDataDataserviceBillDownloadurlQueryModel();
            model.setBillType(bill_type1);
            model.setBillDate(bill_date1);
            alipay_request.setBizModel(model);

            AlipayDataDataserviceBillDownloadurlQueryResponse alipay_response = client.execute(alipay_request);
            System.out.println(alipay_response.getBillDownloadUrl());

        return alipay_response.getBillDownloadUrl();
    }

6.新建一個同步異步回調地址

@RequestMapping("/callback")
@Controller
public class CallBackController {


    @Autowired
    private AlipayConfig properties;

    /**
     * 同步回調,展示頁面
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping("/return")
    public ModelAndView returnUrl(HttpServletRequest request, HttpServletResponse response)throws Exception{
        ModelAndView mv = new ModelAndView();
        PrintWriter out = response.getWriter();

        //獲取支付寶GET過來反饋信息
        Map<String,String> params = new HashMap<String,String>();
        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //亂碼解決,這段代碼在出現亂碼時使用。如果mysign和sign不相等也可以使用這段代碼轉化
            valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }

        //獲取支付寶的通知返回參數,可參考技術文檔中頁面跳轉同步通知參數列表(以下僅供參考)//
        //商戶訂單號

        String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");

        //支付寶交易號
        String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");

        //付款金額
        String total_amount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"),"UTF-8");

        //獲取支付寶的通知返回參數,可參考技術文檔中頁面跳轉同步通知參數列表(以上僅供參考)//
        //計算得出通知驗證結果
        //boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
        boolean verify_result = AlipaySignature.rsaCheckV1(params, properties.getAlipay_public_key(), properties.getCharset(), "RSA2");

        if(verify_result){//驗證成功
            //////////////////////////////////////////////////////////////////////////////////////////
            //請在這裏加上商戶的業務邏輯程序代碼
            //該頁面可做頁面美工編輯
            out.println("驗證成功<br />");
            //——請根據您的業務邏輯來編寫程序(以上代碼僅作參考)——

            String result="trade_no:"+trade_no+"<br/>out_trade_no:"+out_trade_no+"<br/>total_amount:"+total_amount;
            mv.addObject("data",result);
            mv.addObject("msg","驗籤成功");
            mv.setViewName("/result");
            //////////////////////////////////////////////////////////////////////////////////////////
        }else{
            //該頁面可做頁面美工編輯
            out.println("驗證失敗");
        }

        return mv;
    }


    /**
     * 異步回調
     * @param request
     * @param response
     * @throws Exception
     */
    @RequestMapping("/notify")
    public void notifyUrl(HttpServletRequest request, HttpServletResponse response) throws Exception{

        PrintWriter out = response.getWriter();

        //獲取支付寶POST過來反饋信息
        Map<String,String> params = new HashMap<String,String>();
        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //亂碼解決,這段代碼在出現亂碼時使用。如果mysign和sign不相等也可以使用這段代碼轉化
            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
            params.put(name, valueStr);
        }
        //獲取支付寶的通知返回參數,可參考技術文檔中頁面跳轉同步通知參數列表(以下僅供參考)//
        //商戶訂單號

        String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");
        //支付寶交易號

        String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");

        //交易狀態
        String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),"UTF-8");

        //獲取支付寶的通知返回參數,可參考技術文檔中頁面跳轉同步通知參數列表(以上僅供參考)//
        //計算得出通知驗證結果
        //boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
        boolean verify_result = AlipaySignature.rsaCheckV1(params, properties.getAlipay_public_key(), properties.getCharset(), "RSA2");

        if(verify_result){//驗證成功
            //////////////////////////////////////////////////////////////////////////////////////////
            //請在這裏加上商戶的業務邏輯程序代碼

            //——請根據您的業務邏輯來編寫程序(以下代碼僅作參考)——

            if(trade_status.equals("TRADE_FINISHED")){
                //判斷該筆訂單是否在商戶網站中已經做過處理
                //如果沒有做過處理,根據訂單號(out_trade_no)在商戶網站的訂單系統中查到該筆訂單的詳細,並執行商戶的業務程序
                //請務必判斷請求時的total_fee、seller_id與通知時獲取的total_fee、seller_id爲一致的
                //如果有做過處理,不執行商戶的業務程序

                //注意:
                //如果簽約的是可退款協議,退款日期超過可退款期限後(如三個月可退款),支付寶系統發送該交易狀態通知
                //如果沒有簽約可退款協議,那麼付款完成後,支付寶系統發送該交易狀態通知。
            } else if (trade_status.equals("TRADE_SUCCESS")){
                //判斷該筆訂單是否在商戶網站中已經做過處理
                //如果沒有做過處理,根據訂單號(out_trade_no)在商戶網站的訂單系統中查到該筆訂單的詳細,並執行商戶的業務程序
                //請務必判斷請求時的total_fee、seller_id與通知時獲取的total_fee、seller_id爲一致的
                //如果有做過處理,不執行商戶的業務程序

                //注意:
                //如果簽約的是可退款協議,那麼付款完成後,支付寶系統發送該交易狀態通知。
            }

            //——請根據您的業務邏輯來編寫程序(以上代碼僅作參考)——
            out.println("success");	//請不要修改或刪除

            //////////////////////////////////////////////////////////////////////////////////////////
        }else{//驗證失敗
            out.println("fail");
        }
    }
}

7.新建一個全局地址的轉換類
新建WebMvcConfiguration,其實這裏也可以在控制層寫跳轉,不過這樣更好

@Configuration
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
    @Override
    protected void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/topay").setViewName("pay");
        registry.addViewController("/query").setViewName("query");
        registry.addViewController("/tk").setViewName("refund");
        registry.addViewController("/tkquery").setViewName("refundquery");
        registry.addViewController("/url").setViewName("downloadurl");
        super.addViewControllers(registry);
    }

    /**
     * @Description 靜態資源路徑
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
        super.addResourceHandlers(registry);
    }
}

8.頁面
所有的頁面都是可以直接使用demo中的樣式

三.運行結果

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

備註:項目源碼我放在github上
https://github.com/ZGQ1996/phonepay.git

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章