要使用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中使用他就可以了。。
以上就是本文的全部内容,希望对大家的学习有所帮助。