Rumah applet WeChat pembangunan WeChat 详解Java通过JsApi方式实现微信支付方法

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

Mar 27, 2017 pm 01:56 PM

本文讲解了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();
}
Salin selepas log masuk

以上传入的参数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);
 }
 }
}
Salin selepas log masuk

因为有些参数为必填,有些参数为选填。而且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;
 }
}
Salin selepas log masuk

然后是我们的总入口:

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));
 }
}
Salin selepas log masuk

返回的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>
Salin selepas log masuk

return_code 和result_code都为SUCCESS的时候会返回我们需要的prepay_id。。。,然后在jsapi中使用他就可以了。。

Atas ialah kandungan terperinci 详解Java通过JsApi方式实现微信支付方法. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

AI Hentai Generator

AI Hentai Generator

Menjana ai hentai secara percuma.

Artikel Panas

R.E.P.O. Kristal tenaga dijelaskan dan apa yang mereka lakukan (kristal kuning)
4 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Tetapan grafik terbaik
4 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Cara Memperbaiki Audio Jika anda tidak dapat mendengar sesiapa
4 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Cara Membuka Segala -galanya Di Myrise
1 bulan yang lalu By 尊渡假赌尊渡假赌尊渡假赌

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)