JAVA PC端掃碼支付(二)支付寶支付開發

1、配置java

配置

  1. 用戶註冊web

    首先用公司相關信息在螞蟻金服開放平臺註冊一個支付寶帳戶(https://openhome.alipay.com/platform/home.htm) 註冊公司支付寶帳號spring

    而後在進入開放平臺後進入開發者中心>網頁&移動應用接入中express

    輸入圖片說明

    接着和支付寶簽約,接入支付功能(手機網站支付)apache

    輸入圖片說明

  2. 配置和獲取相關開發信息json

    進入申請的支付功能頁面,配置受權回調地址和密鑰api

    輸入圖片說明

ok,如今咱們獲取了APPID、支付寶網關、受權回調地址、商戶私鑰、應用公鑰、支付寶公鑰等相關信息,開發時我將會把他們寫到配置文件中瀏覽器

另外,咱們還須要一個支付寶的SDK,請你們自行下載安全

輸入圖片說明到此,所需的所有準備工做完成,你們能夠愉快的開發了微信

2、開發

支付邏輯

  • 支付邏輯

    1. 商戶系統調用支付寶預下單接口alipay.trade.precreate,得到該訂單二維碼圖片地址。
    2. 發起輪詢得到支付結果:等待5秒後調用交易查詢接口alipay.trade.query經過支付時傳入的商戶訂單號(out_trade_no)查詢支付結果(返回參數TRADE_STATUS),若是仍然返回等待用戶付款(WAIT_BUYER_PAY),則再次等待5秒後繼續查詢,直到返回確切的支付結果(成功TRADE_SUCCESS 或 已撤銷關閉TRADE_CLOSED),或是超出輪詢時間。在最後一次查詢仍然返回等待用戶付款的狀況下,必須當即調用交易撤銷接口alipay.trade.cancel將這筆交易撤銷,避免用戶繼續支付。
    3. 這裏是列表文本除了主動輪詢,也能夠經過接受異步通知得到支付結果。
    4. 和微信支付差別的地方就在支付寶返回查詢用戶付款狀態的方式,支付寶除了主動輪詢查詢支付狀態,還能夠異步獲取。在項目裏咱們將這兩種方式交叉使用。

公共請求參數

  • 公共請求參數

    輸入圖片說明

與支付無關的業務邏輯

  • 與支付無關的業務邏輯

    這部分代碼已經在上篇文章微信支付中貼出,這裏就再也不從新貼一遍了

封裝固定參數

  • 封裝固定參數
package com.andata.conf;
/* * 
 *類名:AlipayConfig
 *功能:基礎配置類
 *詳細:設置賬戶有關信息及返回路徑
 *提示:如何獲取安全校驗碼和合做身份者ID
 *1.用您的簽約支付寶帳號登陸支付寶網站(www.alipay.com)
 *2.點擊「商家服務」(https://b.alipay.com/order/myOrder.htm)
 *3.點擊「查詢合做者身份(PID)」、「查詢安全校驗碼(Key)」
 *安全校驗碼查看時,輸入支付密碼後,頁面呈灰色的現象,怎麼辦?
 *解決方法:
 *一、檢查瀏覽器配置,不讓瀏覽器作彈框屏蔽設置
 *二、更換瀏覽器或電腦,從新登陸查詢。
 */
public class AlipayConfig {
	//ServiceURL
	public static String ServiceUrl="https://openapi.alipay.com/gateway.do";
	//APP支付寶支付業務:app_id
	public static String app_id = "20180xxxxxxxxxxxxxx";
	// 商戶的私鑰,使用支付寶自帶的openssl工具生成。
	public static String private_key = "xxxxxxxxxxxxxxxxxxx";
	// 應用的公鑰,無需修改該值
	public static String ali_public_key  = "xxxxxxxxxxxxxxxxxxxxx";
	// 支付寶的公鑰,去open.alipay.com對應應用下查看。
	public static String zfb_public_key  = "xxxxxxxxxxxxxxxxxxxxx";
	// 字符編碼格式 目前支持 gbk 或 utf-8
	public static String input_charset = "UTF-8";
}

AliPayController

package com.andata.controller;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeCancelRequest;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeCancelResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.andata.conf.AlipayConfig;
import com.andata.pojo.ProductOrders;
import com.andata.service.ProOrdersService;
import com.andata.util.QRCodeUtil;
import net.sf.json.JSONObject;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

@Controller
public class AliPayController {
    @Resource
    private ProOrdersService proOrdersService;
    /**
     * 支付邏輯
     * 一、商戶系統調用支付寶預下單接口alipay.trade.precreate,得到該訂單二維碼圖片地址。
     * 二、發起輪詢得到支付結果:等待5秒後調用交易查詢接口alipay.trade.query經過支付時傳入的商戶訂單號(out_trade_no)查詢支付結果(返回參數TRADE_STATUS),
     若是仍然返回等待用戶付款(WAIT_BUYER_PAY),則再次等待5秒後繼續查詢,直到返回確切的支付結果(成功TRADE_SUCCESS 或 已撤銷關閉TRADE_CLOSED),
     或是超出輪詢時間。在最後一次查詢仍然返回等待用戶付款的狀況下,必須當即調用交易撤銷接口alipay.trade.cancel將這筆交易撤銷,避免用戶繼續支付。
     * 三、除了主動輪詢,也能夠經過接受異步通知得到支付結果
     */
    /**
     * 阿里訂單取消接口
     * 請求返回值示例:
     * {"alipay_trade_cancel_response":{"code":"40004","msg":"Business Failed","sub_code":"ACQ.INVALID_PARAMETER","sub_msg":"參數無效","out_trade_no":"20150320010101002",
     * "retry_flag":"N"},"sign":""}
     * @return
     * @throws AlipayApiException
     */
    @RequestMapping(value = "aliremove.do")
    @ResponseBody
    private Map<String, Object> remove(@Param("orderid")String orderid) throws AlipayApiException {
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.ServiceUrl, AlipayConfig.app_id, AlipayConfig.private_key, "json", AlipayConfig.input_charset, AlipayConfig.zfb_public_key, "RSA2"); //得到初始化的AlipayClient
        AlipayTradeCancelRequest request = new AlipayTradeCancelRequest();//建立API對應的request類
        Map<String,Object> returnmap=new HashMap<>();
        try {
            //判斷訂單是否完成支付,完成支付的訂單禁止撤銷
            int i = this.proOrdersService.selectOrderStatus(orderid);
            if (i==1)
            {
                returnmap.put("type","0");
                returnmap.put("data","訂單已支付,撤銷訂單失敗");
            }else {
                Map<String,Object> map=new HashMap<>();
                map.put("out_trade_no",orderid);
                String returndata = JSONObject.fromObject(map).toString();
                request.setBizContent(returndata); //設置業務參數
                AlipayTradeCancelResponse response = alipayClient.execute(request);//經過alipayClient調用API,得到對應的response類
                JSONObject query_response = JSONObject.fromObject(response.getBody()).getJSONObject("alipay_trade_cancel_response");
                String code = query_response.getString("code");
                String msg = query_response.getString("msg");
                if (code.equals("10000") && msg.equals("Success")) {
                    System.out.println("阿里訂單取消接口調用成功!");
                    returnmap.put("type","1");
                    returnmap.put("data","撤銷訂單成功");
                }else {
                    System.out.println("撤銷訂單請求失敗");
                    returnmap.put("type","0");
                    returnmap.put("data",query_response.getString("sub_msg"));
                    System.out.println(query_response);//返回失敗信息
                }
                //根據response中的結果繼續業務邏輯處理
            }
        }catch (Exception e)
        {
            System.out.println("撤銷訂單異常");
            e.printStackTrace();
        }
        return returnmap;
    }

    /**
     * 阿里交易查詢接口
     * out_trade_no	支付時傳入的商戶訂單號,與trade_no必填一個
     *  trade_no	支付時返回的支付寶交易號,與out_trade_no必填一個
     *  請求返回值示例:
     *  {"alipay_trade_query_response":{"code":"10000","msg":"Success","buyer_logon_id":"159****4027","buyer_pay_amount":"0.01","buyer_user_id":"2088012351746164",
     *  "fund_bill_list":[{"amount":"0.01","fund_channel":"PCREDIT"}],"invoice_amount":"0.01","out_trade_no":"020910312752381","point_amount":"0.00","receipt_amount":"0.01",
     *  "send_pay_date":"2018-02-09 10:31:45","total_amount":"0.01","trade_no":"2018020921001004160275738069","trade_status":"TRADE_SUCCESS"},
     *  "sign":""}
     * @return
     * @throws Exception
     */
    @RequestMapping(value="/aliget")
    @ResponseBody
    private Map<String, Object> get(@Param("orderid")String orderid) throws AlipayApiException{
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.ServiceUrl, AlipayConfig.app_id, AlipayConfig.private_key, "json", AlipayConfig.input_charset, AlipayConfig.zfb_public_key, "RSA2"); //得到初始化的AlipayClient
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();//建立API對應的request類
        Map<String,Object> map=new HashMap<>();
        map.put("out_trade_no",orderid);
        String returndata = JSONObject.fromObject(map).toString();
        request.setBizContent(returndata); //設置業務參數
        AlipayTradeQueryResponse response = alipayClient.execute(request);//經過alipayClient調用API,得到對應的response類
        JSONObject jsonObject = JSONObject.fromObject(response.getBody()).getJSONObject("alipay_trade_query_response");
        String code = jsonObject.getString("code");
        String msg = jsonObject.getString("msg");
        Map<String,Object> returnmap=new HashMap<>();
        if (code.equals("10000") && msg.equals("Success"))
        {
            System.out.println("交易查詢請求成功");
            String trade_status = jsonObject.getString("trade_status");
            if (trade_status.equals("TRADE_SUCCESS"))
            {
                returnmap.put("type","1");
                returnmap.put("data","支付成功");
            }else {
                returnmap.put("type","0");
                returnmap.put("data",trade_status);
            }
        }else {
            System.out.println("交易查詢請求失敗");
            returnmap.put("type","0");
            returnmap.put("data",jsonObject.getString("sub_msg"));
            System.out.println(jsonObject);//返回失敗信息
        }
        return returnmap;
    }
    /**
     * @name 預下單請求,阿里獲取二維碼接口
     * @throws AlipayApiException
     * @Param out_trade_no 商戶訂單號,64個字符之內、只能包含字母、數字、下劃線;需保證在商戶端不重複
     * @Param total_amount 訂單總金額,單位爲元,精確到小數點後兩位,取值範圍[0.01,100000000] 若是同時傳入了【打折金額】,【不可打折金額】,
     * 【訂單總金額】三者,則必須知足以下條件:【訂單總金額】=【打折金額】+【不可打折金額】
     * @Param subject 訂單標題
     * @Param store_id 商戶門店編號
     * @Param timeout_express 該筆訂單容許的最晚付款時間,逾期將關閉交易。
     * 取值範圍:1m~15d。m-分鐘,h-小時,d-天,1c-當天(1c-當天的狀況下,不管交易什麼時候建立,都在0點關閉)。 該參數數值不接受小數點, 如 1.5h,可轉換爲 90m。
     */
    @RequestMapping(value="/alipay.do")
    @ResponseBody
    private Map list(HttpServletResponse responses, @Param("orderid")String orderid) throws AlipayApiException{
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.ServiceUrl, AlipayConfig.app_id, AlipayConfig.private_key, "json", AlipayConfig.input_charset, AlipayConfig.zfb_public_key, "RSA2"); //得到初始化的AlipayClient
        AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();//建立API對應的request類

        Map<String,Object> map=new HashMap<>();
        if (orderid.isEmpty())
        {
            map.put("type","2");
            map.put("data","訂單號不能爲空");
            return map;
        }
        //設置回調地址
        request.setNotifyUrl("http://www.andata.com.cn/aliPayCallBack.do");
        //根據訂單號查詢訂單信息
        ProductOrders productOrders = this.proOrdersService.selectByOrderId(orderid);
        Map<String,Object> maps=new HashMap<>();
        maps.put("out_trade_no",productOrders.getOrdernumber());
        maps.put("total_amount","0.01");
        maps.put("subject","小編機器人糾錯");
        maps.put("store_id","XB001");
        maps.put("timeout_express","1m");
        //把訂單信息轉換爲json對象的字符串
        String postdata = JSONObject.fromObject(maps).toString();
        request.setBizContent(postdata);
        AlipayTradePrecreateResponse response = alipayClient.execute(request);
        String body = response.getBody();
        JSONObject jsonObject = JSONObject.fromObject(body);
        String qr_code = jsonObject.getJSONObject("alipay_trade_precreate_response").getString("qr_code");
        //流輸出
        ServletOutputStream sos = null;
        try {
            sos = responses.getOutputStream();
            //生成二維碼
            QRCodeUtil.encode(qr_code, sos);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    /**
     * 支付寶支付成功回調
     */
    @RequestMapping(value = "aliPayCallBack.do")
    @ResponseBody
    public void aliPayCallBack(HttpServletResponse response, HttpServletRequest request) {
        System.out.println("支付寶回調成功");
        try {
            //獲取支付寶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] + ",";
                }
                //亂碼解決,這段代碼在出現亂碼時使用。
                //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
                params.put(name, valueStr);
            }
            boolean flag = AlipaySignature.rsaCheckV1(params, AlipayConfig.zfb_public_key, AlipayConfig.input_charset,"RSA2");
            // 獲取支付寶的通知返回參數,可參考技術文檔中頁面跳轉同步通知參數列表(如下僅供參考)//
            String order_no = request.getParameter("out_trade_no"); // 獲取訂單號

//			String trade_no = request.getParameter("trade_no"); // 支付寶交易號
//			String total_amount = request.getParameter("total_amount"); // 獲取總金額
//			String subject = new String(request.getParameter("subject")
//					.getBytes("ISO-8859-1"), "gbk");// 商品名稱、訂單名稱
//			String body = "";
//			if (request.getParameter("body") != null) {
//				body = new String(request.getParameter("body").getBytes(
//						"ISO-8859-1"), "gbk");// 商品描述、訂單備註、描述
//			}
//			String buyer_email = request.getParameter("buyer_email"); // 買家支付寶帳號
            String trade_status = request.getParameter("trade_status"); // 交易狀態
            // 獲取支付寶的通知返回參數,可參考技術文檔中頁面跳轉同步通知參數列表(以上僅供參考)//
            if (flag==true) {// 驗證成功
                try{
                    int i = this.proOrdersService.updateByOrderId(order_no);
                    if (i==1)
                    {
                        System.out.println("支付寶訂單支付成功!");
                    }
                }catch (Exception e)
                {
                    System.out.println("支付寶支付異常");
                    e.printStackTrace();
                }
            }
            response.getWriter().write("success");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

如今,基本的代碼都貼完了,生成二維碼的邏輯和微信同樣,拿到code_url後,用二維碼生成工具類生成二維碼,把他貼到網頁上須要支付的頁面,就成功了~

相關文章
相關標籤/搜索