java服務端微信APP支付接口詳解
一、微信APP支付接入商戶服務中心
二、開始開發(fā)
1、配置相關的配置信息
1.1、配置appid(Android)、mch_id(ios)、微信支付后的回調(diào)地址
sys.properties配置文件: appid=wx***************1 mch_id=1********2 notify_url=http://6*.***.***.**/returnmsg.do //回調(diào)通知的地址,一定是要可以直接訪問的地址
2、微信支付–下單
@ResponseBody
@RequestMapping(value = "/weixinpay.do", produces = "text/html;charset=UTF-8",method={RequestMethod.POST})
public static String weixinpay(String body, //商品描述
String detail, //商品詳情
String attach, //附加數(shù)據(jù),在查詢API和支付通知中原樣返回,該字段主要用于商戶攜帶訂單的自定義數(shù)據(jù)
String out_trade_no, //商戶系統(tǒng)內(nèi)部的訂單號,32個字符內(nèi)、可包含字母, 其他說明見商戶訂單號
String total_price, //訂單總金額,單位為分,詳見支付金額
String spbill_create_ip //用戶端實際ip
) throws Exception {
WeixinConfigUtils config = new WeixinConfigUtils();
//參數(shù)組
String appid = config.appid;//微信開放平臺審核通過的應用APPID
System.out.println("appid是:"+appid);
String mch_id = config.mch_id;
System.out.println("mch_id是:"+mch_id);
String nonce_str = RandCharsUtils.getRandomString(16);
System.out.println("隨機字符串是:"+nonce_str);
body = body;//"測試微信支付0.01_2";
detail = detail;//"0.01_元測試開始";
//attach = attach;//"備用參數(shù),先留著,后面會有用的";
//String out_trade_no = OrderUtil.getOrderNo();//"2015112500001000811017342394";
double totalfee =0;
try{
totalfee=Double.parseDouble(total_price);////單位是分,即是0.01元
}catch (Exception e) {
totalfee=0;
}
int total_fee=(int) (totalfee*100);
spbill_create_ip = spbill_create_ip;//"127.0.0.1";
String time_start = RandCharsUtils.timeStart();
System.out.println(time_start);
String time_expire = RandCharsUtils.timeExpire();
System.out.println(time_expire);
String notify_url = config.notify_url;
System.out.println("notify_url是:"+notify_url);
String trade_type = "APP";
//參數(shù):開始生成簽名
SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();
parameters.put("appid", appid);
parameters.put("mch_id", mch_id);
parameters.put("nonce_str", nonce_str);
parameters.put("body", body);
//parameters.put("nonce_str", nonce_str);
parameters.put("detail", detail);
parameters.put("attach", attach);
parameters.put("out_trade_no", out_trade_no);
parameters.put("total_fee", total_fee);
parameters.put("time_start", time_start);
parameters.put("time_expire", time_expire);
parameters.put("notify_url", notify_url);
parameters.put("trade_type", trade_type);
parameters.put("spbill_create_ip", spbill_create_ip);
String sign = WXSignUtils.createSign("UTF-8", parameters);
System.out.println("簽名是:"+sign);
Unifiedorder unifiedorder = new Unifiedorder();
unifiedorder.setAppid(appid);
unifiedorder.setMch_id(mch_id);
unifiedorder.setNonce_str(nonce_str);
unifiedorder.setSign(sign);
unifiedorder.setBody(body);
unifiedorder.setDetail(detail);
unifiedorder.setAttach(attach);
unifiedorder.setOut_trade_no(out_trade_no);
unifiedorder.setTotal_fee(total_fee);
unifiedorder.setSpbill_create_ip(spbill_create_ip);
unifiedorder.setTime_start(time_start);
unifiedorder.setTime_expire(time_expire);
unifiedorder.setNotify_url(notify_url);
unifiedorder.setTrade_type(trade_type);
System.out.println(MD5Utils.md5("fenxiangzhuyi") + "========================");
//構造xml參數(shù)
String xmlInfo = HttpXmlUtils.xmlInfo(unifiedorder);
String wxUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";
String method = "POST";
String weixinPost = HttpXmlUtils.httpsRequest(wxUrl, method, xmlInfo).toString();
System.out.println(weixinPost);
ParseXMLUtils.jdomParseXml(weixinPost);
String json = JsonUtil.xml2jsonString(weixinPost);
System.out.println("=========================================================");
Bean b = JsonUtil.getSingleBean(json, Bean.class);
if(null!=b){
WeixinOrder weixin = b.getXml();
//參數(shù):開始生成簽名
SortedMap<Object,Object> par = new TreeMap<Object,Object>();
par.put("appid", weixin.getAppid());
par.put("partnerid", weixin.getMch_id());
par.put("prepayid", weixin.getPrepay_id());
par.put("package", "Sign=WXPay");
par.put("noncestr", weixin.getNonce_str());
//時間戳
Date date = new Date();
long time = date.getTime();
//mysq 時間戳只有10位 要做處理
String dateline = time + "";
dateline = dateline.substring(0, 10);
par.put("timestamp", dateline);
String signnew = WXSignUtils.createSign("UTF-8", par);
System.out.println("再次簽名是:"+signnew);
SetPay setPay = new SetPay();
setPay.setAppid(weixin.getAppid());
setPay.setPartnerid(weixin.getMch_id());
setPay.setPrepayid(weixin.getPrepay_id());
setPay.setNoncestr(weixin.getNonce_str());
setPay.setTimestamp(dateline);
setPay.setSign(signnew);
setPay.setPack("Sign=WXPay");
JSONObject js = JSONObject.fromObject(setPay);
StringBuilder msg = new StringBuilder();
msg.append("{\"code\":\"1\",");
msg.append("\"msg\":\"查詢成功!\",");
msg.append("\"datas\":");
msg.append(js.toString());
msg.append("}");
System.out.println(js);
return msg.toString();
}
StringBuilder msg = new StringBuilder();
msg.append("{\"code\":\"1\",");
msg.append("\"msg\":\"查詢成功!\",");
msg.append("\"datas\":");
msg.append("支付失?。?);
msg.append("}");
return msg.toString();
}
2.1、微信支付簽名算法sign
package com.wx.weixincontroller.pay.weixin.Utils;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import com.wx.weixin.utils.MD5Utils;
/**
* 微信支付簽名
* @author iYjrg_xiebin
* @date 2016年10月25日下午4:47:07
*/
public class WXSignUtils {
//http://mch.weixin.qq.com/wiki/doc/api/index.php?chapter=4_3
//商戶Key:改成公司申請的即可
//32位密碼設置地址:http://www.sexauth.com/ jdex1hvufnm1sdcb0e81t36k0d0f15nc
private static String Key = "***cb**e**ef**c*e*d***e*fd***cb*";
/**
* 微信支付簽名算法sign
* @param characterEncoding
* @param parameters
* @return
*/
@SuppressWarnings("rawtypes")
public static String createSign(String characterEncoding,SortedMap<Object,Object> parameters){
StringBuffer sb = new StringBuffer();
Set es = parameters.entrySet();//所有參與傳參的參數(shù)按照accsii排序(升序)
Iterator it = es.iterator();
while(it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
String k = (String)entry.getKey();
Object v = entry.getValue();
if(null != v && !"".equals(v)
&& !"sign".equals(k) && !"key".equals(k)) {
sb.append(k + "=" + v + "&");
}
}
sb.append("key=" + Key);
System.out.println("字符串拼接后是:"+sb.toString());
String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
return sign;
}
}
2.2、POST提交XML格式的參數(shù)
package com.wx.weixincontroller.pay.weixin.Utils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import com. com.wx.weixin.wxcontroller.pay.weixin.entity.Unifiedorder;
/**
* post提交xml格式的參數(shù)
* @author iYjrg_xiebin
* @date 2016年10月25日下午3:33:38
*/
public class HttpXmlUtils {
/**
* 開始post提交參數(shù)到接口
* 并接受返回
* @param url
* @param xml
* @param method
* @param contentType
* @return
*/
public static String xmlHttpProxy(String url,String xml,String method,String contentType){
InputStream is = null;
OutputStreamWriter os = null;
try {
URL _url = new URL(url);
HttpURLConnection conn = (HttpURLConnection) _url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestProperty("Content-type", "text/xml");
conn.setRequestProperty("Pragma:", "no-cache");
conn.setRequestProperty("Cache-Control", "no-cache");
conn.setRequestMethod("POST");
os = new OutputStreamWriter(conn.getOutputStream());
os.write(new String(xml.getBytes(contentType)));
os.flush();
//返回值
is = conn.getInputStream();
return getContent(is, "utf-8");
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally{
try {
if(os!=null){os.close();}
if(is!=null){is.close();}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
/**
* 解析返回的值
* @param is
* @param charset
* @return
*/
public static String getContent(InputStream is, String charset) {
String pageString = null;
InputStreamReader isr = null;
BufferedReader br = null;
StringBuffer sb = null;
try {
isr = new InputStreamReader(is, charset);
br = new BufferedReader(isr);
sb = new StringBuffer();
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
}
pageString = sb.toString();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (is != null){
is.close();
}
if(isr!=null){
isr.close();
}
if(br!=null){
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
sb = null;
}
return pageString;
}
/**
* 構造xml參數(shù)
* @param xml
* @return
*/
public static String xmlInfo(Unifiedorder unifiedorder){
//構造xml參數(shù)的時候,至少又是個必傳參數(shù)
/*
* <xml>
<appid>wx2421b1c4370ec43b</appid>
<attach>支付測試</attach>
<body>JSAPI支付測試</body>
<mch_id>10000100</mch_id>
<nonce_str>1add1a30ac87aa2db72f57a2375d8fec</nonce_str>
<notify_url>http://wxpay.weixin.qq.com/pub_v2/pay/notify.v2.php</notify_url>
<openid>oUpF8uMuAJO_M2pxb1Q9zNjWeS6o</openid>
<out_trade_no>1415659990</out_trade_no>
<spbill_create_ip>14.23.150.211</spbill_create_ip>
<total_fee>1</total_fee>
<trade_type>JSAPI</trade_type>
<sign>0CB01533B8C1EF103065174F50BCA001</sign>
</xml>
*/
if(unifiedorder!=null){
StringBuffer bf = new StringBuffer();
bf.append("<xml>");
bf.append("<appid><![CDATA[");
bf.append(unifiedorder.getAppid());
bf.append("]]></appid>");
bf.append("<mch_id><![CDATA[");
bf.append(unifiedorder.getMch_id());
bf.append("]]></mch_id>");
bf.append("<nonce_str><![CDATA[");
bf.append(unifiedorder.getNonce_str());
bf.append("]]></nonce_str>");
bf.append("<sign><![CDATA[");
bf.append(unifiedorder.getSign());
bf.append("]]></sign>");
bf.append("<body><![CDATA[");
bf.append(unifiedorder.getBody());
bf.append("]]></body>");
bf.append("<detail><![CDATA[");
bf.append(unifiedorder.getDetail());
bf.append("]]></detail>");
bf.append("<attach><![CDATA[");
bf.append(unifiedorder.getAttach());
bf.append("]]></attach>");
bf.append("<out_trade_no><![CDATA[");
bf.append(unifiedorder.getOut_trade_no());
bf.append("]]></out_trade_no>");
bf.append("<total_fee><![CDATA[");
bf.append(unifiedorder.getTotal_fee());
bf.append("]]></total_fee>");
bf.append("<spbill_create_ip><![CDATA[");
bf.append(unifiedorder.getSpbill_create_ip());
bf.append("]]></spbill_create_ip>");
bf.append("<time_start><![CDATA[");
bf.append(unifiedorder.getTime_start());
bf.append("]]></time_start>");
bf.append("<time_expire><![CDATA[");
bf.append(unifiedorder.getTime_expire());
bf.append("]]></time_expire>");
bf.append("<notify_url><![CDATA[");
bf.append(unifiedorder.getNotify_url());
bf.append("]]></notify_url>");
bf.append("<trade_type><![CDATA[");
bf.append(unifiedorder.getTrade_type());
bf.append("]]></trade_type>");
bf.append("</xml>");
return bf.toString();
}
return "";
}
/**
* post請求并得到返回結(jié)果
* @param requestUrl
* @param requestMethod
* @param output
* @return
*/
public static String httpsRequest(String requestUrl, String requestMethod, String output) {
try{
URL url = new URL(requestUrl);
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setUseCaches(false);
connection.setRequestMethod(requestMethod);
if (null != output) {
OutputStream outputStream = connection.getOutputStream();
outputStream.write(output.getBytes("UTF-8"));
outputStream.close();
}
// 從輸入流讀取返回內(nèi)容
InputStream inputStream = connection.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
inputStream = null;
connection.disconnect();
return buffer.toString();
}catch(Exception ex){
ex.printStackTrace();
}
return "";
}
}
3、微信支付–回調(diào)通知業(yè)務處理
//通知處理類
@ResponseBody
@RequestMapping(value = "/returnmsg.do", produces = "text/html;charset=UTF-8",method={RequestMethod.POST})
public String returnmsg(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 解析結(jié)果存儲在HashMap
Map<String, String> map = new HashMap<String, String>();
InputStream inputStream = request.getInputStream();
// 讀取輸入流
SAXReader reader = new SAXReader();
Document document = reader.read(inputStream);
// 得到xml根元素
Element root = document.getRootElement();
// 得到根元素的所有子節(jié)點
List<Element> elementList = root.elements();
// 遍歷所有子節(jié)點
for (Element e : elementList) {
map.put(e.getName(), e.getText());
}
JSONObject json = JSONObject.fromObject(map);
System.out.println("===消息通知的結(jié)果:" + json.toString() + "==========================");
System.out.println("===return_code===" + map.get("return_code"));
System.out.println("===return_msg===" + map.get("return_msg"));
System.out.println("===out_trade_no===" + map.get("out_trade_no"));
//驗證簽名的過程
//判斷是否支付成功
if(map.get("return_code").equals("SUCCESS")) {
/**
*支付成功之后的業(yè)務處理
*/
// 釋放資源
inputStream.close();
inputStream = null;
//bis.close();
return "SUCCESS";
}
}
if (map.get("return_code").equals("FAIL")) {
/**
*支付失敗后的業(yè)務處理
*/
// 釋放資源
inputStream.close();
inputStream = null;
return "SUCCESS";
}
}
// 釋放資源
inputStream.close();
inputStream = null;
return "SUCCESS";
}
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
Java類如何實現(xiàn)一個類的障眼法(JadClipse的bug)
這篇文章主要介紹了Java類實現(xiàn)一個類的障眼法(JadClipse的bug),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-12-12
java高級用法之綁定CPU的線程Thread?Affinity簡介
java線程thread affinity是用來將java代碼中的線程綁定到CPU特定的核上,用來提升程序運行的性能,這篇文章主要介紹了java高級用法之綁定CPU的線程thread affinity的相關知識,需要的朋友可以參考下2022-05-05
SpringCloud Zuul在何種情況下使用Hystrix及問題小結(jié)
這篇文章主要介紹了SpringCloud Zuul在何種情況下使用Hystrix 及問題小結(jié),感興趣的朋友跟隨小編一起看看吧2018-11-11
Java commons io包實現(xiàn)多線程同步圖片下載入門教程
這篇文章主要介紹了Java commons io包實現(xiàn)多線程同步圖片下載入門,commons io: 是針對開發(fā)IO流功能的工具類庫,其中包含了許多可調(diào)用的函數(shù),感興趣的朋友跟隨小編一起看看吧2021-04-04
Java8 Optional優(yōu)雅空值判斷的示例代碼
這篇文章主要介紹了Java8 Optional優(yōu)雅空值判斷的相關知識,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-05-05

