中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

java如何實現微信jsApi支付

發布時間:2021-10-19 17:09:44 來源:億速云 閱讀:146 作者:柒染 欄目:大數據

java如何實現微信jsApi支付,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。

標注:1、必須在微信內置瀏覽器進行支付;2、open id必須獲取;3、獲取code必須請求后臺服務器,將code獲取到返回前端,再請求獲取openid,將openid存在自己服務器的session中

一、賬戶準備

1、在微信公眾平臺開通服務號并付費300元認證(只有企業才能開通)獲取appid,在微信支付商戶平臺注冊超級管理員并付費300認證,獲取mch_id(商戶id)。

2、在微信公眾平臺獲取 appid,appsecret。在商戶平臺獲取mch_id,api安全中獲取API密鑰(paternerKey)

二、平臺配置

1、商戶平臺:產品中心開發配置,屬于支付頁面

2、公眾平臺:賬戶詳情功能設置,配置網頁授權域名,(將txt文件放在一級域名以及目錄中,可通過域名/txt(文件全稱)訪問,測試是否可以獲取txt內容。如果不行,則進行nginx配置域名訪問目錄)

3、公眾平臺:開發,基本設置,配置服務器地址(需要寫接口并返回echostr,驗證服務器),令牌隨便寫,消息密鑰(隨機生成),加密模式:兼容模式。

三、開發(下載javasdk。將微信中的工具類導入https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1)

1、支付前獲取基本參數

  /**
     * 微信中請求打開頁面
     */
    @RequestMapping(value = "/toJob")
    public String  toJob(HttpServletResponse response){
        String appId = WxConstants.APPID;
        String tologin =redirectURL;
        return "redirect:https://open.weixin.qq.com/connect/oauth3/authorize?appid="+appId+"&redirect_uri="+tologin+"&response_type=code&scope=snsapi_base#wechat_redirect";
    }

    /**
     * 微信請求打開頁面重定向到該接口,獲取code
     * 然后重定向到自己頁面
     */
    @RequestMapping(value = "/tologin")
    public String  tologin(String code ,HttpServletResponse response){
        return "redirect:"+loginUrl+code;
    }

    /**
     * 獲取open id
     */
    @RequestMapping("/getOpenId")
    @ResponseBody
    public String getOpenId( @RequestParam("code") String code,HttpServletRequest request){
        logger.info("code  code:" + code);
        Map<String, String> result = new HashMap<>();
        //頁面獲取openId接口
        String getopenid_url = "https://api.weixin.qq.com/sns/oauth3/access_token";
        Map<String, String> param = new HashMap<>();
        param.put("appid", WxConstants.APPID);
        param.put("secret", WxConstants.SECRET);
        param.put("code", code);
        param.put("grant_type", "authorization_code");
        //向微信服務器發送get請求獲取openIdStr
        String openIdStr = HttpClientUtil.doGet(getopenid_url, param);
        JSONObject jsonObject = JSON.parseObject(openIdStr);
        logger.info("opendID  JSON:" + openIdStr);
        String openid =  jsonObject.getString("openid");
        //將open id存入session。
        //如果直接重定向到該接口,openid存不到session中,只會存在騰訊的session中
        //微信中打開頁面只能請求后臺接口,后臺獲取到code拼接到前臺頁面后面
        //前臺獲取到code,然后請求獲取open id的接口,可以將open id存到我們自己服務器中
        request.getSession().setAttribute("openid", openid);
        //返回登錄頁
        return openid;
    }

    /**
     * 微信測試接口
     * @param request
     * @return
     */
    @RequestMapping("/Token")
    @ResponseBody
    public String Token(HttpServletRequest request){
        logger.info(JSON.toJSONString(request.getParameterMap()));
        return request.getParameter("echostr");
    }

2、支付、回調

