1. 程式人生 > >【java】小白最詳細除錯支付寶沙箱手機網站支付,電腦網站掃碼支付

【java】小白最詳細除錯支付寶沙箱手機網站支付,電腦網站掃碼支付

      最近公司有電腦網站跟手機網站的支付寶支付需求,正好博主最近相對有空,於是花了一天時間去實現這個功能。先是在支付寶的開放平臺的文件中心看了半天,,發現並不能找到立馬就能上手開發的內容。於是搜了幾篇部落格,綜合之下終於實現了功能。在此將java沙箱除錯的歷程整理出來,希望能對大家有所幫助,好了廢話不扯,來看看怎麼一步步實現的。

第一步

    訪問開放平臺文件中西,看看支付寶的支付流程,大概瞭解一下就行了。地址如下https://docs.open.alipay.com/270/105898/

第二步

         下載java的demo(非常重要),裡面包含了需要的jar包以及定義好了支付寶支付的基本引數,下載下來之後我們把自己的引數copy進去,呼叫起來就很方便。下載路徑如下


第三步

       申請沙箱環境。沙箱環境相當於是一個支付寶的測試中心,申請之後,會給你指定的appid,測試買家的賬號(付款賬號),測試賣家賬號(收款賬號)。有了這些,我們就能愉快的享受除錯買買買的樂趣了。

      申請及資料採集步驟如下

1.進入支付寶沙箱測試中心     

