統一下單 、掉起支付接口、回調支付結果通知
這裏將以APP支付做示例
- 準備工作 可以下載官方的demo使用裏面的輔助類
首先將你的商戶號、AppID、商戶祕鑰啥的重要點的信息可以單獨用一個類保存下來.
public class ConstantUtil {
// 商戶密鑰
public static String PARTNER_KEY = "你的商戶祕鑰";// 商戶祕鑰
// 應用ID
public static String APPID = "APPID";// AppID
// 商戶號
public static String MCH_ID = "商戶號";
public final static String SIGN_TYPE = "MD5";// 簽名加密方式
// 微信統一下單接口路徑
public static String UNIFIED_ORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
}
- 統一下單
//這個是回調的接口url
public final static String notify_url = "http://你的域名或者IP:8080/appWXPay/wxNotify";
@RequestMapping(value = "/getWxPayParameters")
@ResponseBody
public Map<String,Object> getWxPayParameters(HttpServletRequest request) {
Map<String, Object> map = new HashMap<String, Object>();
//根據id查詢訂單號
AppActivityRecord goodsTrade = appActivityRecordService.findOrderNo(Integer.valueOf( request.getParameter("id")));
//我這裏是根據數據庫查詢相應的訂單信息 實際按照自己的需求來即可
Double price = goodsTrade.getMoney(); //根據id獲得訂單金額
// // 防止抓包修改訂單金額造成損失
if (price < 0) {
map.put("stateCode",State.NO_MESSAGE_FIND.getValue());
map.put("msg","付款金額錯誤!");
return map;
}
//微信價格最小單位分 轉換爲整數
DecimalFormat df = new DecimalFormat("#######.##");
price = price * 100;//這裏是要支付的金額 再乘以100 (注:這裏微信是以分的形式) 比如:你支付的是一元 前端傳給你的是 1(實際在微信是0.01元) 再由你這裏 做一個乘以100的處理,到達微信即1元
price = Math.ceil(price);
String totalAmount= df.format(price);
try {
SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
parameters.put("appid", ConstantUtil.APPID);//這裏的appid 就是你的商戶號
parameters.put("body", "自定義");//這個是支付頁的顯示的字符串
parameters.put("mch_id", ConstantUtil.MCH_ID);//這是你的商戶號
parameters.put("nonce_str", PayCommonUtil.CreateNoncestr());//這個是隨機字符創(輔助類中有)
parameters.put("notify_url", notify_url); //請求成功返回路徑
parameters.put("out_trade_no", goodsTrade.getOrderno()); //訂單號(就是你自己生成的訂單號)
parameters.put("spbill_create_ip", getIpAddr(request));//這個是IP地址
parameters.put("total_fee", totalAmount); //單位爲分 金額
parameters.put("trade_type", "APP"); //支付類型APP(默認爲APP 不做修改)
System.out.print("=========================={金額:total_fee}:"+totalAmount);
//設置簽名
String sign = PayCommonUtil.createSign("UTF-8", parameters);
parameters.put("sign", sign);
String requestXML = PayCommonUtil.getRequestXml(parameters);
String result = PayCommonUtil.httpsRequest(ConstantUtil.UNIFIED_ORDER_URL, "POST", requestXML);
System.out.print("\n統一下單:{}{}{}========>>>>>>" + result);
if (result.equals("")) {
logger.info("error:統一支付接口下單失敗");
//throw new Exception("error:統一支付接口下單失敗");
map.put("msg","error:統一支付接口下單失敗!");
return map;
}
SortedMap<Object, Object> parMap = AppWXPayController.startWXPay(result);
//logger.debug("最終的map是:" + parMap.toString());
if (parMap == null) {
map.put("stateCode",State.NO_MESSAGE_FIND.getValue());
map.put("msg","支付出現異常,請稍後重試!");
return map;
}
} catch (Exception e) {
e.printStackTrace();
map.put("stateCode",State.NO_MESSAGE_FIND.getValue());
map.put("msg","程序異常");
logger.error(e.getMessage());
return map;
}
return map;
}
2.掉起支付接口
public static SortedMap<Object, Object> startWXPay(String result) {
try {
Map<String, String> map = XmlFormat.doXMLParse(result);
String time = Long.toString(System.currentTimeMillis());
SortedMap<Object, Object> parameterMap = new TreeMap<Object, Object>();
parameterMap.put("appid", ConstantUtil.APPID);//依舊是你的APPID
parameterMap.put("partnerid", ConstantUtil.MCH_ID);//你的商戶號
parameterMap.put("prepayid", map.get("prepay_id"));
parameterMap.put("package", "Sign=WXPay");
parameterMap.put("noncestr", PayCommonUtil.CreateNoncestr());//隨機字符串
parameterMap.put("timestamp", time);
String sign = PayCommonUtil.createSign("UTF-8", parameterMap);
parameterMap.put("sign", sign);
logger.info("\t\t====>>>>>>{startWXPay方法:}二次簽名後返回的數據是:" + parameterMap.toString());
return parameterMap;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
3.回調(支付結果通知)
@RequestMapping("/wxNotify")
@ResponseBody
public void wxNotify(HttpServletRequest request, HttpServletResponse response) throws IOException, JDOMException {
//讀取參數
InputStream inputStream;
StringBuffer sb = new StringBuffer();
inputStream = request.getInputStream();
String s;
BufferedReader in = new BufferedReader(new InputStreamReader( inputStream, "UTF-8"));
while ((s = in.readLine()) != null) {
sb.append(s);
}
in.close();
inputStream.close();
//解析xml成map
Map<String, String> m = new HashMap<String, String>();
m = XmlFormat.doXMLParse(sb.toString());
for (Object keyValue : m.keySet()) {
System.out.println(keyValue + "=" + m.get(keyValue));
}
//過濾空 設置 TreeMap
SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
Iterator it = m.keySet().iterator();
while (it.hasNext()) {
String parameter = (String) it.next();
String parameterValue = m.get(parameter);
String v = "";
if (null != parameterValue) {
v = parameterValue.trim();
}
packageParams.put(parameter, v);
}
//判斷簽名是否正確
String resXml = "";
if (PayCommonUtil.isTenpaySign("UTF-8", packageParams)) {
if ("SUCCESS".equals((String) packageParams.get("result_code"))) {
// 這裏是支付成功
String mch_id = (String) packageParams.get("mch_id"); //商戶號
String openid = (String) packageParams.get("openid");
//String is_subscribe = (String)packageParams.get("is_subscribe");
String out_trade_no = (String) packageParams.get("out_trade_no"); //商戶訂單號
String total_fee = (String) packageParams.get("total_fee");
String transaction_id = (String) packageParams.get( "transaction_id"); //微信支付訂單號
//執行自己業務邏輯
logger.info(">>>>>>>>>支付成功");
//通知微信.異步確認成功.必寫.不然會一直通知後臺.八次之後就認爲交易失敗了.
resXml = "<xml>" +
"<return_code><![CDATA[SUCCESS]]></return_code>" +
"<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
//===========================分割線===============================
//以下便是做支付成功後的操作啦
AppActivityRecord gt = new AppActivityRecord();
gt.setOrderno(out_trade_no);
//查詢訂單 根據訂單號查詢訂單
AppActivityRecord trade = appActivityRecordService.getInfo(gt);
if (trade != null) {
//-----修改支付狀態 交易類型 交易時間 訂單狀態
AppActivityRecord payState = new AppActivityRecord();
payState.setPayState(AppActivityRecord.payState_yes);
payState.setPayType("在線支付");
payState.setPaytime(new Date());
payState.setOrderno(out_trade_no);
int result = appActivityRecordService.updatePayState(payState);
if (result == 1) { logger.info(">>> 修改狀態成功>>>\t" +result); }
}
} else {
logger.info("支付失敗,錯誤信息:" + packageParams.get("err_code"));
resXml = "<xml>" +
"<return_code><![CDATA[FAIL]]></return_code>" +
"<return_msg><![CDATA[報文爲空]]></return_msg>" + "</xml> ";
}
} else {
resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" +
"<return_msg><![CDATA[通知簽名驗證失敗]]></return_msg>" + "</xml> ";
logger.info("通知簽名驗證失敗");
}
//------------------------------
//處理業務完畢
//------------------------------
BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
out.write(resXml.getBytes());
out.flush();
out.close();
}
到這裏就完成了…