微信支付,需要通过微信支付验证
目前,支付仅限服务号,
做微信支付开发,主要看开发文档
统一下单,
订单查询
退款等
1.发起支付,都是通过h5发起的,首先获取prepay_id
发起支付,需要统一下单的prepay_id
SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
parameters.put("appid", ConfigUtil.APPID);
parameters.put("mch_id", ConfigUtil.MCH_ID);
parameters.put("nonce_str", PayCommonUtil.CreateNoncestr());
parameters.put("body", bodyorder);
parameters.put("out_trade_no", outTradeNo);// 用户订单号
parameters.put("total_fee", totalfee);// 标价金额(分)
// parameters.put("spbill_create_ip",IpAddressUtil.getIpAddr(request));
parameters.put("spbill_create_ip", "192.168.1.1");// 电脑测试
// parameters.put("spbill_create_ip",NetworkUtil.getIpAddress(request));
parameters.put("notify_url", ConfigUtil.NOTIFY_URL);
parameters.put("trade_type", "JSAPI");
parameters.put("openid", openId);
String sign = PayCommonUtil.createSign("UTF-8", parameters);
parameters.put("sign", sign);
String requestXML = PayCommonUtil.getRequestXml(parameters);
String result = CommonUtil.httpsRequestR2s(ConfigUtil.UNIFIED_ORDER_URL, "POST", requestXML);
System.out.println("第一弹数据" + result + "ip地址" + NetworkUtil.getIpAddress(request));
数据为
第一弹数据
<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<appid><![CDATA[wx06e68e38fcef451d]]></appid>
<mch_id><![CDATA[1427607202]]></mch_id>
<nonce_str><![CDATA[vOK9ll6ZylQAOiRV]]></nonce_str>
<sign><![CDATA[4D7F2D8D55377493503F8BB9E2F94C8B]]></sign>
<result_code><![CDATA[SUCCESS]]></result_code>
<prepay_id><![CDATA[wx20170105120958d7d94506790707606719]]></prepay_id>
<trade_type><![CDATA[JSAPI]]></trade_type>
</xml>
2.拿到prepay_id后,就可以发起支付
支付,需要设置测试路径和真实路径,
发起支付,将参数转为json,在放到respond里,然后h5页面从request里取
SortedMap<Object, Object> params = new TreeMap<Object, Object>();
params.put("appId", ConfigUtil.APPID);
params.put("timeStamp", Long.toString(new Date().getTime()));
params.put("nonceStr", PayCommonUtil.CreateNoncestr());
System.out.println("订单id" + map.get("prepay_id"));
params.put("package", "prepay_id=" + map.get("prepay_id"));
params.put("signType", ConfigUtil.SIGN_TYPE);
String paySign = PayCommonUtil.createSign("UTF-8", params);
// params.put("packageValue", "prepay_id="+map.get("prepay_id"));
// //这里用packageValue是预防package是关键字在js获取值出错
params.put("paySign", paySign); // paySign的生成规则和Sign的生成规则一致
String json = JSONObject.fromObject(params).toString();
System.out.println("第二弹数据" + json);
try {
response.setContentType("text/html" + ";charset=UTF-8");
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
response.getWriter().write(json);
response.getWriter().flush();
} catch (IOException e) {
e.printStackTrace();
}
}
上传,支付的html页面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>微信支付</title>
</head>
<body>
<!-- <form action="weiChatPayServlet" method="post" >
<input type="button" value="确认支付" name="ajaxLoadId" id="test1"/>
</form> -->
<div>
<p> 苏牌皮草</p>
<p> 库存18件</p>
<p> 原价:8888元</p>
<p> 现价:5000</p>
<p> <button id="test"> 我要购买</button></p>
</div>
<script src="js/jquery.min.js"></script>
<script src="js/jweixin-1.0.0.js"></script>
<script src="js/bootstrap.min.js"></script>
<script type="text/javascript">
function checkWeiXinVersion(){
var wechatInfo = navigator.userAgent.match(/MicroMessenger\/([\d\.]+)/i) ;
if( !wechatInfo ) {
alert("本活动仅支持微信") ;
} else if ( wechatInfo[1] < "5.0" ) {
alert("本活动仅支持微信5.0以上版本") ;
}
}
function onBridgeReady(obj){
WeixinJSBridge.invoke(‘getBrandWCPayRequest‘,{
"appId":obj.appId, //公众号名称,由商户传入
"timeStamp":obj.timeStamp, //时间戳,自 1970 年以来的秒数
"nonceStr":obj.nonceStr, //随机串
"package" : obj.package, //<span style="font-family:微软雅黑;">商品包信息</span>
"signType" : obj.signType, //微信签名方式:
"paySign" : obj.paySign //微信签名
},function(res){
alert(res.err_msg);
if(res.err_msg == "get_brand_wcpay_request:ok" ) {
window.location.href="http://weixin.xiaowanban.com/WXZ/weichatPay.html";
alert("f成功");
}else{
alert("fail");
window.location.href="http://weixin.xiaowanban.com/WXZ/signup.html";
//<span style="font-family:微软雅黑;">当失败后,继续跳转该支付页面让用户可以继续付款,贴别注意不能直接调转jsp,</span><span style="font-size:10.5pt">不然会报</span><span style="font-size:12.0pt"> system:access_denied。</span>
}
});
}
var basePath ="weiChatPayServlet";
$("#test").one("click",function(){
$.ajax({
type:"POST",
url:basePath
//<span style="font-family:微软雅黑;">ajax调用微信统一接口获取prepayId</span>
}).done(function(data){
alert("数据"+data);
console.log("数据为"+data);
var obj = eval(‘(‘ + data + ‘)‘);
//var obj =eval("("+data+")");//转换为json对象
/* if(parseInt(obj.agent)<5){
alert("您的微信版本低于5.0无法使用微信支付");
return;
} */
/* //配置微信
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: obj.appId, // 必填,公众号的唯一标识
timestamp:obj.timeStamp , // 必填,生成签名的时间戳
nonceStr: obj.nonceStr, // 必填,生成签名的随机串
signature: obj.signature,// 必填,签名,见附录1
jsApiList: [‘chooseWXPay‘] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});*/
checkWeiXinVersion();
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(obj);
}
});
});
</script>
</body>
</html>
支付后,可以登录商户平台查看支付状态
3.支付后要查询自己的订单
在支付时,我会默认存一下,商家生成的订单(商户订单号),一个openid下n那个订单,
商户订单号,要求唯一性,为了测试,我获取的时间戳,但是商用,最好用每秒100000次不同的订单号,自己可以搜
我拿到自己的数据库的商户号后,就去掉订单查询
private String checkOrder(String outTradeNo){
SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();
parameters.put("appid", ConfigUtil.APPID);
parameters.put("mch_id", ConfigUtil.MCH_ID);
parameters.put("nonce_str", PayCommonUtil.CreateNoncestr());
parameters.put("out_trade_no", outTradeNo);//用户订单号
parameters.put("sign_type", ConfigUtil.SIGN_TYPE);
String sign = PayCommonUtil.createSign("UTF-8", parameters);
parameters.put("sign", sign);
String requestXML = PayCommonUtil.getRequestXml(parameters);
String result=null ;
Map<String, String> map = null;
result =CommonUtil.httpsRequestR2s(ConfigUtil.CHECK_ORDER_URL, "POST", requestXML);
try {
map = XMLUtil.doXMLParse(result);
} catch (JDOMException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (map!=null) {
String returnCode= map.get("return_code");
String resultCode= map.get("result_code");
if (returnCode.equals("SUCCESS")&&resultCode.equals("SUCCESS")){
// System.out.println("returnCode结果为"+returnCode+"resultCode结果"+resultCode);
// System.out.println("支付状态"+map.get("trade_state"));
return map.get("trade_state");
}else {
return "noArrivePay";//为发起支付,没有到输入密码处直接退出
}
}else{
return null;
}
}
直要查到为支付成功,就修改数据库,支付状态
4.微信支付退款,直接看pai,涉及到证书的
测试退款时,也可以自己登陆商户平台退款;
退款的servlet主要代码
SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
parameters.put("appid", ConfigUtil.APPID);
parameters.put("mch_id", ConfigUtil.MCH_ID);
parameters.put("nonce_str", PayCommonUtil.CreateNoncestr());
parameters.put("out_trade_no", outTradeNo);// 用户订单号
parameters.put("out_refund_no", outRefundno);// 商户退款单号
parameters.put("total_fee", totalFee);// 订单金额
parameters.put("refund_fee", refundFee);// 退款金额
parameters.put("op_user_id", ConfigUtil.MCH_ID);// 操作员id
parameters.put("sign_type", ConfigUtil.SIGN_TYPE);
String sign = PayCommonUtil.createSign("UTF-8", parameters);
parameters.put("sign", sign);
String requestXML = PayCommonUtil.getRequestXml(parameters);
String result = null;
Map<String, String> map = null;
result = CommonUtil.httpsRequestR2s(ConfigUtil.REFUND_URL, "POST", requestXML);
try {
map = XMLUtil.doXMLParse(result);
} catch (JDOMException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 退款微信证书相关
KeyStore keyStore = null;
FileInputStream instream=null;
try {
keyStore = KeyStore.getInstance("PKCS12");
instream = new FileInputStream(new File("D:/10016225.p12"));
keyStore.load(instream, "10016225".toCharArray());
} catch (KeyStoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (CertificateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
instream.close();
}
// Trust own CA and all self-signed certs
SSLContext sslcontext=null;
try {
sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, "10016225".toCharArray()).build();
} catch (KeyManagementException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (KeyStoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Allow TLSv1 protocol only
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
try {
HttpGet httpget = new HttpGet("https://api.mch.weixin.qq.com/secapi/pay/refund");
System.out.println("executing request" + httpget.getRequestLine());
CloseableHttpResponse responseSJT = httpclient.execute(httpget);
try {
HttpEntity entity = responseSJT.getEntity();
System.out.println("----------------------------------------");
System.out.println(responseSJT.getStatusLine());
if (entity != null) {
System.out.println("Response content length: " + entity.getContentLength());
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent()));
String text;
while ((text = bufferedReader.readLine()) != null) {
System.out.println(text);
}
}
EntityUtils.consume(entity);
} finally {
responseSJT.close();
}
} finally {
httpclient.close();
}
}
退款成功图片
退款成功的数据
退款成功返回
executing requestPOST https://api.mch.weixin.qq.com/secapi/pay/refund HTTP/1.1
----------------------------------------
HTTP/1.1 200 OK
Response content length: 850
<xml><return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<appid><![CDATA[wx06e68e38fcef451d]]></appid>
<mch_id><![CDATA[1427607202]]></mch_id>
<nonce_str><![CDATA[tR8oByXN60Xc1C9M]]></nonce_str>
<sign><![CDATA[4F9FD6304C7CF37F0DD9B194AA7C6B8A]]></sign>
<result_code><![CDATA[SUCCESS]]></result_code>
<transaction_id><![CDATA[4007112001201701115967786227]]></transaction_id>
<out_trade_no><![CDATA[1484126688291]]></out_trade_no>
<out_refund_no><![CDATA[20170113161502599000]]></out_refund_no>
<refund_id><![CDATA[2007112001201701130741391621]]></refund_id>
<refund_channel><![CDATA[]]></refund_channel>
<refund_fee>100</refund_fee>
<coupon_refund_fee>0</coupon_refund_fee>
<total_fee>100</total_fee>
<cash_fee>100</cash_fee>
<coupon_refund_count>0</coupon_refund_count>
<cash_refund_fee>100</cash_refund_fee>
</xml>
5.说一下,支付的api准备配置
5.1微信支付需要验证
5.2微信支付,设置秘钥
设置秘钥时,会提醒你,是否安装证书,就是微信验证,发给你的邮件里附件里的cert
6.微信授权,获取openid,网页授权的东西,是最基本的,也要知道
网页授权,获取用户信息