本文解釋了Java如何實現(xiàn)JsApi方式的微信支付,代碼內(nèi)容詳細(xì),文章思路清晰,需要的朋友可以參考下
要使用JsApi進行微信支付,首先要從微信獲得一個prepay_id,然後透過呼叫微信的jsapi完成支付,JS API的回傳結(jié)果get_brand_wcpay_request:ok僅在使用者成功完成支付時傳回。由於前端互動複雜,get_brand_wcpay_request:cancel或get_brand_wcpay_request:fail可以統(tǒng)一處理為使用者遇到錯誤或主動放棄,不必細(xì)化區(qū)分。
範(fàn)例程式碼如下:
function?onBridgeReady(){ ?WeixinJSBridge.invoke( ?'getBrandWCPayRequest',?{ ??"appId"?:?"wx2421b1c4370ec43b",?//公眾號名稱,由商戶傳入? ??"timeStamp":"?1395712654",??//時間戳,自1970年以來的秒數(shù)? ??"nonceStr"?:?"e61463f8efa94090b1f366cccfbbb444",?//隨機串? ??"package"?:?"u802345jgfjsdfgsdg888",? ??"signType"?:?"MD5",??//微信簽名方式:? ??"paySign"?:?"70EA570631E4BB79628FBCA90534C63FF7FADD89"?//微信簽名? ?}, ?function(res){? ??if(res.err_msg?==?"get_brand_wcpay_request:ok"?)?{}?//?使用以上方式判斷前端返回,微信團隊鄭重提示:res.err_msg將在用戶支付成功后返回?ok,但并不保證它絕對可靠。? ?} ?);? } 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(); }
以上傳入的參數(shù)package,也就是為prepay_id
下面講的是取得參數(shù)來呼叫jsapi
我們呼叫JSAPI時,必須取得用戶的openid,(trade_type=JSAPI,openid為必填參數(shù)。)
先定義一個請求的物件:
package?com.unstoppedable.protocol; import?com.unstoppedable.common.Configure; import?com.unstoppedable.common.HttpService; import?com.unstoppedable.common.RandomStringGenerator; import?com.unstoppedable.common.Signature; import?java.lang.reflect.Field; import?java.util.HashMap; import?java.util.Map; public?class?UnifiedOrderReqData?{ ?private?String?appid; ?private?String?mch_id; ?private?String?device_info; ?private?String?nonce_str; ?private?String?sign; ?private?String?body; ?private?String?detail; ?private?String?attach; ?private?String?out_trade_no; ?private?String?fee_type; ?private?int?total_fee; ?private?String?spbill_create_ip; ?private?String?time_start; ?private?String?time_expire; ?private?String?goods_tag; ?private?String?notify_url; ?private?String?trade_type; ?private?String?product_id; ?private?String?limit_pay; ?private?String?openid; ?private?UnifiedOrderReqData(UnifiedOrderReqDataBuilder?builder)?{ ?this.appid?=?builder.appid; ?this.mch_id?=?builder.mch_id; ?this.device_info?=?builder.device_info; ?this.nonce_str?=?RandomStringGenerator.getRandomStringByLength(32); ?this.body?=?builder.body; ?this.detail?=?builder.detail; ?this.attach?=?builder.attach; ?this.out_trade_no?=?builder.out_trade_no; ?this.fee_type?=?builder.fee_type; ?this.total_fee?=?builder.total_fee; ?this.spbill_create_ip?=?builder.spbill_create_ip; ?this.time_start?=?builder.time_start; ?this.time_expire?=?builder.time_expire; ?this.goods_tag?=?builder.goods_tag; ?this.notify_url?=?builder.notify_url; ?this.trade_type?=?builder.trade_type; ?this.product_id?=?builder.product_id; ?this.limit_pay?=?builder.limit_pay; ?this.openid?=?builder.openid; ?this.sign?=?Signature.getSign(toMap()); ?} ?public?void?setAppid(String?appid)?{ ?this.appid?=?appid; ?} ?public?void?setMch_id(String?mch_id)?{ ?this.mch_id?=?mch_id; ?} ?public?void?setDevice_info(String?device_info)?{ ?this.device_info?=?device_info; ?} ?public?void?setNonce_str(String?nonce_str)?{ ?this.nonce_str?=?nonce_str; ?} ?public?void?setSign(String?sign)?{ ?this.sign?=?sign; ?} ?public?void?setBody(String?body)?{ ?this.body?=?body; ?} ?public?void?setDetail(String?detail)?{ ?this.detail?=?detail; ?} ?public?void?setAttach(String?attach)?{ ?this.attach?=?attach; ?} ?public?void?setOut_trade_no(String?out_trade_no)?{ ?this.out_trade_no?=?out_trade_no; ?} ?public?void?setFee_type(String?fee_type)?{ ?this.fee_type?=?fee_type; ?} ?public?void?setTotal_fee(int?total_fee)?{ ?this.total_fee?=?total_fee; ?} ?public?void?setSpbill_create_ip(String?spbill_create_ip)?{ ?this.spbill_create_ip?=?spbill_create_ip; ?} ?public?void?setTime_start(String?time_start)?{ ?this.time_start?=?time_start; ?} ?public?void?setTime_expire(String?time_expire)?{ ?this.time_expire?=?time_expire; ?} ?public?void?setGoods_tag(String?goods_tag)?{ ?this.goods_tag?=?goods_tag; ?} ?public?void?setNotify_url(String?notify_url)?{ ?this.notify_url?=?notify_url; ?} ?public?void?setTrade_type(String?trade_type)?{ ?this.trade_type?=?trade_type; ?} ?public?void?setProduct_id(String?product_id)?{ ?this.product_id?=?product_id; ?} ?public?void?setLimit_pay(String?limit_pay)?{ ?this.limit_pay?=?limit_pay; ?} ?public?void?setOpenid(String?openid)?{ ?this.openid?=?openid; ?} ?public?Map<String, Object>?toMap()?{ ?Map<String, Object>?map?=?new?HashMap<String, Object>(); ?Field[]?fields?=?this.getClass().getDeclaredFields(); ?for?(Field?field?:?fields)?{ ??Object?obj; ??try?{ ??obj?=?field.get(this); ??if?(obj?!=?null)?{ ???map.put(field.getName(),?obj); ??} ??}?catch?(IllegalArgumentException?e)?{ ??e.printStackTrace(); ??}?catch?(IllegalAccessException?e)?{ ??e.printStackTrace(); ??} ?} ?return?map; ?} ?public?static?class?UnifiedOrderReqDataBuilder?{ ?private?String?appid; ?private?String?mch_id; ?private?String?device_info; ?private?String?body; ?private?String?detail; ?private?String?attach; ?private?String?out_trade_no; ?private?String?fee_type; ?private?int?total_fee; ?private?String?spbill_create_ip; ?private?String?time_start; ?private?String?time_expire; ?private?String?goods_tag; ?private?String?notify_url; ?private?String?trade_type; ?private?String?product_id; ?private?String?limit_pay; ?private?String?openid; ?public?UnifiedOrderReqDataBuilder(String?appid,?String?mch_id,?String?body,?String?out_trade_no,?Integer?total_fee, ??????String?spbill_create_ip,?String?notify_url,?String?trade_type)?{ ??if?(appid?==?null)?{ ??throw?new?IllegalArgumentException("傳入?yún)?shù)appid不能為null"); ??} ??if?(mch_id?==?null)?{ ??throw?new?IllegalArgumentException("傳入?yún)?shù)mch_id不能為null"); ??} ??if?(body?==?null)?{ ??throw?new?IllegalArgumentException("傳入?yún)?shù)body不能為null"); ??} ??if?(out_trade_no?==?null)?{ ??throw?new?IllegalArgumentException("傳入?yún)?shù)out_trade_no不能為null"); ??} ??if?(total_fee?==?null)?{ ??throw?new?IllegalArgumentException("傳入?yún)?shù)total_fee不能為null"); ??} ??if?(spbill_create_ip?==?null)?{ ??throw?new?IllegalArgumentException("傳入?yún)?shù)spbill_create_ip不能為null"); ??} ??if?(notify_url?==?null)?{ ??throw?new?IllegalArgumentException("傳入?yún)?shù)notify_url不能為null"); ??} ??if?(trade_type?==?null)?{ ??throw?new?IllegalArgumentException("傳入?yún)?shù)trade_type不能為null"); ??} ??this.appid?=?appid; ??this.mch_id?=?mch_id; ??this.body?=?body; ??this.out_trade_no?=?out_trade_no; ??this.total_fee?=?total_fee; ??this.spbill_create_ip?=?spbill_create_ip; ??this.notify_url?=?notify_url; ??this.trade_type?=?trade_type; ?} ?public?UnifiedOrderReqDataBuilder?setDevice_info(String?device_info)?{ ??this.device_info?=?device_info; ??return?this; ?} ?public?UnifiedOrderReqDataBuilder?setDetail(String?detail)?{ ??this.detail?=?detail; ??return?this; ?} ?public?UnifiedOrderReqDataBuilder?setAttach(String?attach)?{ ??this.attach?=?attach; ??return?this; ?} ?public?UnifiedOrderReqDataBuilder?setFee_type(String?fee_type)?{ ??this.fee_type?=?fee_type; ??return?this; ?} ?public?UnifiedOrderReqDataBuilder?setTime_start(String?time_start)?{ ??this.time_start?=?time_start; ??return?this; ?} ?public?UnifiedOrderReqDataBuilder?setTime_expire(String?time_expire)?{ ??this.time_expire?=?time_expire; ??return?this; ?} ?public?UnifiedOrderReqDataBuilder?setGoods_tag(String?goods_tag)?{ ??this.goods_tag?=?goods_tag; ??return?this; ?} ?public?UnifiedOrderReqDataBuilder?setProduct_id(String?product_id)?{ ??this.product_id?=?product_id; ??return?this; ?} ?public?UnifiedOrderReqDataBuilder?setLimit_pay(String?limit_pay)?{ ??this.limit_pay?=?limit_pay; ??return?this; ?} ?public?UnifiedOrderReqDataBuilder?setOpenid(String?openid)?{ ??this.openid?=?openid; ??return?this; ?} ?public?UnifiedOrderReqData?build()?{ ??if("JSAPI".equals(this.trade_type)?&&?this.openid?==?null)?{ ??throw?new?IllegalArgumentException("當(dāng)傳入trade_type為JSAPI時,openid為必填參數(shù)"); ??} ??if("NATIVE".equals(this.trade_type)?&&?this.product_id?==?null)?{ ??throw?new?IllegalArgumentException("當(dāng)傳入trade_type為NATIVE時,product_id為必填參數(shù)"); ??} ??return?new?UnifiedOrderReqData(this); ?} ?} }
因為有些參數(shù)為必填,有些參數(shù)為選填。而且sign要等所有參數(shù)傳入之後才能計算的出,所以這裡用了builder模式。關(guān)於builder模式。
我們選用httpclient進行網(wǎng)路傳輸。
package?com.unstoppedable.common; import?com.thoughtworks.xstream.XStream; import?com.thoughtworks.xstream.io.xml.DomDriver; import?com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder; import?org.apache.commons.logging.Log; import?org.apache.commons.logging.LogFactory; import?org.apache.http.HttpEntity; import?org.apache.http.HttpResponse; import?org.apache.http.client.ClientProtocolException; import?org.apache.http.client.ResponseHandler; import?org.apache.http.client.config.RequestConfig; import?org.apache.http.client.methods.HttpGet; import?org.apache.http.client.methods.HttpPost; import?org.apache.http.conn.ConnectTimeoutException; import?org.apache.http.conn.ConnectionPoolTimeoutException; import?org.apache.http.conn.ssl.SSLConnectionSocketFactory; import?org.apache.http.conn.ssl.SSLContexts; import?org.apache.http.entity.StringEntity; import?org.apache.http.impl.client.CloseableHttpClient; import?org.apache.http.impl.client.HttpClients; import?org.apache.http.util.EntityUtils; import?javax.net.ssl.SSLContext; import?java.io.File; import?java.io.FileInputStream; import?java.io.IOException; import?java.net.SocketTimeoutException; import?java.security.KeyStore; /** ?*?Created?by?hupeng?on?2015/7/28. ?*/ public?class?HttpService?{ ?private?static?Log?logger?=?LogFactory.getLog(HttpService.class); ?private?static?CloseableHttpClient?httpClient?=?buildHttpClient(); ?//連接超時時間,默認(rèn)10秒 ?private?static?int?socketTimeout?=?5000; ?//傳輸超時時間,默認(rèn)30秒 ?private?static?int?connectTimeout?=?5000; ?private?static?int?requestTimeout?=?5000; ?public?static?CloseableHttpClient?buildHttpClient()?{ ?try?{ ??KeyStore?keyStore?=?KeyStore.getInstance("PKCS12"); ??FileInputStream?instream?=?new?FileInputStream(new?File(Configure.getCertLocalPath()));//加載本地的證書進行https加密傳輸 ??try?{ ??keyStore.load(instream,?Configure.getCertPassword().toCharArray());//設(shè)置證書密碼 ??}?finally?{ ??instream.close(); ??} ??//?Trust?own?CA?and?all?self-signed?certs ??SSLContext?sslcontext?=?SSLContexts.custom() ???.loadKeyMaterial(keyStore,?Configure.getCertPassword().toCharArray()) ???.build(); ??//?Allow?TLSv1?protocol?only ??SSLConnectionSocketFactory?sslsf?=?new?SSLConnectionSocketFactory( ???sslcontext, ???new?String[]{"TLSv1"}, ???null, ???SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); ??RequestConfig?requestConfig?=?RequestConfig.custom() ???.setConnectTimeout(connectTimeout) ???.setConnectionRequestTimeout(requestTimeout) ???.setSocketTimeout(socketTimeout).build(); ??httpClient?=?HttpClients.custom() ???.setDefaultRequestConfig(requestConfig) ???.setSSLSocketFactory(sslsf) ???.build(); ??return?httpClient; ?}?catch?(Exception?e)?{ ??throw?new?RuntimeException("error?create?httpclient......",?e); ?} ?} ?public?static?String?doGet(String?requestUrl)?throws?Exception?{ ?HttpGet?httpget?=?new?HttpGet(requestUrl); ?try?{ ??logger.debug("Executing?request?"?+?httpget.getRequestLine()); ??//?Create?a?custom?response?handler ??ResponseHandler<String>?responseHandler?=?new?ResponseHandler<String>()?{ ??@Override ??public?String?handleResponse( ???final?HttpResponse?response)?throws?ClientProtocolException,?IOException?{ ???int?status?=?response.getStatusLine().getStatusCode(); ???if?(status?>=?200?&&?status?< 300) { HttpEntity entity = response.getEntity(); return entity != null ? EntityUtils.toString(entity) : null; } else { throw new ClientProtocolException("Unexpected response status: " + status); } } }; return httpClient.execute(httpget, responseHandler); } finally { httpget.releaseConnection(); } } public static String doPost(String url, Object object2Xml) { String result = null; HttpPost httpPost = new HttpPost(url); //解決XStream對出現(xiàn)雙下劃線的bug XStream xStreamForRequestPostData = new XStream(new DomDriver("UTF-8", new XmlFriendlyNameCoder("-_", "_"))); //將要提交給API的數(shù)據(jù)對象轉(zhuǎn)換成XML格式數(shù)據(jù)Post給API String postDataXML = xStreamForRequestPostData.toXML(object2Xml); logger.info("API,POST過去的數(shù)據(jù)是:"); logger.info(postDataXML); //得指明使用UTF-8編碼,否則到API服務(wù)器XML的中文不能被成功識別 StringEntity postEntity = new StringEntity(postDataXML, "UTF-8"); httpPost.addHeader("Content-Type", "text/xml"); httpPost.setEntity(postEntity); //設(shè)置請求器的配置 logger.info("executing request" + httpPost.getRequestLine()); try { HttpResponse response = httpClient.execute(httpPost); HttpEntity entity = response.getEntity(); result = EntityUtils.toString(entity, "UTF-8"); } catch (ConnectionPoolTimeoutException e) { logger.error("http get throw ConnectionPoolTimeoutException(wait time out)", e); } catch (ConnectTimeoutException e) { logger.error("http get throw ConnectTimeoutException", e); } catch (SocketTimeoutException e) { logger.error("http get throw SocketTimeoutException", e); } catch (Exception e) { logger.error("http get throw Exception", e); } finally { httpPost.abort(); } return result; } }
然後是我們的總?cè)肟冢?/p>
package com.unstoppedable.service; import com.unstoppedable.common.Configure; import com.unstoppedable.common.HttpService; import com.unstoppedable.common.XMLParser; import com.unstoppedable.protocol.UnifiedOrderReqData; import org.xml.sax.SAXException; import javax.xml.parsers.ParserConfigurationException; import java.io.IOException; import java.util.Map; /** * Created by hupeng on 2015/7/28. */ public class WxPayApi { public static Map<String,Object>?UnifiedOrder(UnifiedOrderReqData?reqData)?throws?IOException,?SAXException,?ParserConfigurationException?{ ?String?res?=?HttpService.doPost(Configure.UNIFIED_ORDER_API,?reqData); ?return?XMLParser.getMapFromXML(res); ?} ?public?static?void?main(String[]?args)?throws?Exception?{ ?UnifiedOrderReqData?reqData?=?new?UnifiedOrderReqData.UnifiedOrderReqDataBuilder("appid",?"mch_id",?"body",?"out_trade_no",?1,?"spbill_create_ip",?"notify_url",?"JSAPI").setOpenid("openid").build(); ?System.out.println(UnifiedOrder(reqData)); ?} }
回傳的xml為:
<xml> ?<return_code><![CDATA[SUCCESS]]></return_code> ?<return_msg><![CDATA[OK]]></return_msg> ?<appid><![CDATA[wx2421b1c4370ec43b]]></appid> ?<mch_id><![CDATA[10000100]]></mch_id> ?<nonce_str><![CDATA[IITRi8Iabbblz1Jc]]></nonce_str> ?<sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign> ?<result_code><![CDATA[SUCCESS]]></result_code> ?<prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id> ?<trade_type><![CDATA[JSAPI]]></trade_type> </xml>
return_code 和result_code都為SUCCESS的時候會回傳我們需要的prepay_id。 。 。 ,然後在jsapi中使用他就可以了。 。
以上是詳解Java透過JsApi方式實作微信支付方法的詳細(xì)內(nèi)容。更多資訊請關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

熱AI工具

Undress AI Tool
免費脫衣圖片

Undresser.AI Undress
人工智慧驅(qū)動的應(yīng)用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發(fā)環(huán)境

Dreamweaver CS6
視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)