Java通过JsApi方式实现微信支付
要使用JsApi进行微信支付,首先要从微信获得一个prepay_id,然后通过调用微信的jsapi完成支付,JSAPI的返回结果get_brand_wcpay_request:ok仅在用户成功完成支付时返回。由于前端交互复杂,get_brand_wcpay_request:cancel或者get_brand_wcpay_request:fail可以统一处理为用户遇到错误或者主动放弃,不必细化区分。
示例代码如下:
functiononBridgeReady(){ WeixinJSBridge.invoke( 'getBrandWCPayRequest',{ "appId":"wx2421b1c4370ec43b",//公众号名称,由商户传入 "timeStamp":"1395712654",//时间戳,自1970年以来的秒数 "nonceStr":"e61463f8efa94090b1f366cccfbbb444",//随机串 "package":"u802345jgfjsdfgsdg888", "signType":"MD5",//微信签名方式: "paySign":"70EA570631E4BB79628FBCA90534C63FF7FADD89"//微信签名 }, function(res){ if(res.err_msg=="get_brand_wcpay_request:ok"){}//使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。 } ); } if(typeofWeixinJSBridge=="undefined"){ if(document.addEventListener){ document.addEventListener('WeixinJSBridgeReady',onBridgeReady,false); }elseif(document.attachEvent){ document.attachEvent('WeixinJSBridgeReady',onBridgeReady); document.attachEvent('onWeixinJSBridgeReady',onBridgeReady); } }else{ onBridgeReady(); }
以上传入的参数package,即为prepay_id
下面讲的是获得参数来调用jsapi
我们调用JSAPI时,必须获得用户的openid,(trade_type=JSAPI,openid为必填参数。)
首先定义一个请求的对象:
packagecom.unstoppedable.protocol; importcom.unstoppedable.common.Configure; importcom.unstoppedable.common.HttpService; importcom.unstoppedable.common.RandomStringGenerator; importcom.unstoppedable.common.Signature; importjava.lang.reflect.Field; importjava.util.HashMap; importjava.util.Map; publicclassUnifiedOrderReqData{ privateStringappid; privateStringmch_id; privateStringdevice_info; privateStringnonce_str; privateStringsign; privateStringbody; privateStringdetail; privateStringattach; privateStringout_trade_no; privateStringfee_type; privateinttotal_fee; privateStringspbill_create_ip; privateStringtime_start; privateStringtime_expire; privateStringgoods_tag; privateStringnotify_url; privateStringtrade_type; privateStringproduct_id; privateStringlimit_pay; privateStringopenid; privateUnifiedOrderReqData(UnifiedOrderReqDataBuilderbuilder){ 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()); } publicvoidsetAppid(Stringappid){ this.appid=appid; } publicvoidsetMch_id(Stringmch_id){ this.mch_id=mch_id; } publicvoidsetDevice_info(Stringdevice_info){ this.device_info=device_info; } publicvoidsetNonce_str(Stringnonce_str){ this.nonce_str=nonce_str; } publicvoidsetSign(Stringsign){ this.sign=sign; } publicvoidsetBody(Stringbody){ this.body=body; } publicvoidsetDetail(Stringdetail){ this.detail=detail; } publicvoidsetAttach(Stringattach){ this.attach=attach; } publicvoidsetOut_trade_no(Stringout_trade_no){ this.out_trade_no=out_trade_no; } publicvoidsetFee_type(Stringfee_type){ this.fee_type=fee_type; } publicvoidsetTotal_fee(inttotal_fee){ this.total_fee=total_fee; } publicvoidsetSpbill_create_ip(Stringspbill_create_ip){ this.spbill_create_ip=spbill_create_ip; } publicvoidsetTime_start(Stringtime_start){ this.time_start=time_start; } publicvoidsetTime_expire(Stringtime_expire){ this.time_expire=time_expire; } publicvoidsetGoods_tag(Stringgoods_tag){ this.goods_tag=goods_tag; } publicvoidsetNotify_url(Stringnotify_url){ this.notify_url=notify_url; } publicvoidsetTrade_type(Stringtrade_type){ this.trade_type=trade_type; } publicvoidsetProduct_id(Stringproduct_id){ this.product_id=product_id; } publicvoidsetLimit_pay(Stringlimit_pay){ this.limit_pay=limit_pay; } publicvoidsetOpenid(Stringopenid){ this.openid=openid; } publicMap<String,Object>toMap(){ Map<String,Object>map=newHashMap<String,Object>(); Field[]fields=this.getClass().getDeclaredFields(); for(Fieldfield:fields){ Objectobj; try{ obj=field.get(this); if(obj!=null){ map.put(field.getName(),obj); } }catch(IllegalArgumentExceptione){ e.printStackTrace(); }catch(IllegalAccessExceptione){ e.printStackTrace(); } } returnmap; } publicstaticclassUnifiedOrderReqDataBuilder{ privateStringappid; privateStringmch_id; privateStringdevice_info; privateStringbody; privateStringdetail; privateStringattach; privateStringout_trade_no; privateStringfee_type; privateinttotal_fee; privateStringspbill_create_ip; privateStringtime_start; privateStringtime_expire; privateStringgoods_tag; privateStringnotify_url; privateStringtrade_type; privateStringproduct_id; privateStringlimit_pay; privateStringopenid; publicUnifiedOrderReqDataBuilder(Stringappid,Stringmch_id,Stringbody,Stringout_trade_no,Integertotal_fee, Stringspbill_create_ip,Stringnotify_url,Stringtrade_type){ if(appid==null){ thrownewIllegalArgumentException("传入参数appid不能为null"); } if(mch_id==null){ thrownewIllegalArgumentException("传入参数mch_id不能为null"); } if(body==null){ thrownewIllegalArgumentException("传入参数body不能为null"); } if(out_trade_no==null){ thrownewIllegalArgumentException("传入参数out_trade_no不能为null"); } if(total_fee==null){ thrownewIllegalArgumentException("传入参数total_fee不能为null"); } if(spbill_create_ip==null){ thrownewIllegalArgumentException("传入参数spbill_create_ip不能为null"); } if(notify_url==null){ thrownewIllegalArgumentException("传入参数notify_url不能为null"); } if(trade_type==null){ thrownewIllegalArgumentException("传入参数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; } publicUnifiedOrderReqDataBuildersetDevice_info(Stringdevice_info){ this.device_info=device_info; returnthis; } publicUnifiedOrderReqDataBuildersetDetail(Stringdetail){ this.detail=detail; returnthis; } publicUnifiedOrderReqDataBuildersetAttach(Stringattach){ this.attach=attach; returnthis; } publicUnifiedOrderReqDataBuildersetFee_type(Stringfee_type){ this.fee_type=fee_type; returnthis; } publicUnifiedOrderReqDataBuildersetTime_start(Stringtime_start){ this.time_start=time_start; returnthis; } publicUnifiedOrderReqDataBuildersetTime_expire(Stringtime_expire){ this.time_expire=time_expire; returnthis; } publicUnifiedOrderReqDataBuildersetGoods_tag(Stringgoods_tag){ this.goods_tag=goods_tag; returnthis; } publicUnifiedOrderReqDataBuildersetProduct_id(Stringproduct_id){ this.product_id=product_id; returnthis; } publicUnifiedOrderReqDataBuildersetLimit_pay(Stringlimit_pay){ this.limit_pay=limit_pay; returnthis; } publicUnifiedOrderReqDataBuildersetOpenid(Stringopenid){ this.openid=openid; returnthis; } publicUnifiedOrderReqDatabuild(){ if("JSAPI".equals(this.trade_type)&&this.openid==null){ thrownewIllegalArgumentException("当传入trade_type为JSAPI时,openid为必填参数"); } if("NATIVE".equals(this.trade_type)&&this.product_id==null){ thrownewIllegalArgumentException("当传入trade_type为NATIVE时,product_id为必填参数"); } returnnewUnifiedOrderReqData(this); } } }
因为有些参数为必填,有些参数为选填。而且sign要等所有参数传入之后才能计算的出,所以这里用了builder模式。关于builder模式。
我们选用httpclient进行网络传输。
packagecom.unstoppedable.common; importcom.thoughtworks.xstream.XStream; importcom.thoughtworks.xstream.io.xml.DomDriver; importcom.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder; importorg.apache.commons.logging.Log; importorg.apache.commons.logging.LogFactory; importorg.apache.http.HttpEntity; importorg.apache.http.HttpResponse; importorg.apache.http.client.ClientProtocolException; importorg.apache.http.client.ResponseHandler; importorg.apache.http.client.config.RequestConfig; importorg.apache.http.client.methods.HttpGet; importorg.apache.http.client.methods.HttpPost; importorg.apache.http.conn.ConnectTimeoutException; importorg.apache.http.conn.ConnectionPoolTimeoutException; importorg.apache.http.conn.ssl.SSLConnectionSocketFactory; importorg.apache.http.conn.ssl.SSLContexts; importorg.apache.http.entity.StringEntity; importorg.apache.http.impl.client.CloseableHttpClient; importorg.apache.http.impl.client.HttpClients; importorg.apache.http.util.EntityUtils; importjavax.net.ssl.SSLContext; importjava.io.File; importjava.io.FileInputStream; importjava.io.IOException; importjava.net.SocketTimeoutException; importjava.security.KeyStore; /** *Createdbyhupengon2015/7/28. */ publicclassHttpService{ privatestaticLoglogger=LogFactory.getLog(HttpService.class); privatestaticCloseableHttpClienthttpClient=buildHttpClient(); //连接超时时间,默认10秒 privatestaticintsocketTimeout=5000; //传输超时时间,默认30秒 privatestaticintconnectTimeout=5000; privatestaticintrequestTimeout=5000; publicstaticCloseableHttpClientbuildHttpClient(){ try{ KeyStorekeyStore=KeyStore.getInstance("PKCS12"); FileInputStreaminstream=newFileInputStream(newFile(Configure.getCertLocalPath()));//加载本地的证书进行https加密传输 try{ keyStore.load(instream,Configure.getCertPassword().toCharArray());//设置证书密码 }finally{ instream.close(); } //TrustownCAandallself-signedcerts SSLContextsslcontext=SSLContexts.custom() .loadKeyMaterial(keyStore,Configure.getCertPassword().toCharArray()) .build(); //AllowTLSv1protocolonly SSLConnectionSocketFactorysslsf=newSSLConnectionSocketFactory( sslcontext, newString[]{"TLSv1"}, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); RequestConfigrequestConfig=RequestConfig.custom() .setConnectTimeout(connectTimeout) .setConnectionRequestTimeout(requestTimeout) .setSocketTimeout(socketTimeout).build(); httpClient=HttpClients.custom() .setDefaultRequestConfig(requestConfig) .setSSLSocketFactory(sslsf) .build(); returnhttpClient; }catch(Exceptione){ thrownewRuntimeException("errorcreatehttpclient......",e); } } publicstaticStringdoGet(StringrequestUrl)throwsException{ HttpGethttpget=newHttpGet(requestUrl); try{ logger.debug("Executingrequest"+httpget.getRequestLine()); //Createacustomresponsehandler ResponseHandler<String>responseHandler=newResponseHandler<String>(){ @Override publicStringhandleResponse( finalHttpResponseresponse)throwsClientProtocolException,IOException{ intstatus=response.getStatusLine().getStatusCode(); if(status>=200&&status<300){ HttpEntityentity=response.getEntity(); returnentity!=null?EntityUtils.toString(entity):null; }else{ thrownewClientProtocolException("Unexpectedresponsestatus:"+status); } } }; returnhttpClient.execute(httpget,responseHandler); }finally{ httpget.releaseConnection(); } } publicstaticStringdoPost(Stringurl,Objectobject2Xml){ Stringresult=null; HttpPosthttpPost=newHttpPost(url); //解决XStream对出现双下划线的bug XStreamxStreamForRequestPostData=newXStream(newDomDriver("UTF-8",newXmlFriendlyNameCoder("-_","_"))); //将要提交给API的数据对象转换成XML格式数据Post给API StringpostDataXML=xStreamForRequestPostData.toXML(object2Xml); logger.info("API,POST过去的数据是:"); logger.info(postDataXML); //得指明使用UTF-8编码,否则到API服务器XML的中文不能被成功识别 StringEntitypostEntity=newStringEntity(postDataXML,"UTF-8"); httpPost.addHeader("Content-Type","text/xml"); httpPost.setEntity(postEntity); //设置请求器的配置 logger.info("executingrequest"+httpPost.getRequestLine()); try{ HttpResponseresponse=httpClient.execute(httpPost); HttpEntityentity=response.getEntity(); result=EntityUtils.toString(entity,"UTF-8"); }catch(ConnectionPoolTimeoutExceptione){ logger.error("httpgetthrowConnectionPoolTimeoutException(waittimeout)",e); }catch(ConnectTimeoutExceptione){ logger.error("httpgetthrowConnectTimeoutException",e); }catch(SocketTimeoutExceptione){ logger.error("httpgetthrowSocketTimeoutException",e); }catch(Exceptione){ logger.error("httpgetthrowException",e); }finally{ httpPost.abort(); } returnresult; } }
然后是我们的总入口:
packagecom.unstoppedable.service; importcom.unstoppedable.common.Configure; importcom.unstoppedable.common.HttpService; importcom.unstoppedable.common.XMLParser; importcom.unstoppedable.protocol.UnifiedOrderReqData; importorg.xml.sax.SAXException; importjavax.xml.parsers.ParserConfigurationException; importjava.io.IOException; importjava.util.Map; /** *Createdbyhupengon2015/7/28. */ publicclassWxPayApi{ publicstaticMap<String,Object>UnifiedOrder(UnifiedOrderReqDatareqData)throwsIOException,SAXException,ParserConfigurationException{ Stringres=HttpService.doPost(Configure.UNIFIED_ORDER_API,reqData); returnXMLParser.getMapFromXML(res); } publicstaticvoidmain(String[]args)throwsException{ UnifiedOrderReqDatareqData=newUnifiedOrderReqData.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中使用他就可以了。。
本文已被整理到了《JavaScript微信开发技巧汇总》,《Android微信开发教程汇总》,《java微信开发教程汇总》欢迎大家学习阅读。
为大家推荐现在关注度比较高的微信小程序教程一篇:《微信小程序开发教程》小编为大家精心整理的,希望喜欢。
以上就是本文的全部内容,希望对大家的学习有所帮助。