/**
     * 簡歷微信支付
     * @param request
     * @param isUpdate 是否是認證訂單
     */
    @RequestMapping(value = "/wxPayJob")
    @ResponseBody
    public Map<String,String> wxpay(HttpServletRequest request,
                                    @RequestParam("isUpdate") Integer isUpdate,
                                     @RequestParam("jobUserId") Long jobUserId,
                                     @RequestParam("totalAmount") String totalAmount) {
        String openId = (String) request.getSession().getAttribute("openid");
        logger.info("opendID  pay:" + openId);
        //獲取openId
        String ip = WxUtils.getIpAddress(request);
        //將元轉化為分
        String totalFee =  AmountUtils.changeY2F(totalAmount);
        Map<String, String> result = wxService.orderPayment(openId, ip, totalFee, jobUserId, isUpdate);
        return result;
    }

    /**
     * 微信支付回調
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/wxPayJobNotify")
    @ResponseBody
    public  String wxPayJobNotify(HttpServletRequest request, HttpServletResponse response) {
        InputStream is = null;
        try {
            is = request.getInputStream();//獲取請求的流信息(這里是微信發的xml格式所有只能使用流來讀)
            String xml =  IOUtils.toString(is, "utf-8");
            Map<String, String> notifyMap = WXPayUtil.xmlToMap(xml);//將微信發的xml轉map

            if(notifyMap.get("return_code").equals("SUCCESS")){
                if(notifyMap.get("result_code").equals("SUCCESS")){
                    String orderNum = notifyMap.get("out_trade_no");//商戶訂單號
                    String amountpaid = notifyMap.get("total_fee");//實際支付的訂單金額:單位 分
                    String  amount =  AmountUtils.changeF2Y(amountpaid);
                    //String openid = notifyMap.get("openid");  //如果有需要可以獲取
                    //String trade_type = notifyMap.get("trade_type");
                    //修改認證狀態,訂單狀態
                    jobOrderDtoService.updateState(orderNum);
                    }
                }
            //告訴微信服務器收到信息了,不要在調用回調action了========這里很重要回復微信服務器信息用流發送一個xml即可
            response.getWriter().write("<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>");
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

3、支付統一下單主體

 //微信支付----異步回調(接口:payForOrder)
    @Value(value = "${WxConfig.wxJObNotifyUrl}")
    private String wxJObNotifyUrl;


    /**
     *  調用微信支付
     */
    @Override
    public Map<String, String> orderPayment(String openId, String ip, String totalAmount, Long jobUserId, Integer isUpdate) {
        Map<String, String> payMap = new HashMap<String, String>();
        try{
            String OrderNum = OrderNumUtil.outtradeno("JOB");
            String body = "認證";
            Map<String, String>  mapBody =  setSortedMap(openId,OrderNum,body,totalAmount,ip);
            String xml = WXPayUtil.mapToXml(mapBody);//將所有參數(map)轉xml格式
            // 統一下單
            String unifiedorder_url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
            //發送post請求"統一下單接口"返回預支付id:prepay_id
            Map<String, String> xmlMap = new HashMap<>();
            xmlMap.put("xml",xml);
            String xmlStr = HttpClientUtil.doPostJson(unifiedorder_url, xml);
            //返回前端頁面的json數據
            payMap = resultMap(xmlStr);
           
            //插入簡歷訂單
            
        } catch (Exception e) {
            e.printStackTrace();
        }
            return payMap;
     }

    /**
     * 下單主體信息
     */
    public Map<String, String> setSortedMap(String openId,String OrderNum,String body,String totalFee,String ip) throws  Exception{
        //拼接統一下單地址參數
        Map<String, String> paraMap = new HashMap<String, String>();
        paraMap.put("appid", WxConstants.APPID);
        paraMap.put("body", body);
        paraMap.put("mch_id", WxConstants.MCHID);
        paraMap.put("nonce_str", WXPayUtil.generateNonceStr());//生成uuID
        paraMap.put("openid", openId);
        paraMap.put("out_trade_no", OrderNum);//訂單號
        paraMap.put("spbill_create_ip", ip);
        paraMap.put("total_fee",totalFee);//金額 單位 分
        paraMap.put("trade_type", WxConstants.WX_TRADE_JSAPI);
        paraMap.put("notify_url",wxJObNotifyUrl);// 此路徑是微信服務器調用支付結果通知路徑隨意寫
        String sign = WXPayUtil.generateSignature(paraMap, WxConstants.KEY);
        paraMap.put("sign", sign);
        return paraMap;
    }

    /**
     * 返回前端頁面的json數據
     */
    public  Map<String, String> resultMap(String xmlStr)throws  Exception{

        Map<String, String> json = WXPayUtil.xmlToMap(xmlStr);
        //JSONObject json = JSONObject.parseObject(xmlStr);//轉成Json格式
        LOGGER.info("prepay_id  JSON:" + json);
        //獲取prepay_id
        String prepay_id = json.get("prepay_id");//預支付id
        if (xmlStr.indexOf("SUCCESS") != -1) {
            Map<String, String> map = WXPayUtil.xmlToMap(xmlStr);
            prepay_id = (String) map.get("prepay_id");
        }
        Map<String, String> payMap = new HashMap<String, String>();
        payMap.put("appId", WxConstants.APPID);
        payMap.put("timeStamp", WXPayUtil.getCurrentTimestamp()+"");
        payMap.put("nonceStr", WXPayUtil.generateNonceStr());
        payMap.put("signType", "MD5");
        payMap.put("package", "prepay_id=" + prepay_id);
        String paySign = WXPayUtil.generateSignature(payMap, WxConstants.KEY);
        payMap.put("paySign", paySign);
        return payMap;
    }

4、工具類:

元轉分,分轉元

