Java中的微信支付

微信支付文檔上有刷卡支付,掃碼支付,公衆號支付,APP支付等各類支付手段。本次就微信內打開的網頁支付爲例子,用java進行實現一下。微信內網頁支付能夠將其歸屬爲公衆號支付。javascript

1、設置支付目錄

打開微信商戶平臺,設置路徑:商戶平臺-->產品中心-->開發配置,如圖7.7所示。公衆號支付在請求支付的時候會校驗請求來源是否有在商戶平臺作了配置,因此必須確保支付目錄已經正確的被配置,不然將驗證失敗,請求支付不成功。前端

支付目錄配置

2、設置受權域名

開發公衆號支付時,在統一下單接口中要求必傳用戶openid,而獲取openid則須要您在公衆平臺設置獲取openid的域名,只有被設置過的域名纔是一個有效的獲取openid的域名,不然將獲取失敗。java

微信網頁受權域名

完成以上兩步後,微信端的支付端口就可以被咱們的網站調用了。git

3、分析業務時序圖

微信在官方文檔中用時序圖反映了其對應的業務流程。github

微信內網頁支付時序圖

根據此圖,能夠看出流程大體爲:本身的java後臺生成付款連接,用戶點擊連接,在java後臺中生成商戶訂單,將此訂單按照微信的格式發送給微信支付系統,微信支付系統生成一個預付單給java後臺,而後在java後臺中生成支付參數返回給用戶,用戶點擊付款,會向微信支付系統檢查支付參數的合法性,確認無誤後便可完成付款操做。付款完成後異步通知商戶付款結果,並會跳到指定的付款成功頁面。ajax

4、java實現

一、首先須要調用微信支付的包,加入到pom.xml中。json

<dependency>
		    <groupId>com.github.wxpay</groupId>
		    <artifactId>wxpay-sdk</artifactId>
		    <version>0.0.3</version>
		</dependency>

二、在頁面中,須要點擊支付按鈕發生的事件以下,首先跳轉到本身的後臺,返回支付所須要的支付參數,並存進js的元素中,留給pay2()使用。其中'${redirect_uri}'這個值是本身以前填進去的域名。只不過這裏我爲了方便管理,講其寫入了配置文件,可讓其做爲後臺返回的一個值傳進js中。微信

function pay(){
   	 var redirect_uri = 'http://'+'${redirect_uri}'+"/xjwUtil/mobile/user/pay/";
   	 jQuery.ajax({
 		url : redirect_uri,
 		datatype : 'json',
 		type : "Post",
 		scriptCharset: 'utf-8',
 		contentType: "application/x-www-form-urlencoded; charset=utf-8",
 		success : function(data) {
 			var d = eval('('+data +')');
 			jQuery('#appId').val();
 			jQuery('#timeStamp').val(d.timeStamp);
 			jQuery('#nonceStr').val(d.nonceStr);
 			jQuery('#signType').val(d.signType);
 			jQuery('#paySign').val(d.paySign);
 			jQuery('#package').val(d.pk);
 			pay2();
 		}
 	})
}

三、經過"mobile/user/pay/"這個地址對應的java處理Controller以下代碼所示,目的是返回支付所須要的參數值。其中openId這一參數是在用戶使用微信登陸時被我存入session中的。重點在於WXPayExample.yy(openId)這裏,這個類是經過openId獲取預付款信息的通道。session

Controller.java app

