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

要使用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微信开发教程汇总》欢迎大家学习阅读。

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

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

(0)

相关推荐

  • java调用中国天气网api获得天气预报信息的方法

    本文实例讲述了java调用中国天气网api获得天气预报信息的方法.分享给大家供大家参考.具体实现方法如下: //以冰城哈尔滨为例通过中国天气api调用天气信息 private String getWeatherInfo2(){ StringBuilder info = new StringBuilder(); try { DefaultHttpClient httpclient = new DefaultHttpClient(); HttpGet httget = new HttpGet("ht

  • 详解Java的JDBC API中事务的提交和回滚

    如果JDBC连接是在自动提交模式下,它在默认情况下,那么每个SQL语句都是在其完成时提交到数据库. 这可能是对简单的应用程序,但有三个原因,你可能想关闭自动提交和管理自己的事务: 为了提高性能 为了保持业务流程的完整性 使用分布式事务 若要控制事务,以及何时更改应用到数据库.它把单个SQL语句或一组SQL语句作为一个逻辑单元,而且如果任何语句失败,整个事务失败. 若要启用,而不是JDBC驱动程序默认使用auto-commit模式手动事务支持,使用Connection对象的的setAutoComm

  • JAVA IO API使用详解

    一.理论准备流是个抽象的概念,是对输入输出设备的抽象,Java程序中,对于数据的输入/输出操作都是以"流"的方式进行,设备可以是文件.网络.内存等.流具有方向性,至于是输入流还是输出流则是一个相对的概念,一般以程序(小马哥说的是机器)为参考,如果数据的流向是程序至设备,我们成为输出流,反之我们称为输入流,可以将流想象成一个"水流管道"(很多资料都这么讲的),自然就出现了方向的概念.流把I/O设备内部的具体操作给隐藏起来了.所有InputStream和Reader的派

  • Java中的Calendar日历API用法完全解析

    第一部分 Calendar介绍 Calendar 定义: public abstract class Calendar implements Serializable, Cloneable, Comparable<Calendar> {} Calendar 可以看作是一个抽象类. 它的实现,采用了设计模式中的工厂方法.表现在:当我们获取Calendar实例时,Calendar会根据传入的参数来返回相应的Calendar对象.获取Calendar实例,有以下两种方式: (1) 当我们通过 Cal

  • java使用淘宝API读写json实现手机归属地查询功能代码

    一般查询手机归属地内容应该很好用json格式保存,在网上找到了淘宝的归属地API,并下了处理json相关的jar包,做了这个手机归属地查询功能 复制代码 代码如下: package com.think.java; import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.net.MalformedURLException;import java.net

  • java调用百度定位api服务获取地理位置示例

    复制代码 代码如下: package test; import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.Reader;import java.net.URL;import java.nio.charset.Charset; import org.json.JSONException;imp

  • 用Java实现全国天气预报的api接口调用示例

    step1:选择本文所示例的接口"全国天气预报接口" 聚合数据url:http://www.juhe.cn/docs/api/id/39/aid/87 step2:每个接口都需要传入一个参数key,相当于用户的令牌,所以第一步你需要申请一个key. step3:学过java的同学们都知道,当我们对一个类或者方法不明白其意图和思想时,我们可以去查看文档,这里也不例外,而且对于英文不是特别好的同学来说很幸运的是,聚合网站上的文档都是中文版本的,比起阅读java源码里的英文文档应该轻松很多.

  • android monkey自动化测试改为java调用monkeyrunner Api

    众所周知,一般情况下我们使用android中的monkeyrunner进行自动化测试时,使用的是python语言来写测试脚本.不过,最近发现可以用java调用monkeyrunner Api,用java语言写测试脚本. 于是,就简单研究了一下.这里做一些总结.希望有对在研究的午饭可以有所用处. 开始时,搜素到一些零碎的教程,说使用java调用monkeyrunner时,需要导入android sdk  tools路径下的lib里面的4个包:ddmlib.jar,guavalib.jar,monk

  • Java8新日期时间API的20个使用示例

    除了lambda表达式,stream以及几个小的改进之外,Java 8还引入了一套全新的时间日期API,在本篇教程中我们将通过几个简单的任务示例来学习如何使用Java 8的这套API.Java对日期,日历及时间的处理一直以来都饱受诟病,尤其是它决定将java.util.Date定义为可修改的以及将SimpleDateFormat实现成非线程安全的.看来Java已经意识到需要为时间及日期功能提供更好的支持了,这对已经习惯使用Joda时间日期库的社区而言也是件好事.关于这个新的时间日期库的最大的优点

  • 5个Java API使用技巧

    本文介绍了一些关于Java API安全和性能方面的简单易用的技巧,其中包括保证API Key安全和开发Web Service方面中在框架方面选择的一些建议. 程序员都喜欢使用API!例如为app应用构建API或作为微服务架构体系的一部分.当然,使用API的前提是能让你的工作变得更轻松.为了简化开发和提高工作效率所作出的努力,有时也意味着需要寻找新的类库或者过程(或者减少过程).对于很多开发团队来说,对于其APP和API进行管理认证和访问控制要耗费很多的时间,因此我们需想分享一些技巧,它们能节约你

随机推荐