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微信开发教程汇总》欢迎大家学习阅读。
为大家推荐现在关注度比较高的微信小程序教程一篇:《微信小程序开发教程》小编为大家精心整理的,希望喜欢。
以上就是本文的全部内容,希望对大家的学习有所帮助。