微信支付---服務端操作


微信支付服務端流程:

首先客戶端調起服務端接口來進行微信的統一下單(微信統一下單要進行兩次簽名驗證),通過驗證后返回處理結果,得到成功狀態碼后通知客戶端,並返回相應的信息。

然后客戶端發起支付,調用微信服務端。支付成功后,微信調用服務端的回調函數通知服務端支付結果,然后服務端進行一些后續處理操作。

 

1--------- 微信支付統一下單及驗證簽名

  /**
     * 微信支付統一下單及驗證簽名
     * 
     * @param request
     *            請求信息
     * @return 處理結果JSON信息
     * @throws*/
    @RequestMapping(value = "/wxPayinfo", method = RequestMethod.GET)
    @ResponseBody
    public ResultTO wxPayinfo(String orderId,String memberId,HttpServletRequest request,
            HttpServletResponse response) {
        // 下單詳細
        Map<String, Object> back = null;

        // 未輸入訂單ID
        if (orderId==null || orderId.isEmpty() || "".equals(orderId)) {
            // 返回未輸入訂單ID錯誤信息
            return ResultTO.newFailResultTO("參數orderId不能為空", null);
        }

        // 未輸入用戶ID
        if (memberId==null || memberId.isEmpty() || "".equals(memberId)) {
            // 返回未輸入用戶ID錯誤信息
            return ResultTO.newFailResultTO("參數memberId不能為空", null);
        }

        try {
            // 提交前訂單信息
            Map<String,Object> map = new HashMap<String,Object>();
            map.put("orderId", orderId);
            Order oldOrder = OrderService.selectObject(map);
            

            if (oldOrder != null) {
                Double amount = oldOrder.getOrderAmount().doubleValue();
                TenPayManager tenPayManager = new TenPayManager();
         //一次簽名驗證 back
= tenPayManager.weixinPay(oldOrder.getOrderSn().toString(), amount, request, response); } if(back.get("return_code").toString().equals("FAIL")){ String msg = back.get("return_msg").toString(); // 返回登錄信息錯誤信息 return ResultTO.newFailResultTO(msg, null); } else { logger.info("++++++++++++++++++++++++++++++++++ back: "+back); //二次簽名驗證 TenPayManager tenPayManager = new TenPayManager(); Map<String, Object> back2 = tenPayManager.weixinSignSecond(back); logger.info("++++++++++++++++++++++++++++++++++ back2: "+back2); // 返回處理成功信息 return ResultTO.newSuccessResultTO("微信驗證成功", back2); } } catch (Exception e) { // 保存錯誤LOG logger.error(e.getLocalizedMessage()); // 返回登錄信息錯誤信息 return ResultTO.newFailResultTO("微信驗證失敗", null); } }

2------微信工具類

package com.util.pay.tenpay;

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

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

import org.jboss.logging.Logger;

import com.util.AmountUtils;
import com.util.DateUtil;
import com.util.pay.tenpay.util.HttpPost;
import com.util.pay.tenpay.util.MD5Weixin;
import com.util.pay.tenpay.util.XmlParser;

public class TenPayManager {
    /**
     * 發單超過系統次數支付接口
     * 
     * @param orderId
     * @param request
     * @param response
     * @return
     */
    public Map<String, Object> weixinPay(String orderSn, double amount,
            HttpServletRequest request, HttpServletResponse response) {
     //服務器IP
        String serverIP = "127.0.0.1";
//        if(request != null){
//            serverIP = request.getRemoteAddr();
//        }
        String nonce_str = createNonceStr();
        String body = "訂單:" + orderSn;
     //注意:微信中金額單位為分,傳參值要轉化為分    
        String oAmount = moneyToFen(amount);
        //要刪--用於測試 start
        //oAmount = "1";
        // end
 //簽名驗證,拼接字符串
        String stringA = "appid=" + Constant.appID + "&body=" + body
                + "&mch_id=" + Constant.mchID + "&nonce_str=" + nonce_str
                + "&notify_url=" + Constant.wxNoticeUrl + "&out_trade_no="
                + orderSn + "&spbill_create_ip=" + serverIP + "&total_fee="
                + oAmount + "&trade_type=" + Constant.wxTradeType;
     //拼接key String stringSignTemp
= stringA + "&key=" + Constant.key; System.out.println(stringA); System.out.println(stringSignTemp); // 簽名最后全部轉為大寫 String sign = MD5Weixin.MD5Encode(stringSignTemp).toUpperCase(); System.out.println(sign); // 拼接xml StringBuffer xml = new StringBuffer(); xml.append("<xml>"); xml.append("<appid>").append(Constant.appID).append("</appid>"); xml.append("<body>").append(body).append("</body>"); xml.append("<mch_id>").append(Constant.mchID).append("</mch_id>"); xml.append("<nonce_str>").append(nonce_str).append("</nonce_str>"); xml.append("<notify_url>").append(Constant.wxNoticeUrl) .append("</notify_url>"); xml.append("<out_trade_no>").append(orderSn).append("</out_trade_no>"); xml.append("<spbill_create_ip>").append(serverIP) .append("</spbill_create_ip>"); xml.append("<total_fee>").append(oAmount).append("</total_fee>"); xml.append("<trade_type>").append(Constant.wxTradeType) .append("</trade_type>"); xml.append("<sign><![CDATA[").append(sign).append("]]></sign>"); xml.append("</xml>"); // System.out.println( "----------微信下單-----下單參數----------:" + // xml.toString() ); Map<String, Object> resultMap = new HashMap<String, Object>(); String retXmlStr = null; retXmlStr = HttpPost.sendPostWithXmlPara(Constant.pay_address, new String(xml.toString())); if (null != retXmlStr) { resultMap = XmlParser.xmlStrParser(retXmlStr); resultMap.put("timestamp", DateUtil.intDate()); resultMap.put("pack", "Sign=WXPay"); } return resultMap; } public static String createNonceStr() { String letter[] = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "S", "Y", "Z" }; String nonce_str = ""; for (int i = 0; i < 26; i++) { int num = new Random().nextInt(26); nonce_str += letter[num]; } return nonce_str; } /** * 將金額轉換成分 * * @param amount * 金額 * @return String 分為單位的金額 */ public static String moneyToFen(double amount) { // 分為單位的金額 String toFenTemp = String.valueOf(amount); // 臨時保存用金額 String toFen = AmountUtils.changeY2F(toFenTemp); // 返回分為單位的金額 return toFen; } /** * 微信二次簽名 * * @return */ public Map<String, Object> weixinSignSecond(Map<String,Object> back) { String stringA = "appid=" + Constant.appID + "&noncestr=" + back.get("nonce_str") + "&package=Sign=WXPay" + "&partnerid=" + Constant.mchID + "&prepayid=" + back.get("prepay_id") + "&timestamp=" + DateUtil.intDate(); System.out.println(stringA); String stringSignTemp = stringA + "&key=" + Constant.key; System.out.println(stringSignTemp); // 簽名最后全部轉為大寫 String sign = MD5Weixin.MD5Encode(stringSignTemp).toUpperCase(); System.out.println(sign); Map<String, Object> resultMap = new HashMap<String, Object>(); resultMap.put("appid", Constant.appID); resultMap.put("partnerid", Constant.mchID); resultMap.put("prepayid", back.get("prepay_id")); resultMap.put("pack", "Sign=WXPay"); resultMap.put("noncestr", back.get("nonce_str")); resultMap.put("timestamp", DateUtil.intDate()); resultMap.put("sign", sign); return resultMap; } }

3------配置類

package com.util.pay.tenpay;

public class Constant {
    
    public static final String key = "";// 簽名算法需要用到的秘鑰
    public static final String appID = "";// 開放平台AppID
    public static final String mchID = "100011111";// 商戶號
    public static final String pwd = "111111";// 
//    public static final String wxBody = "微信test";//
    public static final String pay_address = "https://api.mch.weixin.qq.com/pay/unifiedorder";// 統一支付API接口地址
    public static final String check_url = "https://api.mch.weixin.qq.com/pay/orderquery";// 查詢訂單API接口地址
    public static final String close_url = "https://api.mch.weixin.qq.com/pay/closeorder";// 關閉訂單API接口地址
    
    public static final String refund_url = "https://api.mch.weixin.qq.com/secapi/pay/refund"; //退款
    //測試用地址
//  public static String wxNoticeUrl = "http://xxx.xxx.xxx.xx:8080/api/wxPayReturn/wxPayNotifyReturn";
    public static String wxNoticeUrl = "http://xxx.xxx.xxx.xx:8080/api/wxPayReturn/wxPayNotifyReturn"; 
  
   public static final String wxTradeType = "APP";// 取值如下:JSAPI,NATIVE,APP }

4-----回調函數

package com.controller.api.;

import java.io.BufferedOutputStream;
import java.io.StringReader;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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

import org.apache.log4j.Logger;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.xml.sax.InputSource;

import com.controller.AbstractAPIController;
import com.po.Order;
import com.po.Store;
import com.service.OrderService;
import com.service.StoreService;
import com.to.ResultTO;
import com.util.RequestParamUtil;
import com.util.pay.tenpay.TenPayManager;
import com.util.pay.tenpay.bean.WxPayResult;

/**
 * FileName AppCourseController.java
 * 
 * Version 1.0
 * 
 * Create by zy 2016/3/20
 * 
 * APP課程業務控制器
 */
@Controller
@RequestMapping("/api/wxPayReturn")
public class WxPayReturnController extends AbstractAPIController {

    /** 日志文件生成器 */
    private static Logger log = Logger.getLogger(WxPayReturnController.class);
    
    @Autowired
    private OrderService OrderService;
    
    @Autowired
    private StoreService StoreService;

    /**
     * 微信支付回調接口
     * 
     * @author zy
     * @since Version 1.0
     * @param request
     *            請求信息
     * @return 處理結果JSON信息
     * @throws*/
    @RequestMapping(value = "/wxPayNotifyReturn")
    @ResponseBody
    public ResultTO wxPayNotifyReturn(HttpServletRequest request,
            HttpServletResponse response) {
        log.info("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA-------進入微信回調函數wxPayNotifyReturn!");
        try {
            // 把如下代碼貼到的你的處理回調的servlet 或者.do 中即可明白回調操作
            String inputLine;
            String notityXml = "";
            String resXml = "";

            try {
                while ((inputLine = request.getReader().readLine()) != null) {
                    notityXml += inputLine;
                }
                request.getReader().close();
            } catch (Exception e) {
                e.printStackTrace();
            }

            System.out.println("接收到的報文:" + notityXml);

            Map<String,String> m = parseXmlToList2(notityXml);
            WxPayResult wpr = new WxPayResult();
            wpr.setAppid(m.get("appid").toString());
            wpr.setBankType(m.get("bank_type").toString());
            wpr.setCashFee(m.get("cash_fee").toString());
            wpr.setFeeType(m.get("fee_type").toString());
            wpr.setIsSubscribe(m.get("is_subscribe").toString());
            wpr.setMchId(m.get("mch_id").toString());
            wpr.setNonceStr(m.get("nonce_str").toString());
            wpr.setOpenid(m.get("openid").toString());
            wpr.setOutTradeNo(m.get("out_trade_no").toString());
            wpr.setResultCode(m.get("result_code").toString());
            wpr.setReturnCode(m.get("return_code").toString());
            wpr.setSign(m.get("sign").toString());
            wpr.setTimeEnd(m.get("time_end").toString());
            wpr.setTotalFee(m.get("total_fee").toString());
            wpr.setTradeType(m.get("trade_type").toString());
            wpr.setTransactionId(m.get("transaction_id").toString());

            boolean payFlag = false;
            
            log.info("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA-------wpr.getReturnCode():"+wpr.getReturnCode());
            
            if ("SUCCESS".equals(wpr.getReturnCode())) {
                // 支付成功
                resXml = "<xml>"
                        + "<return_code><![CDATA[SUCCESS]]></return_code>"
                        + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";

                payFlag = true;
            } else {
                resXml = "<xml>"
                        + "<return_code><![CDATA[FAIL]]></return_code>"
                        + "<return_msg><![CDATA[報文為空]]></return_msg>"
                        + "</xml> ";
            }

            // 支付成功
            if (payFlag) {
                log.info("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA----------------payFlag:"+payFlag);
                //支付成功后,商戶操作處理
            }

            BufferedOutputStream out = new BufferedOutputStream(
                    response.getOutputStream());
            out.write(resXml.getBytes());
            out.flush();
            out.close();
        } catch (Exception e) {
            // 保存錯誤LOG
            log.error(e.getLocalizedMessage());
            // 返回登錄信息錯誤信息
            return ResultTO.newFailResultTO("支付失敗!", null);
        }
        // 返回處理成功信息以及課程列表
        return ResultTO.newSuccessResultTO("支付成功", null);
    }

    /**
     * description: 解析微信通知xml
     * 
     * @param xml
     * @return
     * @author ex_yangxiaoyi
     * @see
     */
    private static Map<String,String> parseXmlToList2(String xml) {
        Map<String,String> retMap = new HashMap<String,String>();
        try {
            StringReader read = new StringReader(xml);
            // 創建新的輸入源SAX 解析器將使用 InputSource 對象來確定如何讀取 XML 輸入
            InputSource source = new InputSource(read);
            // 創建一個新的SAXBuilder
            SAXBuilder sb = new SAXBuilder();
            // 通過輸入源構造一個Document
            Document doc = (Document) sb.build(source);
            Element root = doc.getRootElement();// 指向根節點
            List<Element> es = root.getChildren();
            if (es != null && es.size() != 0) {
                for (Element element : es) {
                    retMap.put(element.getName(), element.getValue());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return retMap;
    }

 5、AmountUtils

/**
     * 將元為單位的轉換為分 替換小數點,支持以逗號區分的金額
     * 
     * @param amount
     * @return
     */
    public static String changeY2F(String amount) {
        String currency = amount.replaceAll("\\$|\\¥|\\,", ""); // 處理包含, ¥
                                                                // 或者$的金額
        int index = currency.indexOf(".");
        int length = currency.length();
        Long amLong = 0l;
        if (index == -1) {
            amLong = Long.valueOf(currency + "00");
        } else if (length - index >= 3) {
            amLong = Long.valueOf((currency.substring(0, index + 3)).replace(
                    ".", ""));
        } else if (length - index == 2) {
            amLong = Long.valueOf((currency.substring(0, index + 2)).replace(
                    ".", "") + 0);
        } else {
            amLong = Long.valueOf((currency.substring(0, index + 1)).replace(
                    ".", "") + "00");
        }
        return amLong.toString();
    }

 


免責聲明!

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



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