欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2024-03-06 08:05:07
要使用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微信开发教程汇总》欢迎大家学习阅读。

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

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