public class AmountUtils {
    /**金額為分的格式 */
    public static final String CURRENCY_FEN_REGEX = "\\-?[0-9]+";

    /**
     * 將分為單位的轉換為元并返回金額格式的字符串 (除100)
     *
     * @param amount
     * @return
     * @throws Exception
     */
    public static String changeF2Y(Long amount) throws Exception{
        if(!amount.toString().matches(CURRENCY_FEN_REGEX)) {
            throw new Exception("金額格式有誤");
        }

        int flag = 0;
        String amString = amount.toString();
        if(amString.charAt(0)=='-'){
            flag = 1;
            amString = amString.substring(1);
        }
        StringBuffer result = new StringBuffer();
        if(amString.length()==1){
            result.append("0.0").append(amString);
        }else if(amString.length() == 2){
            result.append("0.").append(amString);
        }else{
            String intString = amString.substring(0,amString.length()-2);
            for(int i=1; i<=intString.length();i++){
                if( (i-1)%3 == 0 && i !=1){
                    result.append(",");
                }
                result.append(intString.substring(intString.length()-i,intString.length()-i+1));
            }
            result.reverse().append(".").append(amString.substring(amString.length()-2));
        }
        if(flag == 1){
            return "-"+result.toString();
        }else{
            return result.toString();
        }
    }

    /**
     * 將分為單位的轉換為元 (除100)
     *
     * @param amount
     * @return
     * @throws Exception
     */
    public static String changeF2Y(String amount) throws Exception{
        if(!amount.matches(CURRENCY_FEN_REGEX)) {
            throw new Exception("金額格式有誤");
        }
        return BigDecimal.valueOf(Long.valueOf(amount)).divide(new BigDecimal(100)).toString();
    }

    /**
     * 將元為單位的轉換為分 (乘100)
     *
     * @param amount
     * @return
     */
    public static String changeY2F(Long amount){
        return BigDecimal.valueOf(amount).multiply(new BigDecimal(100)).toString();
    }

    /**
     * 將元為單位的轉換為分 替換小數點,支持以逗號區分的金額
     *
     * @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();
    }

    public static void main(String[] args) {
//        try {
//            System.out.println("結果:"+changeF2Y("-000a00"));
//        } catch(Exception e){
//            System.out.println("----------->>>"+e.getMessage());
////          return e.getErrorCode();
//        }
//      System.out.println("結果:"+changeY2F("1.00000000001E10"));

        System.out.println(AmountUtils.changeY2F("1.33"));
        try {
            System.out.println(AmountUtils.changeF2Y("1322"));
        } catch (Exception e) {
            e.printStackTrace();
        }
//        System.out.println(Long.parseLong(AmountUtils.changeY2F("1000000000000000")));
//        System.out.println(Integer.parseInt(AmountUtils.changeY2F("10000000")));
//        System.out.println(Integer.MIN_VALUE);
//        long a = 0;
//        System.out.println(a);

    }

}

http doPost doGet 請求

import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class HttpClientUtil {

	public static String doGet(String url, Map<String, String> param) {

		// 創建Httpclient對象
		CloseableHttpClient httpclient = HttpClients.createDefault();
		String resultString = "";
		CloseableHttpResponse response = null;
		try {

			StringBuilder sb = new StringBuilder(url+"?");
			for (String key : param.keySet()) {
				sb.append(key+"="+param.get(key)+"&");
			}
			sb.deleteCharAt(sb.length()-1);
			URI uri = new URI(sb.toString());
			// 創建http GET請求
			HttpGet httpGet = new HttpGet(uri);

			// 執行請求
			response = httpclient.execute(httpGet);
			// 判斷返回狀態是否為200
			if (response.getStatusLine().getStatusCode() == 200) {
				resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (response != null) {
					response.close();
				}
				httpclient.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return resultString;
	}

	public static String doGet(String url) {
		return doGet(url, null);
	}

	public static String doPost(String url, Map<String, String> param) {
		// 創建Httpclient對象
		CloseableHttpClient httpClient = HttpClients.createDefault();
		CloseableHttpResponse response = null;
		String resultString = "";
		try {
			// 創建Http Post請求
			HttpPost httpPost = new HttpPost(url);
			// 創建參數列表
			if (param != null) {
				List<NameValuePair> paramList = new ArrayList<>();
				for (String key : param.keySet()) {
					paramList.add(new BasicNameValuePair(key, param.get(key)));
				}
				// 模擬表單
				UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList);
				httpPost.setEntity(entity);
			}
			// 執行http請求
			response = httpClient.execute(httpPost);
			resultString = EntityUtils.toString(response.getEntity(), "utf-8");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				response.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		return resultString;
	}

	public static String doPost(String url) {
		return doPost(url, null);
	}
	
	public static String doPostJson(String url, String json) {
		// 創建Httpclient對象
		CloseableHttpClient httpClient = HttpClients.createDefault();
		CloseableHttpResponse response = null;
		String resultString = "";
		try {
			// 創建Http Post請求
			HttpPost httpPost = new HttpPost(url);
			// 創建請求內容
			StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
			httpPost.setEntity(entity);
			// 執行http請求
			response = httpClient.execute(httpPost);
			resultString = EntityUtils.toString(response.getEntity(), "utf-8");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				response.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		return resultString;
	}
}

微信工具類

import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

public class WxUtils {


    //請求xml組裝
    public static String getRequestXml(Map<String,String> parameters){
        StringBuffer sb = new StringBuffer();
        sb.append("<xml>");
        Set es = parameters.entrySet();
        Iterator it = es.iterator();
        while(it.hasNext()) {
            Map.Entry<String,String> entry = (Map.Entry)it.next();
            sb.append("<"+entry.getKey()+">"+entry.getValue()+"</"+entry.getKey()+">");
        }
        sb.append("</xml>");
        return sb.toString();
    }

    /**
     * 隨機字符串生成
     */
    public static String getRandomString(int length) { //length表示生成字符串的長度
        String base = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }
    /**
     * 將xml格式的字符串轉換成Map對象
     *
     * @param xmlStr xml格式的字符串
     * @return Map對象
     * @throws Exception 異常
     */
    public static Map<String, String> xmlStrToMap(String xmlStr) throws Exception {
        if(StringUtils.isEmpty(xmlStr)) {
            return null;
        }
        Map<String, String> map = new HashMap<>();
        //將xml格式的字符串轉換成Document對象
        Document doc = DocumentHelper.parseText(xmlStr);
        //獲取根節點
        Element root = doc.getRootElement();
        //獲取根節點下的所有元素
        List children = root.elements();
        //循環所有子元素
        if(children != null && children.size() > 0) {
            for(int i = 0; i < children.size(); i++) {
                Element child = (Element)children.get(i);
                map.put(child.getName(), child.getTextTrim());
            }
        }
        return map;
    }