@RequestMapping(value = "/pay/", method = RequestMethod.POST)
@ResponseBody  
	public String pay(HttpServletRequest req, HttpServletResponse resp){
		Map<String,String> m= new HashMap<String,String>();
		try {
		req.setCharacterEncoding("utf-8");
		String openId=(String)req.getSession().getAttribute("openId");
		Map<String,String> result=WXPayExample.yy(openId);
		String nonceStr=result.get("nonce_str");
		String package1="prepay_id="+result.get("prepay_id");
		m.put("appId","************");
		m.put("package", package1);
		m.put("nonceStr", nonceStr);
		long time=System.currentTimeMillis()/1000;
		m.put("timeStamp",time+"");
	    m.put("signType", "MD5");
		m.put("paySign", WXPayUtil.generateSignature(m,"*********************", SignType.MD5));
		String reqBody =WXPayUtil.mapToXml(m);
		m.put("pk", package1);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	    String result1 = JSON.toJSONString(m);
        return result1; 
	}

在WXPayExample類中,第一步仍是經過MyConfig()配置獲取服務號APPID,商戶號,和Key,而且加載支付證書。而後填寫支付信息中的隨機碼,支付金額,付款方式,付款URL等。而後由WXPay將其添加簽名,WxPayUtil將其轉化爲xml文件,經過wxpay.unifiedOrder(data)發送給微信支付平臺,並獲取返回值。其中這個三個包均可以須要導入

import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayConstants.SignType;
import com.github.wxpay.sdk.WXPayUtil;

WXPayExample.java 

public static Map<String,String>  yy(String openId) throws Exception {
        MyConfig config = new MyConfig();
        WXPay wxpay = new WXPay(config);
        Map<String, String> data = new HashMap<String, String>();
        data.put("body", "xx");
        data.put("out_trade_no", WXPayUtil.generateNonceStr());
        data.put("device_info", "");
        data.put("fee_type", "CNY");
        data.put("total_fee", "1");
        data.put("spbill_create_ip", "192.168.31.166");
        data.put("openid",openId);
        data.put("notify_url", "http://"+GetPeizhi.serverName+"/xjwUtil");
        data.put("trade_type", "JSAPI"); 
        try {
        	Map<String, String> data2 = wxpay.fillRequestData(data);
        	String reqBody =WXPayUtil.mapToXml(data2);
        	System.out.println(reqBody);
            Map<String, String> resp = wxpay.unifiedOrder(data);
            System.out.println(resp);
            return resp;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

MyConfig.java

import com.github.wxpay.sdk.WXPayConfig;
import java.io.*;
public class MyConfig implements WXPayConfig{

    private byte[] certData;

    public MyConfig() throws Exception {
    	String certPath=this.getClass().getResource("/*****證書******").getPath();
        File file = new File(certPath);
        InputStream certStream = new FileInputStream(file);
        this.certData = new byte[(int) file.length()];
        certStream.read(this.certData);
        certStream.close();
    }

    public String getAppID() {
        return "***********";
    }

    public String getMchID() {
        return "***********";
        
    }

    public String getKey() {
        return "***********";
    }

    public InputStream getCertStream() {
        ByteArrayInputStream certBis = new ByteArrayInputStream(this.certData);
        return certBis;
    }

    public int getHttpConnectTimeoutMs() {
        return 8000;
    }

    public int getHttpReadTimeoutMs() {
        return 10000;
    }
}

4,這個時候,就已經能夠拿到預付款信息了。裏面有一個預付款prepay_id就是微信平臺中的該條預付款信息的ID。將返回的nonceStr,prepay_id按照要求封裝爲package與其餘的參數打包在一塊兒。並添加一個簽名。而後把簽名和其餘全部的標籤放進map集合後,轉成result1發送給頁面。用戶既能夠選擇支付了。

五、用戶支付的javascript。回到cart.jsp中,第二步中的ajax獲取到返回值以後,就能夠進行下一步操做了。pay2()這一個function是用戶支付指令的發送,當微信支付準備好了以後,經過onBridgeReady()這一方法進行付款,若是付款成功,調用success方法,失敗後直接跳轉到失敗頁面。至此,這個整個過程就宣告結束。

cart.jsp

function pay2() {
		var appId = jQuery('#appId').val();
		var timeStamp = jQuery('#timeStamp').val();
		var nonceStr = jQuery('#nonceStr').val();
		var signType = jQuery('#signType').val();
		var pk = jQuery('#package').val();
		var paySign = jQuery('#paySign').val();
		if (typeof WeixinJSBridge == "undefined") {
			if (document.addEventListener) {
				document.addEventListener('WeixinJSBridgeReady', onBridgeReady,
						false);
			} else if (document.attachEvent) {
				document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
				document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
			}

		} else {
			onBridgeReady();
		}
		function onBridgeReady() {
			console.log(appId + "==" + timeStamp + "==" + nonceStr + "==" + pk
					+ "==" + "MD5" + "==" + paySign + "")
			WeixinJSBridge.invoke('getBrandWCPayRequest', {
				"appId" : appId, //公衆號名稱,由商戶傳入     
				"timeStamp" : timeStamp, //時間戳,自1970年以來的秒數     
				"nonceStr" : nonceStr, //隨機串     
				"package" : pk,
				"signType" : "MD5", //微信簽名方式:     
				"paySign" : paySign
			//微信簽名 
			}, function(res) {
				if (res.err_msg == "get_brand_wcpay_request:ok") {
					success();
				} // 使用以上方式判斷前端返回,微信團隊鄭重提示:res.err_msg將在用戶支付成功後返回    ok,但並不保證它絕對可靠。 
				else{
					window.location.href="${pageContext.request.contextPath}/mobile/user/payfail/"
					
				}
			});
		}
	}
  function success(){
    	 jQuery.ajax({
    	 		url : "${pageContext.request.contextPath}/mobile/user/paysuccess/",
    	 		datatype : 'json',
    	 		type : "Post",
    	 		scriptCharset: 'utf-8',
    	 		contentType: "application/x-www-form-urlencoded; charset=utf-8",
    	 		success : function(data) {
    	 			window.location.href="${pageContext.request.contextPath}/mobile/user/success2"
    	 		}
    	 	})
    }

5、另附

使用微信支付時須要用到appId這一變量。在上文中appId經過session取出,初次使用appID 的獲取方法以下:

仍是在下一篇博客寫吧。。。

相關文章
相關標籤/搜索