微信掃碼支付

1 . 註冊獲取微信appid等相關信息   pay.weixin.qq.com

2 . 下載SDK和DEMO文件  https://pay.weixin.qq.com/wiki/doc/api/native_sl.php?chapter=11_1

3 . 複製WxPayUtil.java和WXPayConstants.java 和WXPayXmlUtil.java3個文件到項目以及一個發送請求的工具類

WxPayRequest 


public class WxPayRequest {
	private static int readTimeoutMs = 1000;
	private static int connectTimeoutMs = 1000;

	public static String wxPayRequest(String url,String data) {
		BasicHttpClientConnectionManager connManager = new BasicHttpClientConnectionManager(
				RegistryBuilder.<ConnectionSocketFactory>create()
						.register("http", PlainConnectionSocketFactory.getSocketFactory())
						.register("https", SSLConnectionSocketFactory.getSocketFactory())
						.build(),
				null,
				null,
				null
		);

		HttpClient httpClient = HttpClientBuilder.create()
				.setConnectionManager(connManager)
				.build();

		HttpPost httpPost = new HttpPost(url);

		RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(readTimeoutMs).setConnectTimeout(connectTimeoutMs).build();
		httpPost.setConfig(requestConfig);

		StringEntity postEntity = new StringEntity(data, "UTF-8");
		httpPost.addHeader("Content-Type", "text/xml");
		httpPost.setEntity(postEntity);

		HttpResponse httpResponse = null;
		try {
			httpResponse = httpClient.execute(httpPost);
			HttpEntity httpEntity = httpResponse.getEntity();
			return EntityUtils.toString(httpEntity, "UTF-8");
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
}

4 . 創建一個配置類WxPayConfig.java

public class WxPayConfig {
	//微信支付分配的公衆賬號ID(企業號corpid即爲此appId)
	private String appid;
	//微信支付分配的商戶號
	private String mch_id;
    //支付寶和商戶的密鑰
    private String key;
	//自定義參數,可以爲終端設備號(門店號或收銀設備ID),PC網頁或公衆號內支付可以傳"WEB"
	private String device_info;
	//隨機字符串,長度要求在32位以內。推薦隨機數生成算法
	//private String nonce_str;
	
	//簽名類型,默認爲MD5,支持HMAC-SHA256和MD5。
	private String sign_type;
	//商品簡單描述,該字段請按照規範傳遞,具體請見參數規定
	private String body;
	//商品詳細描述,對於使用單品優惠的商戶,改字段必須按照規範上傳,詳見“單品優惠參數說明”
	private String detail;
	//符合ISO 4217標準的三位字母代碼,默認人民幣:CNY,詳細列表請參見貨幣類型
	private String fee_type;
	//APP和網頁支付提交用戶端ip,Native支付填調用微信支付API的機器IP。
	private String spbill_create_ip;
	//異步接收微信支付結果通知的回調地址,通知url必須爲外網可訪問的url,不能攜帶參數。
	private String notify_url;
	//JSAPI 公衆號支付	NATIVE 掃碼支付	APP APP支付	說明詳見參數規定
	private String trade_type;
	//請求微信生成二維碼的地址


自己生成get/set方法及構造方法

5 . 在spring配置文件中注入配置bean , value根據 微信官網推薦進行配置

<!--微信支付相關配置-->
    <bean id="wxPayConfig" class="cn.itrip.trade.config.WxPayConfig">
        <property name="appid" value="wxab8acb865bb1637e"/>
        <property name="mch_id" value="11473623"/>
         <property name="key" value="dfsfddre32sdrf2"/>
        <property name="device_info" value="013467007045764"/>
        <property name="body" value="騰訊充值中心-QQ會員充值"/>
        <property name="detail" value=""/>
        <property name="fee_type" value="CNY"/>
        <property name="notify_url" value="http://localhost:8080/trade/wxpay/api/notify"/>
       
        <property name="sign_type" value="HMAC-SHA256"/>
        <property name="spbill_create_ip" value="123.12.12.123"/>
        <property name="trade_type" value="JSAPI"/>
        <property name="url" value="https://api.mch.weixin.qq.com/pay/unifiedorder"/>
    </bean>

 6 . 編寫訂單id生成二維碼的controller類方法

        //1.訂單生產二維碼
	@ResponseBody
	@ApiOperation(value = "生成微信支付二維碼")
	@RequestMapping(value = "/pay/{orderNo}",method = RequestMethod.GET)
	public Dto createQRCode(@ApiParam(name = "orderNo",required = true) @PathVariable String orderNo){
		try {
			//1 .獲取訂單信息
			ItripHotelOrder order = orderService.loadItripHotelOrder(orderNo);

			//2 .構造參數
			HashMap<String, String> data = new HashMap<>();

			//訂單信息
			data.put("out_trade_no","orderNo");//訂單id  商戶系統內部訂單號,要求32個字符內,只能是數字、大小寫字母_-|* 且在同一個商戶號下唯一。詳見商戶訂單號

			data.put("total_fee",order.getPayAmount().multiply(new BigDecimal(100)).toBigInteger().toString());//訂單金額,單位分,沒有小數

			data.put("product_id",order.getId().toString());//商品id

			data.put("nonce_str", WXPayUtil.generateNonceStr());//隨機字符串,長度要求在32位以內。推薦隨機數生成算法

			//商戶信息
			data.put("appid",wxPayConfig.getAppid());//微信支付分配的公衆賬號ID(企業號corpid即爲此appId)

			data.put("mch_id",wxPayConfig.getMch_id());//微信支付分配的公衆賬號ID(企業號corpid即爲此appId)

			//商品簡單描述,該字段請按照規範傳遞,具體請見參數規定
			data.put("body",wxPayConfig.getBody());
			//自定義參數,可以爲終端設備號(門店號或收銀設備ID),PC網頁或公衆號內支付可以傳"WEB"
			data.put("device_info",wxPayConfig.getDevice_info());
			//符合ISO 4217標準的三位字母代碼,默認人民幣:CNY,詳細列表請參見貨幣類型
			data.put("fee_type",wxPayConfig.getFee_type());
			//APP和網頁支付提交用戶端ip,Native支付填調用微信支付API的機器IP
			data.put("spbill_create_ip",wxPayConfig.getSpbill_create_ip());
			//異步接收微信支付結果通知的回調地址,通知url必須爲外網可訪問的url,不能攜帶參數。
			data.put("notify_url",wxPayConfig.getNotify_url());
			//JSAPI公衆號支付   NATIVE掃碼支付        APP APP支付    說明詳見參數規定
			data.put("trade_type",wxPayConfig.getTrade_type());

			//	簽名類型,默認爲MD5,支持HMAC-SHA256和MD5
			data.put("sign_type", wxPayConfig.getSign_type());

			String requestXml=null;
			//3.轉換成wx支付的xml
			if (wxPayConfig.getSign_type().equals("MD5")){
				requestXml = WXPayUtil.generateSignedXml(data, wxPayConfig.getKey(), WXPayConstants.SignType.MD5);
			}else {
				requestXml = WXPayUtil.generateSignedXml(data, wxPayConfig.getKey(), WXPayConstants.SignType.HMACSHA256);
			}

			//4. 發送請求獲取二維碼地址
			// url就是請求wx的地址,
			String resultXml = WxPayRequest.wxPayRequest(wxPayConfig.getUrl(), requestXml);
			Map<String, String> responseMap = WXPayUtil.xmlToMap(resultXml);

			if (responseMap.get("return_code").equals("SUCCESS") && responseMap.get("result_code").equals("SUCCESS") ){
				HashMap<String, Object> map = new HashMap<>();
				map.put("code_url",responseMap.get("code_url"));
				return DtoUtils.returnDataSuccess(map);
			}else {
				return DtoUtils.returnFail(responseMap.get("return_msg"),"100002");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return DtoUtils.returnFail("請求二維碼失敗","100002");
	}

7 . 編寫回調方法 , 執行付款成功/失敗的方法

        @ApiOperation(value = "微信支付回調方法 ")
	@RequestMapping(value = "/notify",method = RequestMethod.GET)
	public void wxNotify(HttpServletRequest request, HttpServletResponse response){
		//1 .從回調請求中獲取信息
		StringBuffer stringBuffer = new StringBuffer();
		ServletInputStream inputStream = null;
		String responseXml = null;
		try {
			inputStream = request.getInputStream();
			BufferedReader reader = new BufferedReader(new   InputStreamReader(inputStream));
			String temp;
			while ((temp=reader.readLine())!=null){
				stringBuffer.append(temp);
			}
			reader.close();
			inputStream.close();
			Map<String, String> requestMap = WXPayUtil.xmlToMap(stringBuffer.toString());

			//2 .驗證是否支付成功
			boolean result = false;
			if (wxPayConfig.getSign_type().equals("MD5")){
				result = WXPayUtil.isSignatureValid(requestMap, wxPayConfig.getSign(), WXPayConstants.SignType.MD5);
			}else {
				result = WXPayUtil.isSignatureValid(requestMap, wxPayConfig.getSign(), WXPayConstants.SignType.HMACSHA256);
			}

			Map<String, String> returnMap = new HashMap<>();
			//3.成功,修改訂單信息
			if (result){
				if (requestMap.get("return_code").equals("SUCCESS") && requestMap.get("result_code").equals("SUCCESS") ){
					orderService.paySuccess(requestMap.get("out_trade_no"),2,requestMap.get("prepay_id"));
					returnMap.put("return_code","SUCCESS");
					returnMap.put("return_msg","SUCCESS");
				}else {
					orderService.payFail(requestMap.get("out_trade_no"),2,requestMap.get("prepay_id"));
					returnMap.put("return_code","FAIL");
					returnMap.put("return_msg","付款失敗!");
				}
			}else {
				returnMap.put("return_code","FAIL");
				returnMap.put("return_msg","付款失敗!");
			}
			responseXml = WXPayUtil.generateSignedXml(returnMap, wxPayConfig.getSign(), WXPayConstants.SignType.MD5);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			try {
				response.getWriter().write(responseXml);
				response.getWriter().flush();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章