1. 程式人生 > >支付--支付寶手機網站支付(WAP)

支付--支付寶手機網站支付(WAP)

介紹:
這是放在微信供公眾號內的一個專案,支付模組設計到微信公眾號支付和支付寶手機網站支付,這次把支付寶手機網站支付整理下來。

簽約:
首先要到支付寶開發者後臺去簽約支付寶手機網站支付方式。簽約的要求是必須有能訪問的網頁,網頁上有標明價格、名稱等詳細資訊的商品,而且整個下單流程要完善,網站的完成度要高,這才能通過稽核。

這裡寫圖片描述

參考:
因為之前對接過支付寶的app支付,所以對接wap支付就容易得多。後臺拼接引數的思路、方式都和之前一樣。直接複用之前的程式碼,只需稍微修改幾個引數就可以。
參見上一篇支付寶APP支付:http://blog.csdn.net/tonyfreak/article/details/78104519

這裡寫圖片描述

思路:
1、先到支付寶開放平臺建立應用獲取APPID
2、配置應用的相關引數,簽約申請開通對應的支付型別
3、獲得支付許可權後就可以著手進行程式碼編寫:
①、組裝引數分為公共請求引數和業務請求引數兩部分。詳見:https://docs.open.alipay.com/203/107090/
②、先把業務請求引數轉成json放入公共請求引數biz_content 中
③、將公共請求引數進行簽名操作
④、將簽名後獲得的簽名引數放入公共請求引數sign中
⑤、將此時的公共請求引數進行url編碼
⑥、將json資料傳給前端

微信公眾平臺無法使用支付寶收付款的解決方案
微信中無法開啟支付寶收款是微信瀏覽器限制所致,可以參考下圖方法引導使用者轉到系統瀏覽器,即可用支付寶收款。

點此下載

微信中呼叫支付寶支付效果展示

這裡寫圖片描述

這裡寫圖片描述

後臺程式碼

組裝引數

