当前位置: 移动技术网 > IT编程>开发语言>Java > Java通过JsApi方式实现微信支付

Java通过JsApi方式实现微信支付

2019年07月22日  | 移动技术网IT编程  | 我要评论
要使用jsapi进行微信支付,首先要从微信获得一个prepay_id,然后通过调用微信的jsapi完成支付,js api的返回结果get_brand_wcpay_reque

要使用jsapi进行微信支付,首先要从微信获得一个prepay_id,然后通过调用微信的jsapi完成支付,js api的返回结果get_brand_wcpay_request:ok仅在用户成功完成支付时返回。由于前端交互复杂,get_brand_wcpay_request:cancel或者get_brand_wcpay_request:fail可以统一处理为用户遇到错误或者主动放弃,不必细化区分。
示例代码如下:

function onbridgeready(){
 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 (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();
}


以上传入的参数package,即为prepay_id

下面讲的是获得参数来调用jsapi
我们调用jsapi时,必须获得用户的openid,(trade_type=jsapi,openid为必填参数。)
首先定义一个请求的对象:

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("传入参数appid不能为null");
 }
 if (mch_id == null) {
 throw new illegalargumentexception("传入参数mch_id不能为null");
 }
 if (body == null) {
 throw new illegalargumentexception("传入参数body不能为null");
 }
 if (out_trade_no == null) {
 throw new illegalargumentexception("传入参数out_trade_no不能为null");
 }
 if (total_fee == null) {
 throw new illegalargumentexception("传入参数total_fee不能为null");
 }
 if (spbill_create_ip == null) {
 throw new illegalargumentexception("传入参数spbill_create_ip不能为null");
 }
 if (notify_url == null) {
 throw new illegalargumentexception("传入参数notify_url不能为null");
 }
 if (trade_type == null) {
 throw new illegalargumentexception("传入参数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("当传入trade_type为jsapi时,openid为必填参数");
 }
 if("native".equals(this.trade_type) && this.product_id == null) {
 throw new illegalargumentexception("当传入trade_type为native时,product_id为必填参数");
 }
 return new unifiedorderreqdata(this);
 }
 }



}

因为有些参数为必填,有些参数为选填。而且sign要等所有参数传入之后才能计算的出,所以这里用了builder模式。关于builder模式。

我们选用httpclient进行网络传输。

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();

 //连接超时时间,默认10秒
 private static int sockettimeout = 5000;

 //传输超时时间,默认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());//设置证书密码
 } 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对出现双下划线的bug
 xstream xstreamforrequestpostdata = new xstream(new domdriver("utf-8", new xmlfriendlynamecoder("-_", "_")));

 //将要提交给api的数据对象转换成xml格式数据post给api
 string postdataxml = xstreamforrequestpostdata.toxml(object2xml);

 logger.info("api,post过去的数据是:");
 logger.info(postdataxml);

 //得指明使用utf-8编码,否则到api服务器xml的中文不能被成功识别
 stringentity postentity = new stringentity(postdataxml, "utf-8");
 httppost.addheader("content-type", "text/xml");
 httppost.setentity(postentity);

 //设置请求器的配置

 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;
 }
}

然后是我们的总入口:

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中使用他就可以了。。

本文已被整理到了《javascript微信开发技巧汇总》,《android微信开发教程汇总》,《java微信开发教程汇总》欢迎大家学习阅读。

为大家推荐现在关注度比较高的微信小程序教程一篇:《微信小程序开发教程》小编为大家精心整理的,希望喜欢。

以上就是本文的全部内容,希望对大家的学习有所帮助。

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网