一,銀聯支付的整體流程
客戶端提供服務器給服務器訂單信息----服務器端拿到數據推送給銀聯指定的地址----銀聯給服務器端返回一個流水賬號----服務器將流水賬號返給客戶端
----客戶端由于集成了銀聯控件,根據流水賬號調用銀聯支付界面進行支付----支付完成之后銀聯會回調服務器端提供的回調地址----服務器端根據回調參數處理業務邏輯
二,服務器端主要代碼解析.
upmp.properties
security.key=******//銀聯技術給我們提供的商戶密鑰
mer.id=88000000000***** //商戶的銀聯賬號
mer.back.end.url=/servlet/unionpaycallback//支付成功后銀聯的回調地址
mer.front.end.url=http://www.yourdomain.com/your_path/yourFrontEndUrl//支付成功后銀聯回調的前段地址,可不填
# message info
version=1.0.0//版本號
charset=UTF-8//編碼
sign.method=MD5//加密方法
# server url
upmp.trade.url=http://222.66.233.198:8080/gateway/merchant/trade//處理交易請求的銀聯地址
upmp.query.url=http://222.66.233.198:8080/gateway/merchant/query//查詢交易的銀聯地址
card=6226440123456785//銀聯提供的測試賬戶
password=111101//銀聯提供的測試密碼
下面是給銀聯推送訂單的代碼.
/**
* 銀聯支付推送給銀聯
*/
public String executeUnionPayMoney(String auth, String info, String basePath) {
//returnMap--返回的Map
//returnParams--定義的參數返回類型
Map<String,Object> returnMap = new HashMap<String,Object>();
String result ="";
try{
//把info中的信息解析成map
@SuppressWarnings("unchecked")
Map<String,Object> map = JSON.parseObject(info, Map.class);
OrderDao orderDao = (OrderDao) ac.getBean("orderDao");
if(map.get("order_id")!=null&&!map.get("order_id").equals("")&&
map.get("user_id")!=null&&!map.get("user_id").equals("")&&
map.get("payMoney")!=null&&!map.get("payMoney").equals("")){
//把訂單數據推給銀聯(訂單推送接口),根據返回結果是否為true
Order order = orderDao.getById(Long.valueOf(map.get("order_id").toString()));
Map<String, String> req = new HashMap<String, String>();
Map<String, String> reqReservedMap = new HashMap<String, String>();
reqReservedMap.put("user_id", map.get("user_id").toString());
reqReservedMap.put("order_id", map.get("order_id").toString());
reqReservedMap.put("opt", "0");//自己自定義的參數,把Map轉換成json字符串,通過請求方保留域reqReserved傳遞給銀聯,方便銀聯回調服務器時,服務器處理業務邏輯使用
req.put("version", UpmpConfig.VERSION);// 版本號
req.put("charset", UpmpConfig.CHARSET);// 字符編碼
req.put("transType", "01");// 交易類型
req.put("merId", UpmpConfig.MER_ID);// 商戶代碼
//req.put("backEndUrl",basePath.substring(0, basePath.length()-1) + UpmpConfig.MER_BACK_END_URL);// 通知URL
req.put("backEndUrl",basePath.substring(0, basePath.length()-1) + UpmpConfig.MER_BACK_END_URL);// 通知URL 我自己提供給銀聯支付成功后的回調地址
req.put("frontEndUrl", UpmpConfig.MER_FRONT_END_URL);// 前臺通知URL(可選)
req.put("orderDescription", "航空機票付款");// 訂單描述(可選)
req.put("orderTime", new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));// 交易開始日期時間yyyyMMddHHmmss
req.put("orderTimeout", "");// 訂單超時時間yyyyMMddHHmmss(可選);默認的是一小時
req.put("orderNumber", orderDao.getById(Long.valueOf(map.get("order_id").toString())).getOrderNum());//訂單號(商戶根據自己需要生成訂單號)
req.put("orderAmount", Integer.valueOf(map.get("payMoney").toString())*100+"");// 訂單金額;因為這里默認的單位是分,而通??蛻舳藗鬟^來的單位是元,所以需要再此
//處進行*100的操作,防止因為單位換算導致支付出現問題,需要注意的是:銀聯回調時你如果從回調的參數中拿settleAmount,記得進行除100的操作
req.put("orderCurrency", "156");// 交易幣種(可選) 156代表人民幣
req.put("reqReserved", new Gson().toJson(reqReservedMap));// 請求方保留域(可選,用于透傳商戶信息)//此處用于傳遞咱們自己的參數,可以再銀聯回調時使用,
//此處我是以json字符串的方式傳遞參數的,之后解析json字符串即可獲取相關參數.
Map<String, String> resp = new HashMap<String, String>();
boolean validResp = UpmpService.trade(req, resp);
if(order.getPayState()==0){
returnMap.put("errcode",-98);
returnMap.put("msg","該訂單已支付");
}else{
// 商戶的業務邏輯
if (validResp){
// 服務器應答簽名驗證成功
returnMap.put("tn", resp.get("tn"));//交易流水號,默認的參數就是tn
returnMap.put("errcode",0);
returnMap.put("msg","成功返回流水號");
}else {
// 服務器應答簽名驗證失敗
returnMap.put("errcode",-100);
returnMap.put("msg","系統出錯");
}
}
}else {
returnMap.put("errcode",-9);
returnMap.put("msg","傳值錯誤");
}
}catch (Exception e) {
e.printStackTrace();
returnMap.put("errcode",-99);
returnMap.put("msg","服務器出現異常");
}
result=JSON.toJSONString(returnMap);
return result;
}
CallBackUnionPay.java
這個是我自己寫的一個銀聯回調的servlet,opt為自定義參數,opt=0代表支付訂單,opt=1代表充值操作
/**
* Alipay.com Inc.
* Copyright (c) 2005-2008 All Rights Reserved.
*/
package com.unionpay.upmp.sdk.callback;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.airplane.base.AbstractExecution;
import com.airplane.dao.AccountDao;
import com.airplane.dao.IntegralDao;
import com.airplane.dao.OrderDao;
import com.airplane.dao.UserDao;
import com.airplane.domain.Account;
import com.airplane.domain.Integral;
import com.airplane.domain.Order;
import com.airplane.domain.User;
import com.google.gson.Gson;
import com.unionpay.upmp.sdk.service.UpmpService;
/**
* 接收通知并處理
*
* @author gxw
*/
public class CallBackUnionPay extends HttpServlet {
private static final long serialVersionUID = 7216412938937049671L;
private static Log logger = LogFactory.getLog(CallBackUnionPay.class);
@SuppressWarnings("unchecked")
public void doPost(HttpServletRequest request, HttpServletResponse response){
logger.info("==============================here===========================");
System.out.println("接收到通知!");
PrintWriter out;
try {
out = response.getWriter();
Map<String,String> params = new HashMap<String,String>();
Map requestParams = request.getParameterMap();
logger.info("request的參數:"+requestParams);
for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
String name = (String) iter.next();
String[] values = (String[]) requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i]
: valueStr + values[i] + ",";
}
params.put(name, valueStr);
}
logger.info("request處理后的參數:"+params);
Map<String,String> personParams = new Gson().fromJson(params.get("reqReserved"), Map.class);//解析在上一步自定義的json參數,方便處理業務邏輯.
if(UpmpService.verifySignature(params)){// 服務器簽名驗證成功
//請在這里加上商戶的業務邏輯程序代碼
if("0".equals(personParams.get("opt"))){
String user_id = personParams.get("user_id");
String order_id = personParams.get("order_id");
logger.info("user_id"+user_id+"&order_id="+order_id);
//獲取通知返回參數,可參考接口文檔中通知參數列表(以下僅供參考)
String transStatus = request.getParameter("transStatus");// 交易狀態
if (null != transStatus && transStatus.equals("00")) {
// 交易處理成功
}
out.println("success");
}
if("1".equals(personParams.get("opt"))){
String payMoney2 = params.get("settleAmount");
String user_id2 = personParams.get("user_id");
//獲取通知返回參數,可參考接口文檔中通知參數列表(以下僅供參考)
String transStatus2 = request.getParameter("transStatus");// 交易狀態
if (null != transStatus2 && transStatus2.equals("00")) {
// 交易處理成功
}
out.println("success");
}
else{// 服務器簽名驗證失敗
out.println("fail");
}
}
}catch (IOException e) {
e.printStackTrace();
logger.error(e);
}
}
/*public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
doPost(request, response);
}*/
}