要使用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
详细文档见:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7

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

package com.unstoppedable.protocol;import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.unstoppedable.common.Configure;
import com.unstoppedable.common.RandomStringGenerator;
import com.unstoppedable.common.Signature;import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;@XStreamAlias("xml")
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 String getAppid() {return appid;}public String getMch_id() {return mch_id;}public String getDevice_info() {return device_info;}public String getNonce_str() {return nonce_str;}public String getSign() {return sign;}public String getBody() {return body;}public String getDetail() {return detail;}public String getAttach() {return attach;}public String getOut_trade_no() {return out_trade_no;}public String getFee_type() {return fee_type;}public int getTotal_fee() {return total_fee;}public String getSpbill_create_ip() {return spbill_create_ip;}public String getTime_start() {return time_start;}public String getTime_expire() {return time_expire;}public String getGoods_tag() {return goods_tag;}public String getNotify_url() {return notify_url;}public String getTrade_type() {return trade_type;}public String getProduct_id() {return product_id;}public String getLimit_pay() {return limit_pay;}public String getOpenid() {return 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;/*** 使用配置中的 appid 和  mch_id** @param body* @param out_trade_no* @param total_fee* @param spbill_create_ip* @param notify_url* @param trade_type*/public UnifiedOrderReqDataBuilder(String body, String out_trade_no, Integer total_fee,String spbill_create_ip, String notify_url, String trade_type) {this(Configure.getAppid(), Configure.getMchid(), body, out_trade_no, total_fee,spbill_create_ip, notify_url, trade_type);}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模式。关于每个参数的定义,参考说明文档https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1

我们选用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 certsSSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, Configure.getCertPassword().toCharArray()).build();// Allow TLSv1 protocol onlySSLConnectionSocketFactory 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 handlerResponseHandler<String> responseHandler = new ResponseHandler<String>() {@Overridepublic 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对出现双下划线的bugXStream xStreamForRequestPostData = new XStream(new DomDriver("UTF-8", new XmlFriendlyNameCoder("-_", "_")));//将要提交给API的数据对象转换成XML格式数据Post给APIString 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中使用他就可以了。。

代码托管在https://github.com/hupengcool/wxpay_jsapi ,欢迎指正

转载于:https://www.cnblogs.com/hupengcool/p/4684551.html

Java实现JsApi方式的微信支付相关推荐

  1. jsapi支付java_Java通过JsApi方式实现微信支付.doc

    Java通过JsApi方式实现微信支付 Java通过JsApi方式实现微信支付 本文讲解了Java如何实现JsApi方式的微信支付,代码内容详细,文章思路清晰,需要的朋友可以参考下 要使用JsApi进 ...

  2. JSAPI网页授权-微信支付-微信退款-商户平台Java对接

    简介: 首先,对接微信支付要知道需要什么参数,然后等我们拿到这些需要的参数.就要开始怎么去做.微信有专门的支付dome,可惜我才疏学浅,没怎么看懂(哭泣~).不过里面的有一些工具类是我们所需要的. 这 ...

  3. 千锋Java高级教程+分布式+springcloud+微信支付课程

    课程目录: ├─千锋Java高级教程-cas单点登录(完结-8集) │ 01单点登录介绍 │ 02cas介绍 │ 03tomcat搭建https │ 04cas server搭建 │ 05Cas 配置 ...

  4. php微信支付jsapi,ThinkPHP实现微信支付(jsapi支付)

    这篇文章主要介绍了ThinkPHP实现微信支付(jsapi支付)流程教程详解,需要的朋友可以参考下 之前写过一篇文章讲了PHP实现微信支付(jsapi支付)流程 ,详见文章:PHP实现微信支付(jsa ...

  5. springboot微信sdk方式进行微信支付

    微信支付: 官方文档:https://pay.weixin.qq.com/wiki/doc/api/index.html 第三方SDK:https://github.com/Pay-Group/bes ...

  6. 【Java必备技能五】微信支付之JSAPI方式(公众号支付)超详细实现步骤

    目录 一.JSAPI支付概述 二.名词解释 三.签名算法 四.设置支付目录和授权域名

  7. JAVA实现 springMVC方式的微信接入、实现消息自动回复

    前段时间小忙了一阵,微信公众号的开发,从零开始看文档,踩了不少坑,也算是熬过来了,最近考虑做一些总结,方便以后再开发的时候回顾,也给正在做相关项目的同学做个参考. 思路 微信接入:用户消息和开发者需要 ...

  8. java生成二维码-微信支付、支付宝支付链接转二维码解决方案

    1.后台返回链接利用js生成二维码供客户使用 需要js文件:qrcode.min.js 下载地址:http://static.runoob.com/assets/qrcode/qrcode.min.j ...

  9. APP 对接 java 微信支付统一下单接口

    首先插入微信支付的时序图 统一下单时候的请求对象,需要把这个转为xml 文件格式所以需要在pom.xml 文件中导入 .和微信支付的sdk <dependency> <groupId ...

最新文章

  1. c++读取文件内容并保存到二维数组
  2. java知识点8——垃圾回收原理和算法、通用的分代垃圾回收机制、 JVM调优和Full GC、开发中容易造成内存泄露的操作
  3. boost::proto模块实现使用一个带有语法的域来修剪集合重载运算符的测试程序
  4. Mysql CURD复习(数据库、表、数据)
  5. React中自定义方法
  6. 学习《PythonWeb开发实战(董伟明)》中文PDF+源代码
  7. matlab约当消去法,Gauss消去法解线性方程组(Matlab)
  8. 筛选出一证多卡 用sql_对比Excel学习SQL(3):对列和行的操作
  9. mysql mof提权原理_[原创]WEB安全第六章提权篇12 mof提权
  10. python生成.exe文件
  11. linux 周期性任务,Linux任务计划,周期性任务执行详解
  12. iphone保修期多久_小心!教你如何鉴别 iPhone 翻新机,黑机千万别买!
  13. 三维点云学习(5)3-Deep learning for Point Cloud-PointNet++
  14. 转载--上下标等特殊符号的输入方法
  15. mysql 查看3306端口_如何查看端口(3306)被那个程序占用?
  16. 二进制算法——模二运算
  17. 视频--Pr 第一个剪辑
  18. IIC数据总线 线与 还是 线或 ?是线与
  19. inter uhd graphics630显卡驱动_Intel新驱动已支持Win10 H2更新、11代酷睿狂喜
  20. 嵌入式设备的启动过程

热门文章

  1. 揭秘码云:全球第二大代码托管平台的核心架构
  2. 如何解决经常出现Windows数据执行保护的提示?
  3. 字节流InputStream/OutputStream
  4. 里程碑:BCH网络出现首例Schnorr Multisig交易
  5. 三、Flask_会话控制与请求钩子
  6. EOS净流入超3亿,比特币继续震荡盘整
  7. [NOIP2012] 借教室
  8. Vue单文件组件基础模板
  9. MySQL-Binlog解析篇:2 Authenticate
  10. 解决Sqlite UTF-8中文数据格式在DOS窗口下中文乱码