app端微信支付(二) - 生成預付單


​前一篇文章的時序圖中說了,app端調用微信支付必須先由后台調用微信后台生成預付單,再構建參數給手機端,而數據的構建要以xml形式,那么看看代碼具體實現吧,代碼已經精簡過了,自己的業務已經除去,精簡的代碼附上注釋是可以直接調用微信后台的

這個是微信所要接受的參數,咱們可以把它構建成一個entity

public class WXPrepay {
    private static String unifiedorder = "https://api.mch.weixin.qq.com/pay/unifiedorder";
    private static String orderquery = "https://api.mch.weixin.qq.com/pay/orderquery";
    private String appid;                // 應用ID            微信開放平台審核通過的應用APPID
    private String mch_id;                // 商戶號            微信支付分配的商戶號
    private String nonce_str = OrderUtil.CreateNoncestr();        // 隨機字符串        隨機字符串,不長於32位
    private String sign;                // 簽名        
    private String body;                // 商品描述        商品描述交易字段格式根據不同的應用場景按照以下格式:APP——需傳入應用市場上的APP名字-實際商品名稱,天天愛消除-游戲充值。
    private String out_trade_no;        // 商戶訂單號        商戶系統內部的訂單號,32個字符內、可包含字母
    private String total_fee;            // 總金額            訂單總金額,單位為分
    private String spbill_create_ip;    // 終端IP            用戶端實際ip
    private String notify_url;            // 通知地址        接收微信支付異步通知回調地址,通知url必須為直接可訪問的url,不能攜帶參數。    
    private String trade_type;            // 交易類型        支付類型
    private String partnerKey;
    private String attach;                // 附加數據        附加數據,在查詢API和支付通知中原樣返回,該字段主要用於商戶攜帶訂單的自定義數據
    
    private String prepay_id;            // 預支付訂單號

 

controller作為一個restful接口供手機端調用,這個接口可以被ios,安卓等調用,只要微信提供了相應手機端的sdk,那就沒有問題

@RequestMapping("/wxpay")
    @ResponseBody
    public LeeJSONResult wxpay(HttpServletRequest request, Model model) {
        try {
            // TODO 根據你的業務邏輯計算你需要支付的訂單總額
            double totalFee = 1;
            // 生成交易流水,流水id需要傳給微信,這個流水ID可以作為你的訂單ID,由於我們的業務是多訂單的,流水ID僅僅只是作為表關聯
            // 需要保存貨源id,需要的車輛數,訂單id在通知成功后保存
            String payFlowId = sid.nextShort();
            SpPayFlowCargoSource payFlowCargoSource = new SpPayFlowCargoSource();
            payFlowCargoSource.setId(payFlowId);
            payFlowCargoSource.setFee(new BigDecimal(totalFee));
            payFlowCargoSource.setPayStatus(PayStatusEnum.NOT_PAID.value);    // 支付狀態:未支付
            
            // 構建微信參數
            String spbill_create_ip = request.getRemoteAddr();        // 用戶IP
            WXPrepay prePay = new WXPrepay();
            prePay.setAppid(WXPayContants.appId);                    
            prePay.setMch_id(WXPayContants.partnerId);
            prePay.setBody("demo - 微信支付");                    
            prePay.setOut_trade_no(payFlowId);                        
            // 這里要注意,微信支付是以分為單位,而系統是以元為單位,所以需要金額轉換。題外話:曾經看到過京東和蘇寧都有類似的bug,就是一個台手機和耳機都是要十幾元,估計是金額轉換出的問題
            prePay.setTotal_fee(String.valueOf(new BigDecimal(totalFee).multiply(new BigDecimal(100)).intValue()));     
//            prePay.setTotal_fee("1");
            prePay.setSpbill_create_ip(spbill_create_ip);
            prePay.setNotify_url(notifyUrl);                    // 異步通知,這個下篇文章講
            prePay.setTrade_type("APP");
            prePay.setAttach(payFlowId);                        // 存入交易流水id
                
            prePay.setPartnerKey(WXPayContants.partnerKey);
            
            // 獲取預支付訂單號
            String prepayId = prePay.submitXmlGetPrepayId();
            logger.info("獲取的預支付訂單是:" + prepayId);
            if (prepayId != null && prepayId.length() > 10) {
                // 生成微信支付參數,此處拼接為完整的JSON格式,符合支付調起傳入格式
                String jsParam = WXPay.createPackageValue(WXPayContants.appId, WXPayContants.partnerKey, prepayId);
                System.out.println("jsParam=" + jsParam);
                // 此處可以添加訂單的處理邏輯
                model.addAttribute("jsParam", jsParam);
                logger.info("生成的微信調起JS參數為:" + jsParam);
                
                payFlowCargoSource.setPrepayId(prepayId);                            
                spPayFlowCargoSourceService.savePayFlow(payFlowCargoSource);
                
                return LeeJSONResult.ok();
            } else {
                return LeeJSONResult.errorMsg("微信支付接口調用失敗");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return LeeJSONResult.errorException(e.getMessage());
        }
    }

 

需要注意的是,微信后台接受的參數都是xml格式的,所以咱們的bean需要轉換為xml再傳給微信,最后調用成功,微信會封裝一個xml傳過來,咱們同樣再解析一下獲取預付單號就OK了

public String submitXmlGetPrepayId() {
        // 創建HttpClientBuilder
        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
        // HttpClient
        CloseableHttpClient closeableHttpClient = httpClientBuilder.build();
        HttpPost httpPost = new HttpPost(unifiedorder);
        String xml = getPackage();
        StringEntity entity;
        try {
            entity = new StringEntity(xml, "utf-8");
            httpPost.setEntity(entity);
            HttpResponse httpResponse;
            // post請求
            httpResponse = closeableHttpClient.execute(httpPost);
            HttpEntity httpEntity = httpResponse.getEntity();
            if (httpEntity != null) {
                // 打印響應內容
                String result = EntityUtils.toString(httpEntity, "UTF-8");
                System.out.println(result);
                // 過濾
                result = result.replaceAll("<![CDATA[|]]>", "");
                String prepay_id = Jsoup.parse(result).select("prepay_id").html();
                this.prepay_id = prepay_id;
                if (prepay_id != null) {
                    return prepay_id;
                }
            }
            // 釋放資源
            closeableHttpClient.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return prepay_id;
    }

 

其實不用這樣的方式也行,把bean通過json的方式封裝,最后讓它自動轉為xml,也是沒有問題的,或者直接使用 restful webservice標准協議來接受xml和發送xml


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM