要使用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进行网络传输。
立即学习“Java免费学习笔记(深入)”;
萌次元商城是一个针对二次元的开源发卡系统。系统免费开源、界面美观、功能丰富。 (存在与第三方服务器连接的付费增值服务,但自身免费功能能够满足基本需求) 版权:遵循MIT协议从lizhipay处获得授权进行再分发 特色功能: 1.可以分发密钥,作为发卡网使用 2.可以关联快递单号,作为微商自建电商平台使用 3.支持多种支付方式,包括微信、支付宝、银联和国际
0
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中使用他就可以了。。
以上就是Java实现JsApi方式的微信支付的内容,更多相关内容请关注PHP中文网(www.php.cn)!
微信是一款手机通信软件,支持通过手机网络发送语音短信、视频、图片和文字。微信可以单聊及群聊,还能根据地理位置找到附近的人,带给大家全新的移动沟通体验,有需要的小伙伴快来保存下载体验吧!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号