    public static <T> T  xmlStrToBean(String xmlStr, Class<T> clazz) throws InstantiationException, IllegalAccessException {
        T obj = clazz.newInstance();
        try {
            // 將xml格式的數據轉換成Map對象
            Map<String, String> map = xmlStrToMap(xmlStr);
            //將map對象的數據轉換成Bean對象
            obj = JSON.parseObject(JSON.toJSONString(map),clazz);

        } catch(Exception e) {
            e.printStackTrace();
        }
        return obj;
    }
    public static String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }



}

微信常量類

public class WxConstants {

    //微信統一下單請求xml參數
    public static final String APPID="wx1111111"; //appid是微信公眾賬號或開放平臺APP的唯一標識
    public static final String MCHID="111111";//商戶申請微信支付后,由微信支付分配的商戶收款賬號
    public static final String SECRET="aaaaaaaa";//AppSecret是APPID對應的接口密碼
    public static final String KEY="1111111111";//交易過程生成簽名的密鑰 同API密鑰
    public static final String NONCE_STR="nonce_str";
    public static final String SIGN="sign";//生成簽名
    public static final String ATTACH="attach";
    public static final String TIMESTAMP = "timeStamp";
    public static final String NONCESTR = "noncestr";
    public static final String PREPAYID = "prepayid";
    public static final String PARTNERID = "111111";//API密鑰
    public static final String PACKAGE = "package";
    public static final String OPENID ="OPENID";//用戶唯一標識
    public static final int getHttpConnectTimeoutMs = 8000;//連接時間
    public static final int getHttpReadTimeoutMs = 10000; //超時時間


    /**
     * 微信 JSAPI支付(或小程序支付)微信中調用網頁支付
     */
    public static final String WX_TRADE_JSAPI = "JSAPI";
    /**
     * 微信 Native支付
     */
    public static final String WX_TRADE_NATIVE = "NATIVE";
    /**
     * 微信 H5支付
     */
    public static final String WX_TRADE_MWEB = "MWEB";
    /**
     * 微信 app支付
     */
    public static final String WX_TRADE_APP = "APP";
    
}

看完上述內容,你們掌握java如何實現微信jsApi支付的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

武定县| 合川市| 洛南县| 美姑县| 闽侯县| 东台市| 梓潼县| 皮山县| 梧州市| 丰原市| 和政县| 白水县| 双鸭山市| 高陵县| 东宁县| 丽江市| 铁力市| 津市市| 潮州市| 土默特右旗| 乌拉特前旗| 六盘水市| 深水埗区| 衡南县| 平南县| 乐至县| 资阳市| 秭归县| 鱼台县| 卓尼县| 湖南省| 双峰县| 蚌埠市| 桦川县| 南投市| 东安县| 南丰县| 庄河市| 沙雅县| 霞浦县| 和硕县|