2.需要生成RSA2(SHA256)的應用公鑰,並且配置好RSA2(SHA256)的應用公鑰,這裡注意,不需要配置RSA(SHA1)金鑰。(生成RSA2的應用公鑰詳情請參考:https://docs.open.alipay.com/291/105971) 然後將生成的公鑰填寫到下圖中的應用公鑰,再將支付寶的公鑰copy下來備用。


3.沙箱應用中,還需要配置應用閘道器,這裡就需要做內網穿透了。需要讓你本地的服務能在公網上被訪問到。博主使用的是natapp工具,使用起來很方便,生成了自己的域名之後,然後直接訪問,看看tomcat服務能不能跑起來,能訪問到之後,將域名天下到應用閘道器下。至此,沙箱配置就完成啦


第四步,將下載下來的demo解壓,匯入到自己的開發工具中,博主用的myeclipse,目錄及結構如下


其中為了方便處理支付寶的結構化引數,額外匯入了fastjson的包 ,具體的資源大家可以在百度maven 在倉庫中搜索下載啦

第五部,新增自己的程式碼快,如下

 package com.inspiron.alipay;


import java.util.HashMap;
import java.util.Map;


import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.StringUtils;
import com.alipay.api.request.AlipayTradeCancelRequest;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradePayRequest;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.response.AlipayTradeCancelResponse;
import com.alipay.api.response.AlipayTradePayResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.alipay.config.AlipayConfig;




public class AlipayClientFactory {
    
    /*private static final AlipayClient client = new DefaultAlipayClient( 
        AlipayConfig.URL, AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT, 
        AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY); */
    
    private static final AlipayClient client = new DefaultAlipayClient( 
        AlipayConfig.URL, AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT, 
        AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);
        
    public static AlipayClient getAlipayClientInstance() { 
      return client; 
    } 
    
    /** 
     * appAuthToken 
     * 如ISV代替商家呼叫當面付介面,需將商戶授權後獲取的app_auth_token帶上;如商家申請當面付自己呼叫,則傳null bizContent 
     * JSON格式 商戶的請求引數 
     */
    
    // 手機網頁支付 網站支付 
    public String ydAndPc_Pay(Map<String, String> maps) 
        throws AlipayApiException { 
      AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest(); 
      String NotifyUrl = maps.get("NotifyUrl"); 
      String ReturnUrl = maps.get("ReturnUrl"); 
      // 後臺回撥 
      if (!StringUtils.isEmpty(NotifyUrl)) { 
        alipayRequest.setNotifyUrl(NotifyUrl); 
        // bizContent 中不需要 公共引數 
        maps.remove("NotifyUrl"); 
      } 
      // 頁面回撥 
      if (!StringUtils.isEmpty(ReturnUrl)) { 
        alipayRequest.setReturnUrl(ReturnUrl); 
        // bizContent 中不需要 公共引數 
        maps.remove("ReturnUrl"); 
      } 
      String bizCon = JSON.toJSONString(maps); 
      alipayRequest.setBizContent(bizCon); 
      String form = ""; 
      try { 
        form = AlipayClientFactory.getAlipayClientInstance() 
            .pageExecute(alipayRequest).getBody(); 
      } catch (AlipayApiException e) { 
        form = "err"; 
        e.printStackTrace(); 
      } // 呼叫SDK生成表單 
      return form; 
    } 
    
    
    public String Pc_Pay(Map<String, String> maps) 
        throws AlipayApiException { 
      AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest(); 
      String NotifyUrl = maps.get("NotifyUrl"); 
      String ReturnUrl = maps.get("ReturnUrl"); 
      // 後臺回撥 
      if (!StringUtils.isEmpty(NotifyUrl)) { 
        alipayRequest.setNotifyUrl(NotifyUrl); 
        // bizContent 中不需要 公共引數 
        maps.remove("NotifyUrl"); 
      } 
      // 頁面回撥 
      if (!StringUtils.isEmpty(ReturnUrl)) { 
        alipayRequest.setReturnUrl(ReturnUrl); 
        // bizContent 中不需要 公共引數 
        maps.remove("ReturnUrl"); 
      } 
      String bizCon = JSON.toJSONString(maps); 
      System.out.println("bizCon :"+bizCon);
      alipayRequest.setBizContent(bizCon); 
      String form = ""; 
      try { 
        form = AlipayClientFactory.getAlipayClientInstance() 
            .pageExecute(alipayRequest).getBody(); 
      } catch (AlipayApiException e) { 
        form = "err"; 
        e.printStackTrace(); 
      } // 呼叫SDK生成表單 
      return form; 
    } 
    
    
    
    // 查詢訂單狀態 
    public AlipayTradeQueryResponse query(String appAuthToken, String bizContent) 
        throws AlipayApiException { 
      AlipayTradeQueryRequest request = new AlipayTradeQueryRequest(); 
      request.putOtherTextParam("app_auth_token", appAuthToken); 
      request.setBizContent(bizContent); 
      return AlipayClientFactory.getAlipayClientInstance().execute(request); 
    } 
    
    // 條碼支付 
    public AlipayTradePayResponse pay(String appAuthToken, String bizContent) 
        throws AlipayApiException { 
      AlipayTradePayRequest request = new AlipayTradePayRequest(); 
      request.putOtherTextParam("app_auth_token", appAuthToken); 
      request.setBizContent(bizContent); 
      return AlipayClientFactory.getAlipayClientInstance().execute(request); 
    } 
    
    // 掃碼支付 
    public AlipayTradePrecreateResponse precreate(String appAuthToken, 
        String bizContent) throws AlipayApiException { 
      AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest(); 
      request.putOtherTextParam("app_auth_token", appAuthToken); 
      request.setBizContent(bizContent); 
      return AlipayClientFactory.getAlipayClientInstance().execute(request); 
    } 
    
    // 訂單撤銷 
    public AlipayTradeCancelResponse cancel(String appAuthToken, 
        String bizContent) throws AlipayApiException { 
      AlipayTradeCancelRequest request = new AlipayTradeCancelRequest(); 
      request.putOtherTextParam("app_auth_token", appAuthToken); 
      request.setBizContent(bizContent); 
      return AlipayClientFactory.getAlipayClientInstance().execute(request); 
    } 
    
    // 申請退款 
    public AlipayTradeRefundResponse refund(String appAuthToken, 
        String bizContent) throws AlipayApiException { 
      AlipayTradeRefundRequest request = new AlipayTradeRefundRequest(); 
      request.putOtherTextParam("app_auth_token", appAuthToken); 
      request.setBizContent(bizContent); 
      return AlipayClientFactory.getAlipayClientInstance().execute(request); 
    } 
    
    @SuppressWarnings("unused") 
    public static void main(String[] args) { 
      AlipayClientFactory c = new AlipayClientFactory(); 
      try { 
        Map<String, String> map = new HashMap<String, String>(); 
        map.put("out_trade_no", "20160914113218"); 
        String bizContent = JSON.toJSONString(map); 
        System.err.println(bizContent); 
        AlipayTradeQueryResponse rp = c.query(null, bizContent); 
      } catch (AlipayApiException e) { 
        e.printStackTrace(); 
      } 
    } 
    

}

package com.inspiron.alipay;


import java.io.IOException;
import java.util.HashMap;
import java.util.Map;


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


import com.alipay.api.AlipayApiException;


public class CsPay extends HttpServlet {
    private static final long serialVersionUID = 1L;


    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }


    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 引數目前都是 寫死的 根據業務需求 寫活
        System.out.println("已經成功進入到後臺介面");
        Map<String, String> maps = new HashMap<String, String>();
        maps.put("out_trade_no", UtilDate.getOrderNum());
        maps.put("total_amount","1.00");
        maps.put("subject", "Iphone6 16G");
        maps.put("body", "Iphone6 16G");
        //maps.put("product_code", "QUICK_WAP_PAY");
        maps.put("product_code", "FAST_INSTANT_TRADE_PAY");//網頁版引數不同
        // 下面兩個 引數的 KEY 不要亂寫 要和工具類裡面對應
        maps.put("ReturnUrl", "http://f8s7ks.natappfree.cc/alipay.trade.wap.pay-java-utf-8/return_url.jsp");
        maps.put("NotifyUrl", "http://f8s7ks.natappfree.cc/alipay.trade.wap.pay-java-utf-8/notify_url.jsp");
        try {
            AlipayClientFactory ali = new AlipayClientFactory();
            String form = ali.Pc_Pay(maps);
            if (!form.equals("err")) {
                response.setContentType("text/html;charset=utf-8");
                response.getWriter().write(form);// 直接將完整的表單html輸出到頁面
                response.getWriter().flush();
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        
    }

}

package com.inspiron.alipay;


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


public class CsUtil {
    /**
     * 把陣列所有元素排序,並按照“引數=引數值”的模式用“&”字元拼接成字串
     * 
     * @param params 需要排序並參與字元拼接的引數組
     * @return 拼接後字串
     */
    public static String createLinkString(Map<String, String> params) {


        List<String> keys = new ArrayList<String>(params.keySet());
        Collections.sort(keys);


        String prestr = "";


        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = params.get(key);


            if (i == keys.size() - 1) {// 拼接時,不包括最後一個&字元
                prestr = prestr + key + "=" + value;
            } else {
                prestr = prestr + key + "=" + value + "&";
            }
        }


        return prestr;
    }

}

