BlogJava 聯(lián)系 聚合 管理  

          Blog Stats

          文章分類

          文章檔案


          xwgong

          向javaEE前進(jìn)

           1 package com.alipay.client.base;
           2 
           3 public class PartnerConfig {
           4     
           5     //合作商戶ID。用簽約支付寶賬號(hào)登錄ms.alipay.com后,在賬戶信息頁(yè)面獲取。
           6     public static final String PARTNER = "2088011096718773";
           7     // 賬戶ID。用簽約支付寶賬號(hào)登錄ms.alipay.com后,在賬戶信息頁(yè)面獲取。
           8     public static final String SELLER = "2088011096718773";
           9     // 商戶(RSA)私鑰
          10     public static final String RSA_PRIVATE = "";
          11                                                     
          12     // 支付寶(RSA)公鑰 用簽約支付寶賬號(hào)登錄ms.alipay.com后,在密鑰管理頁(yè)面獲取。
          13     public static final String RSA_ALIPAY_PUBLIC = "";
          14     
          15 }
          PartnerConfig.java為封裝商家提供的屬性類,參數(shù)全部由商戶提供或者技術(shù)生成
          PARTNER 與
          SELLER 為商戶提供的pid,可以再支付寶ms.alipay.com查看.
          RSA_PRIVATE為支付寶提供的openssl-0.9.8k_WIN32(RSA密鑰生成工具)生成商戶私鑰.根據(jù)商戶私鑰生成商戶公鑰(RSA密鑰生成工具),把商戶公鑰在支付寶的私鑰管理頁(yè)面進(jìn)行提交,支付寶會(huì)為商戶提供一個(gè)支付寶公鑰既RSA_ALIPAY_PUBLIC字段的值

          package com.alipay.client.callback;

          import java.io.PrintWriter;
          import java.io.UnsupportedEncodingException;
          import java.net.URLDecoder;

          import javax.servlet.http.HttpServlet;
          import javax.servlet.http.HttpServletRequest;
          import javax.servlet.http.HttpServletResponse;

          import com.alipay.client.base.PartnerConfig;
          import com.alipay.client.security.RSASignature;

          /**
           * 安全支付支付完成商戶同步處理程序
           * 對(duì)支付寶返回訂單信息驗(yàn)簽名
           
          */
          public class RSACallBack extends HttpServlet {


              private static final long serialVersionUID = -2234271646410251381L;
              
              //簽名成功
              public static final String RESULT_CHECK_SIGN_SUCCEED  = "T";
              //簽名失敗
              public static final String RESULT_CHECK_SIGN_FAILED = "F";
              
              @SuppressWarnings("unchecked")
              public void doPost(HttpServletRequest request, HttpServletResponse response)throws UnsupportedEncodingException {
                  //獲得待簽名數(shù)據(jù)和簽名值
                  String sign = URLDecoder.decode(request.getParameter("sign"),"utf-8");
                  String content = URLDecoder.decode(request.getParameter("content"),"utf-8");
                  
                  String retVal = RESULT_CHECK_SIGN_FAILED;
                  //使用支付寶公鑰驗(yàn)簽名
                  try {
                      PrintWriter out = response.getWriter();
                      if(RSASignature.doCheck(content, sign, PartnerConfig.RSA_ALIPAY_PUBLIC)){
                          retVal=RESULT_CHECK_SIGN_SUCCEED;
                      }
                      
                      response.setContentType("text/html");   
                      System.out.println("retVal : " + retVal);
                      out.print(retVal);
                      out.flush();
                      out.close();
                  } catch (Exception e) {
                      e.printStackTrace();
                      System.out.println("驗(yàn)簽名失敗");
                  }

              }
          }
          這個(gè)類基本不需要做修改,主要是RESULT_CHECK_SIGN_SUCCEED和RESULT_CHECK_SIGN_FAILED的值必須要與客戶端相應(yīng)代碼的相應(yīng)字段保持一致.這個(gè)類主要是支付完成之后客戶端與服務(wù)器進(jìn)行的一次驗(yàn)簽名,可以用來(lái)更新數(shù)據(jù)給客戶端.
          /**
           * Alipay.com Inc.
           * Copyright (c) 2005-2008 All Rights Reserved.
           
          */
          package com.alipay.client.notify;

          import java.io.IOException;
          import java.io.PrintWriter;
          import java.util.Date;
          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.IntegralDao;
          import com.airplane.dao.OrderDao;
          import com.airplane.dao.UserDao;
          import com.airplane.domain.Integral;
          import com.airplane.domain.Order;
          import com.airplane.domain.User;
          import com.alipay.client.base.PartnerConfig;
          import com.alipay.client.security.RSASignature;

          /**
           * 接收通知并處理
           * 
           * 
          @author 3y
           * 
          @version $Id: NotifyReceiver.java, v 0.1 2011-8-15 下午03:11:58 3y Exp $
           
          */
          public class RSANotifyReceiver extends HttpServlet {


              private static final long                          serialVersionUID = 7216412938937049671L;
              private static Log logger = LogFactory.getLog(RSANotifyReceiver.class);

              @SuppressWarnings("unchecked")
              public void doPost(HttpServletRequest request, HttpServletResponse response){
                  System.out.println("接收到通知!");
                  //獲得通知參數(shù)
                  try{
                  Map map = request.getParameterMap();
                  //獲得通知簽名
                  String sign = (String) ((Object[]) map.get("sign"))[0];
                  logger.info("sign="+sign);
                  //獲得待驗(yàn)簽名的數(shù)據(jù)
                  String verifyData = getVerifyData(map);
                  logger.info("verifyData="+verifyData);
                  boolean verified = false;
                  //使用支付寶公鑰驗(yàn)簽名
                  try {
                      verified = RSASignature.doCheck(verifyData, sign, PartnerConfig.RSA_ALIPAY_PUBLIC);
                      logger.info("verified="+verified);
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
                  PrintWriter out = response.getWriter();
                  //驗(yàn)證簽名通過(guò)
                  if (verified) {
                      //根據(jù)交易狀態(tài)處理業(yè)務(wù)邏輯
                      
          //當(dāng)交易狀態(tài)成功,處理業(yè)務(wù)邏輯成功。回寫success
                              logger.info("支付寶支付:保存數(shù)據(jù)庫(kù)信息success");
                              out.print("success");
                          }else{
                              out.print("fail");
                          }
                      }
                          
                      }else{
                          out.print("fail");
                      }
                  } else {
                      System.out.println("接收支付寶系統(tǒng)通知驗(yàn)證簽名失敗,請(qǐng)檢查!");
                      out.print("fail");
                  }
                  }catch (Exception e) {
                      e.printStackTrace();
                      logger.info(e);
                  }
              }

              public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
                  doPost(request, response);
              }

              /**
               * 獲得驗(yàn)簽名的數(shù)據(jù)
               * 
          @param map
               * 
          @return
               * 
          @throws Exception 
               
          */
              @SuppressWarnings("unchecked")
              private String getVerifyData(Map map) {
                  String notify_data = (String) ((Object[]) map.get("notify_data"))[0];
                  logger.info(notify_data);
                  return "notify_data="+notify_data;
              }
          }
          RSANotifyReceiver.java是支付寶回調(diào)服務(wù)器的servlet,需要安卓客戶端傳遞該servlet地址及相關(guān)參數(shù)給支付寶,支付寶會(huì)在支付完成之后進(jìn)行回調(diào).回調(diào)之后會(huì)返回消息給支付寶.
          /**
           * Alipay.com Inc.
           * Copyright (c) 2005-2008 All Rights Reserved.
           
          */
          package com.alipay.client.trade;

          import java.io.IOException;
          import java.io.PrintWriter;
          import java.io.UnsupportedEncodingException;
          import java.net.URLEncoder;
          import java.security.Security;

          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 org.bouncycastle.jce.provider.BouncyCastleProvider;

          import com.airplane.action.BackStageAction;
          import com.alipay.client.base.PartnerConfig;
          import com.alipay.client.security.RSASignature;
          import com.alipay.client.util.StringUtil;

          /**
           * 
           * 安全支付服務(wù)器端處理程序
           * 
           * 1.將業(yè)務(wù)參數(shù):合作商戶ID、 外部交易號(hào)、商品名稱、商品的具體描述、商品總價(jià)、賣家?guī)簟otify_url這些參數(shù)按照固定順序簽名
           * 2.將簽名結(jié)果返回客戶端
           * 
          @author 3Y
           
          */
          public class RSATrade extends HttpServlet {

              private static final long serialVersionUID = -3035307235076650766L;
              private static Log logger = LogFactory.getLog(RSATrade.class);
              static {
                    Security.addProvider(new BouncyCastleProvider());
                 }
              String basePath="";
              public void doPost(HttpServletRequest request, HttpServletResponse response)
                      throws IOException {
                  System.out.println("request in");
                  response.setCharacterEncoding("utf-8");
                  PrintWriter out = response.getWriter();
                  logger.info("here");
                  //得到應(yīng)用服務(wù)器地址
                  String path = request.getContextPath();
                  basePath = request.getScheme() + "://" + request.getLocalAddr() + ":"
                                             + request.getServerPort() + path + "/";
                  logger.info("here1");
                  String strReString="";
                  //檢查商戶PartnerConfig.java文件的配置參數(shù)
                  logger.info(checkInfo());
                  if(!checkInfo()){
                      strReString="<result><is_success>F</is_success><error>缺少partner或者seller," +
                              "請(qǐng)?jiān)赾om/alipay/client/base/PartnerConfig.java中增加</error></result>";
                      out.print(strReString);
                      return;
                  }
                  
                  String signData=getSignDate(request);
                  String sign = sign(signData,PartnerConfig.RSA_PRIVATE);
                  signData = URLEncoder.encode(signData,"utf-8");
                   sign = URLEncoder.encode(sign,"utf-8");
                  logger.info(signData);
                  logger.info(sign);
                  //返回待簽名數(shù)據(jù)和簽名數(shù)據(jù)
                  strReString="<result><is_success>T</is_success><content>"+signData+"</content><sign>"+sign+"</sign></result>";
                  logger.info(strReString);
                  //對(duì)返回客戶端的數(shù)據(jù)encode
                  out.print(strReString); 
                  return;
              }
              
              

              //檢查商戶PartnerConfig.java文件的配置參數(shù)
              private boolean checkInfo() {
                  String partner = PartnerConfig.PARTNER;
                  String seller = PartnerConfig.SELLER;
                  //如果合作商戶ID為空或者賬號(hào)ID為空返回false
                  if (StringUtil.isBlank(partner) || StringUtil.isBlank(seller))
                      return false;
                  
                  return true;
              }
              
              
              /**
               * 準(zhǔn)備待簽名的數(shù)據(jù)
               * 
               * 
          @param request
               * 
          @return
               * 
          @throws UnsupportedEncodingException
               
          */
              private String getSignDate(
                      HttpServletRequest request) throws UnsupportedEncodingException {
                  request.setCharacterEncoding("utf-8");
                  
                  //合作商戶ID
                  String partner = PartnerConfig.PARTNER;
                  //賣家?guī)ぬ?hào)
                  String seller = PartnerConfig.SELLER;
               // 外部交易號(hào) 這里取當(dāng)前時(shí)間,商戶可根據(jù)自己的情況修改此參數(shù),但保證唯一性
                  String outTradeNo = System.currentTimeMillis() + "";
                  String opt = request.getParameter("opt").trim();
                  String user_id = request.getParameter("user_id").trim();
                  //opt:0為支付,1為充值
                  if("0".equals(opt)){
                      outTradeNo = request.getParameter("order_id").trim();
                  }else if("1".equals(opt)){
                      outTradeNo = System.currentTimeMillis() + "";
                  }
                  
                  // 商品名稱
                  String subject = request.getParameter("subject").trim();
                  // 商品具體描述
                  String body = request.getParameter("body").trim();
                  // 商品總價(jià)
                  String totalFee = request.getParameter("total_fee").trim();
                  // 接收支付寶發(fā)送的通知的url 商戶可根據(jù)自己的情況修改此參數(shù)
                  String notify_url = basePath+"servlet/RSANotifyReceiver?opt=" + opt +"&order_id="+outTradeNo+"&user_id="+user_id+"&payMoney="+totalFee;
                  
                  //組裝待簽名數(shù)據(jù)
                  String signData = "partner=" + "\"" + partner + "\"";
                  signData += "&";
                  signData += "seller=" + "\"" + seller + "\"";
                  signData += "&";
                  signData += "out_trade_no=" + "\"" + outTradeNo + "\"";
                  signData += "&";
                  signData += "subject=" + "\"" + subject+ "\"";
                  signData += "&";
                  signData += "body=" + "\"" + body + "\"";
                  signData += "&";
                  signData += "total_fee=" + "\""+ totalFee + "\"";
                  signData += "&";
                  signData += "notify_url=" + "\""+notify_url+ "\"";
                  return signData;
              }

              
              
              /**
               * 對(duì)參數(shù)進(jìn)行簽名
               * 
               * 
          @param signData 待簽名數(shù)據(jù),key rsa商戶私鑰
               * 
          @return
               
          */
              private String sign(String signData,String key) {
                  System.out.println("signData:"+signData);
                  String sign = "";
                  try {
                      sign = RSASignature.sign(signData, key);
                  } catch (Exception e1) {
                      e1.printStackTrace();
                  }
                  return sign;
              }

              
          }
          RSATrade.java為客戶端與服務(wù)器端為商品信息進(jìn)行的簽名操作,簽名完成之后服務(wù)器會(huì)將簽名信息以及回調(diào)地址返給客戶端.客戶端拿到回調(diào)地址交給支付寶進(jìn)行回調(diào).
          支付寶流程為:客戶端在支付寶支付之前請(qǐng)求RSATrade.java,此時(shí)服務(wù)器為商品信息注冊(cè)簽名,簽名完成之后服務(wù)器把簽名過(guò)的商品信息和支付寶的回調(diào)地址(RSANotifyReceiver
          )和參數(shù)傳給客戶端,客戶端會(huì)把回調(diào)地址和簽過(guò)名的商品信息交給支付寶,支付寶在完成支付之后請(qǐng)求回調(diào)地址,進(jìn)行簽名和公鑰驗(yàn)證,驗(yàn)證成功即可執(zhí)行持久化操作.若操作成功,客戶端會(huì)請(qǐng)求RSACallBack.java類,進(jìn)行客戶端與服務(wù)器端的同步操作.
          posted on 2013-08-14 14:12 龔小偉 閱讀(8517) 評(píng)論(5)  編輯  收藏 所屬分類: 支付

          評(píng)論

          # re: 支付寶快捷支付(安卓版)的服務(wù)器開發(fā)流程 2013-12-26 22:58 迷途小書童
          求教:
          對(duì)于// 商戶(RSA)私鑰
          public static final String RSA_PRIVATE = "";
          這項(xiàng)是放在服務(wù)器端工作?
          不能放在手機(jī)客戶端嗎?

          商戶密鑰泄露會(huì)導(dǎo)致什么問(wèn)題?  回復(fù)  更多評(píng)論
            

          # re: 支付寶快捷支付(安卓版)的服務(wù)器開發(fā)流程 2013-12-27 14:15 gxw
          @迷途小書童
          商戶私鑰可以放在客戶端.支付寶是通過(guò)商戶私鑰生產(chǎn)商戶公鑰,通過(guò)商戶公鑰上傳給支付寶服務(wù)器,生產(chǎn)支付寶公鑰,給商品簽名的時(shí)候拿著商戶私鑰和支付寶公鑰進(jìn)行簽名以及后續(xù)的驗(yàn)簽,即使盜用商戶私鑰,也不會(huì)產(chǎn)生任何安全問(wèn)題  回復(fù)  更多評(píng)論
            

          # re: 支付寶快捷支付(安卓版)的服務(wù)器開發(fā)流程 2015-08-09 11:00 steaming
          如何得到訂單號(hào)對(duì)應(yīng)的商品信息 只有訂單號(hào) 價(jià)格 狀態(tài)不行吧 不知道買的什么 是將訂單號(hào)設(shè)置為商品id嗎 還是別的方式  回復(fù)  更多評(píng)論
            

          # re: 支付寶快捷支付(安卓版)的服務(wù)器開發(fā)流程 2015-08-27 09:55 龔小偉
          @steaming
          商品信息應(yīng)該有對(duì)應(yīng)的商品id 你可以把商品id放到支付寶的回調(diào)地址中。即把商品id拼接到notify_url這個(gè)參數(shù)  回復(fù)  更多評(píng)論
            

          # re: 支付寶快捷支付(安卓版)的服務(wù)器開發(fā)流程 2015-09-29 19:46 zzapplet
          是否支持并發(fā)不在于sql怎么寫,而在于你的事物控制:
          例如:spring中的
          @Transactional(rollbackFor = Throwable.class, isolation = Isolation.SERIALIZABLE)

          寫代碼不僅僅要面向?qū)ο螅乙蟹謱拥乃枷搿?nbsp; 回復(fù)  更多評(píng)論
            


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 嘉定区| 正安县| 肇庆市| 五指山市| 日喀则市| 油尖旺区| 泰来县| 江安县| 弥勒县| 连云港市| 南康市| 南丹县| 永安市| 谷城县| 鲁山县| 普宁市| 哈巴河县| 安泽县| 竹山县| 汝阳县| 阳信县| 保靖县| 鄢陵县| 邯郸市| 金湖县| 隆尧县| 申扎县| 监利县| 屏东县| 崇阳县| 昔阳县| 县级市| 金溪县| 托克逊县| 望谟县| 平乡县| 沁阳市| 彭水| 泰兴市| 重庆市| 叙永县|