/**
     * 封裝好引數,前臺通過form表單來調起支付寶
     */
    @RequestMapping("/alipayPayChongRequest")
    @ApiOperation(value="支付寶充值起調的介面",httpMethod="POST",response=JsonUtil.class,notes="支付寶充值起調的介面---/alipayPayChongRequest")
    public void alipayPayChongRequest(
            @ApiParam
(required=true,name="orderNumber",value="訂單編號")@RequestParam(value="orderNumber") String orderNumber, @ApiParam(required=true,name="orderTitle",value="訂單標題")@RequestParam(value="orderTitle") String orderTitle, @ApiParam(required=true,name="description",value="訂單描述")@RequestParam(value="description") String description){ try{ if(orderNumber !=null && !orderNumber.equals("") && orderTitle !=null && !orderTitle.equals("") && description !=null && !description.equals("")){ BusWalletChong chong = busWalletChongService.findBusWalletChongById(orderNumber);// 根據訂單主鍵id查詢,訂單編號就是主鍵id String saleMoney = chong.getPrice().toString(); // 公共請求引數 Map<String, String> param = new HashMap<>(); param.put("app_id", AlipayConfig.appId); // 應用appId param.put("method", "alipay.trade.wap.pay"); // 介面名稱 param.put("format", "json"); //資料型別 param.put("charset", AlipayConfig.input_charset);//編碼格式 param.put("timestamp", DatetimeUtil.formatDateTime(new Date()));//傳送請求時間 param.put("version", "1.0");//呼叫介面版本,固定為1.0 param.put("notify_url", AlipayConfig.notify_url_chong);// 支付寶伺服器主動通知商戶服務 param.put("sign_type", AlipayConfig.sign_type);//簽名型別 // 支付業務請求引數 Map<String, Object> pcont = new HashMap<>(); pcont.put("out_trade_no", orderNumber);// 訂單號(綜合採購單編號) pcont.put("total_amount", String.valueOf(saleMoney));// 交易金額 pcont.put("subject", orderTitle); // 訂單標題 pcont.put("body", description); // 對交易或商品的描述 pcont.put("product_code", "QUICK_WAP_WAY"); // 銷售產品碼 param.put("biz_content", JSON.toJSONString(pcont)); // 業務請求引數 不需要對json字串轉義 Map<String, String> payMap = new HashMap<>(); try { param.put("sign", PayUtil.getSign(param, AlipayConfig.private_key)); // 業務請求引數 String orderStr = PayUtil.getSignEncodeUrl(param, true); System.out.println(orderStr); payMap.put("orderStr", orderStr); } catch (Exception e) { e.printStackTrace(); } map1.put("msg", "成功"); map2.put("result", payMap); }else{ map1.put("msg", "引數不全"); } } catch (BusinessException e) { e.printStackTrace(); map1.put("msg", "發生後臺異常"); } map.put("data", map2); map.put("result", map1); JsonUtil.writeJson(response, JsonUtil.objectToJson(map)); }

支付回撥

/**
     * 支付寶充值成功的回撥介面
     */
    @RequestMapping("/alipayPayCallBackWallet")
    @ApiOperation(value="支付寶充值成功的回撥介面",httpMethod="POST",response=JsonUtil.class,notes="支付寶充值成功的回撥介面---pay/alipayPayCallBackWallet")
    public String alipayPayCallBackWallet(){
        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] + ",";
                }
                // 亂碼解決,這段程式碼在出現亂碼時使用。如果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 price = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"), "UTF-8");
            // 獲取支付寶的通知返回引數,可參考技術文件中頁面跳轉同步通知引數列表(以上僅供參考)//
            boolean check = AlipayNotify.verify(params);
            if (check) {// 驗證成功
                // ////////////////////////////////////////////////////////////////////////////////////////
                // 請在這裡加上商戶的業務邏輯程式程式碼
                String orderNo = out_trade_no;// 提交訂單返回的訂單編號
                // 支付寶交易號
                String alipayOrderNo = trade_no;
                BusWalletChong chong = busWalletChongService.findBusWalletChongById(orderNo);
                if(chong != null && !"".equals(chong)){
                    if("1".equals(chong.getStatus())){// 支付狀態為:已支付
                        response.getWriter().write(setXML("SUCCESS", ""));
                    }else{
                        BusWalletChong newChong = new BusWalletChong();
                        newChong.setPrice(new BigDecimal(price));
                        newChong.setPayId(alipayOrderNo);
                        newChong.setPayType(BusWalletChong.ALIPAY_ZHIFU_TYPE);
                        newChong.setId(orderNo);
                        boolean flag = busWalletChongService.updateWallet(newChong);
                        if(flag){
                            response.getWriter().write(setXML("SUCCESS", ""));
                        }else{
                            response.getWriter().write(setXML("FAIL", ""));
                        }
                    }
                }else{
                    response.getWriter().write(setXML("FAIL", ""));
                }
                response.getWriter().write("SUCCESS"); 
            } else {// 驗證失敗
                response.getWriter().write("FAIL");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
public static String setXML(String return_code, String return_msg) {
        return "<xml><return_code><![CDATA[" + return_code + "]]></return_code><return_msg><![CDATA[" + return_msg
                + "]]></return_msg></xml>";
    }

簽名工具類

/**
     * 對支付引數資訊進行簽名
     * 
     * @param map
     *            待簽名授權資訊
     * 
     * @return
     */
    public static String getSign(Map<String, String> map, String rsaKey) {
        List<String> keys = new ArrayList<String>(map.keySet());
        // key排序
        Collections.sort(keys);

        StringBuilder authInfo = new StringBuilder();
        boolean first = true;
        for (String key : keys) {
            if (first) {
                first = false;
            } else {
                authInfo.append("&");
            }
            authInfo.append(key).append("=").append(map.get(key)); 
        }

        return SignUtils.sign(authInfo.toString(), rsaKey);
    }

簽名編碼工具類

/**
     * 返回簽名編碼拼接url
     * 
     * @param params
     * @param isEncode
     * @return
     */
    public static String getSignEncodeUrl(Map<String, String> map, boolean isEncode) {
        String sign = map.get("sign");
        String encodedSign = "";
        if (CollectionUtil.isNotEmpty(map)) {
            map.remove("sign");
            List<String> keys = new ArrayList<String>(map.keySet());
            // key排序
            Collections.sort(keys);

            StringBuilder authInfo = new StringBuilder();

            boolean first = true;// 是否第一個
            for (String key: keys) {
                if (first) {
                    first = false;
                } else {
                    authInfo.append("&");
                }
                authInfo.append(key).append("=");
                if (isEncode) {
                    try {
                        authInfo.append(URLEncoder.encode(map.get(key), AlipayConstants.CHARSET_UTF8));
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                } else {
                    authInfo.append(map.get(key));
                }
            }

            try {
                encodedSign = authInfo.toString() + "&sign=" + URLEncoder.encode(sign, AlipayConstants.CHARSET_UTF8);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }

        return encodedSign.replaceAll("\\+", "%20");
    }

前端程式碼

//點選支付寶付款
        function payByAli(orderId,description,title){
            $.ajax({
                data:{orderNumber:orderId,orderTitle:title,description:description},
                dataType:"json",
                type:"post",
                async: false,
                url:"${ctxPath}/payZhiFuBao/alipayPayRequest",
                success:function(msg){
                    if(msg.result.msg == "成功"){
                        //獲取拼接好的url
                        var url = msg.data.result.orderStr;
                        var urls = "https://mapi.alipay.com/gateway.do?"+url;
                        console.log(urls);
                        $(".ali").attr("href",urls);
                    }
                },
                error:function(msg){

                }
            });
        }