package com.inspiron.alipay;


import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;


/*
 * * 類名:UtilDate 功能:自定義訂單類 詳細:工具類,可以用作獲取系統日期、訂單編號等 版本:3.3 日期:2012-08-17 說明:
 * 以下程式碼只是為了方便商戶測試而提供的樣例程式碼,商戶可以根據自己網站的需要,按照技術文件編寫,並非一定要使用該程式碼。 該程式碼僅供學習和研究支付寶介面使用,只是提供一個參考。
 */
public class UtilDate {


    /** 年月日時分秒(無下劃線) yyyyMMddHHmmss */
    public static final String dtLong = "yyyyMMddHHmmss";


    /** 完整時間 yyyy-MM-dd HH:mm:ss */
    public static final String simple = "yyyy-MM-dd HH:mm:ss";


    /** 年月日(無下劃線) yyyyMMdd */
    public static final String dtShort = "yyyyMMdd";


    /**
     * 返回系統當前時間(精確到毫秒),作為一個唯一的訂單編號
     * 
     * @return 以yyyyMMddHHmmss為格式的當前系統時間
     */
    public static String getOrderNum() {
        Date date = new Date();
        DateFormat df = new SimpleDateFormat(dtLong);
        return df.format(date);
    }


    /**
     * 獲取系統當前日期(精確到毫秒),格式:yyyy-MM-dd HH:mm:ss
     * 
     * @return
     */
    public static String getDateFormatter() {
        Date date = new Date();
        DateFormat df = new SimpleDateFormat(simple);
        return df.format(date);
    }


    /**
     * 獲取系統當期年月日(精確到天),格式:yyyyMMdd
     * 
     * @return
     */
    public static String getDate() {
        Date date = new Date();
        DateFormat df = new SimpleDateFormat(dtShort);
        return df.format(date);
    }


    /**
     * 產生隨機的三位數
     * 
     * @return
     */
    public static String getThree() {
        Random rad = new Random();
        return rad.nextInt(1000) + "";
    }


}

程式碼貼進去之後,填寫AlipayConfig檔案中的引數,如下


然後需要配置servelt的入口,我們在web.xml 檔案中作如下配置

<servlet>
<servlet-name>cspay</servlet-name>
<servlet-class>com.inspiron.alipay.CsPay</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>cspay</servlet-name>
<url-pattern>/cspay</url-pattern>

</servlet-mapping>

將專案載入到伺服器中,訪問路徑 http://自己的網址/alipay.trade.wap.pay-java-utf-8/cspay   

出現以下頁面


恭喜你,大公高成啦。

如果是手機網站,呼叫app的方式,需要在程式碼中做如下修改


然後訪問出現如下頁面



表示成功 。然後可以登入沙箱給我們的買家的賬號,就可以體驗支付的流程啦

如果有問題,歡迎大家溝通指導~~