1. 程式人生 > >微信支付 java 服務端demo (v3版本app支付 springMVC框架中)

微信支付 java 服務端demo (v3版本app支付 springMVC框架中)

//靜態資源

/** 
 * @author 徐小驥
 * @version :2016-5-9 上午11:43:48 
 */

public class WeixinPayConstants {
	public static final String appid = "XXXXXX";//在微信開發平臺登記的app應用
	public static final String appsecret = "XXXXXXXXX";
	public static final String partner = "XXXXXXXXX";//商戶號
	public static final String partnerkey ="XXXXXXXXXXXXXXXXXXXXXXXXXXXXX";//不是商戶登入密碼,是商戶在微信平臺設定的32位長度的api祕鑰,
	public static final String createOrderURL="https://api.mch.weixin.qq.com/pay/unifiedorder";
	public static final String backUri="http://XXXXXXXX/api/weixin/topay.jhtml";//微信支付下單地址
	public static final String notify_url="http://XXXXXXXXXX/api/weixin/notify.jhtml";//非同步通知地址
}

//

/** 
 * @author 徐小驥
 * @version :2016-5-9 上午11:46:48 
 */
@Controller("weixinPayController")
@RequestMapping("/api/weixin")
public class WeixinPayController {
@Resource(name = "memberServiceImpl")
private MemberService memberService;
@Resource(name = "orderServiceImpl")
private RecordsConsumptionService  recordsConsumptionService;
//商戶相關資料 
private static String appid = WeixinPayConstants.appid;
private static String appsecret = WeixinPayConstants.appsecret;
private static String partner = WeixinPayConstants.partner;
private static String partnerkey = WeixinPayConstants.partnerkey;
@RequestMapping(value = "/topay") 
@ResponseBody public void topay(HttpServletRequest request,HttpServletResponse response) throws Exception{
	request.setCharacterEncoding("UTF-8");
	response.setCharacterEncoding("UTF-8");
	response.setContentType("text/html;charset=UTF-8");
	String orderNo= request.getParameter("Orderid");
	String mobile= request.getParameter("mobile");
	PrintWriter out = response.getWriter();
	String json=null;
     JSONObject retMsgJson=new JSONObject();
	if(orderNo==null||mobile==null){
		retMsgJson.put("msg", "error");
		retMsgJson.put("body", "資料請求異常");
		json=retMsgJson.toString();					
	    out.write(json);
	    out.close();
	    return;
	}
	Member member=memberService.findListByMobile(mobile);//獲取使用者資料
	Order order=orderService.find(Long.valueOf(orderNo));//獲取訂單資料
     //驗證訂單與支付會員關係
     if(member==null||order==null){
		retMsgJson.put("msg", "error");
		retMsgJson.put("body", "資料請求異常");
		json=retMsgJson.toString();					
	    out.write(json);
	    out.close();
	    return;
	}
	if(!order.getMember().equals(member)){
		retMsgJson.put("msg", "error");
		retMsgJson.put("body", "無許可權處理訂單");
		json=retMsgJson.toString();					
	    out.write(json);
	    out.close();
	    return;
	}
	if(!order.getPaymentStatus().equals(Order.PaymentStatus.unpaid)){
		retMsgJson.put("msg", "error");
		retMsgJson.put("body", "訂單狀態異常");
		json=retMsgJson.toString();					
	    out.write(json);
	    out.close();
	    return;
	}
	String userId = member.getId().toString(); 	
	String money = order.getAmount().toString();//獲取訂單金額
	//金額轉化為分為單位
	float sessionmoney = Float.parseFloat(money);
	String finalmoney = String.format("%.2f", sessionmoney);
	finalmoney = finalmoney.replace(".", "");
			String currTime = TenpayUtil.getCurrTime();
			//8位日期
			String strTime = currTime.substring(8, currTime.length());
			//四位隨機數
			String strRandom = TenpayUtil.buildRandom(4) + "";
			//10位序列號,可以自行調整。
			String strReq = strTime + strRandom;		
			//商戶號
			String mch_id = partner;
			//子商戶號  非必輸
			//String sub_mch_id="";
			//裝置號   非必輸
			String device_info="";
			//隨機數 
			String nonce_str = strReq;
			String body = order.getName();
			//附加資料
			String attach = userId;
			//商戶訂單號
			String out_trade_no = order.getSn()+"|"+System.currentTimeMillis();//訂單編號加時間戳
			int intMoney = Integer.parseInt(finalmoney);			
			//總金額以分為單位,不帶小數點
			String total_fee = String.valueOf(intMoney);
			//訂單生成的機器 IP
			String spbill_create_ip = request.getRemoteAddr();
            String notify_url =WeixinPayConstants.notify_url;//微信非同步通知地址			
			String trade_type = "APP";//app支付必須填寫為APP
                        //對以下欄位進行簽名
            SortedMap<String, String> packageParams = new TreeMap<String, String>();
			packageParams.put("appid", appid);  
			packageParams.put("attach", attach); 
			packageParams.put("body", body);  
			packageParams.put("mch_id", mch_id);  	
			packageParams.put("nonce_str", nonce_str);  
			packageParams.put("notify_url", notify_url);  
			packageParams.put("out_trade_no", out_trade_no);  	
			packageParams.put("spbill_create_ip", spbill_create_ip); 
			packageParams.put("total_fee", total_fee);
			packageParams.put("trade_type", trade_type);  
			RequestHandler reqHandler = new RequestHandler(request, response);
			reqHandler.init(appid, appsecret, partnerkey);		
			String sign = reqHandler.createSign(packageParams);//獲取簽名
			String xml="<xml>"+
					"<appid>"+appid+"</appid>"+
					"<attach>"+attach+"</attach>"+
					"<body><![CDATA["+body+"]]></body>"+
					"<mch_id>"+mch_id+"</mch_id>"+
					"<nonce_str>"+nonce_str+"</nonce_str>"+
					"<notify_url>"+notify_url+"</notify_url>"+
					"<out_trade_no>"+out_trade_no+"</out_trade_no>"+
					"<spbill_create_ip>"+spbill_create_ip+"</spbill_create_ip>"+
					"<total_fee>"+total_fee+"</total_fee>"+
					"<trade_type>"+trade_type+"</trade_type>"+
					"<sign>"+sign+"</sign>"+
					"</xml>";
			String allParameters = "";
			try {
				allParameters =  reqHandler.genPackage(packageParams);
			 } catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			String createOrderURL = WeixinPayConstants.createOrderURL;
			String prepay_id="";
			try {
				prepay_id = new GetWxOrderno().getPayNo(createOrderURL, xml);
				if(prepay_id.equals("")){
				retMsgJson.put("msg", "error");
				json=retMsgJson.toString();					
			    out.write(json);
				out.close();
				return;
				 }
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			 }
                        //獲取到prepayid後對以下欄位進行簽名最終傳送給app
                       SortedMap<String, String> finalpackage = new TreeMap<String, String>();
			String timestamp = Sha1Util.getTimeStamp();
			finalpackage.put("appid", appid);  
			finalpackage.put("timestamp", timestamp);  
			finalpackage.put("noncestr", nonce_str);  
			finalpackage.put("partnerid", WeixinPayConstants.partner); 
			finalpackage.put("package", "Sign=WXPay");  			
			finalpackage.put("prepayid", prepay_id);  
  			String finalsign = reqHandler.createSign(finalpackage);
			        retMsgJson.put("msg", "ok");
					retMsgJson.put("appid", appid);
					retMsgJson.put("timestamp", timestamp);
					retMsgJson.put("noncestr", nonce_str);
					retMsgJson.put("partnerid", WeixinPayConstants.partner);
					retMsgJson.put("prepayid", prepay_id);
					retMsgJson.put("package", "Sign=WXPay");
					retMsgJson.put("sign", finalsign);
					json=retMsgJson.toString();					
			        out.write(json);
			        out.close();
}
//微信非同步通知
@RequestMapping(value = "/notify") 
@ResponseBody public void notify(HttpServletRequest request,HttpServletResponse response) throws Exception{
	request.setCharacterEncoding("UTF-8");
	response.setCharacterEncoding("UTF-8");
	response.setContentType("text/html;charset=UTF-8");
	response.setHeader("Access-Control-Allow-Origin", "*"); 
    InputStream in=request.getInputStream();
    ByteArrayOutputStream out=new ByteArrayOutputStream();
    byte[] buffer =new byte[1024];
    int len=0;
    while((len=in.read(buffer))!=-1){
    	out.write(buffer, 0, len);
    }
    out.close();
    in.close();
    String msgxml=new String(out.toByteArray(),"utf-8");//xml資料
    System.out.println(msgxml);   
    Map map =  new GetWxOrderno().doXMLParse(msgxml);
    String result_code=(String) map.get("result_code");
    String out_trade_no  = (String) map.get("out_trade_no");
    String total_fee  = (String) map.get("total_fee");
    String sign  = (String) map.get("sign");
    Double amount=new Double(total_fee)/100;//獲取訂單金額
    String attach= (String) map.get("attach");
    String sn=out_trade_no.split("\\|")[0];//獲取訂單編號
    Long memberid=Long.valueOf(attach);
    Member member=memberService.find(memberid);
	Order order=orderService.findBySn(sn);
	if(result_code.equals("SUCCESS")&&member!=null&&order!=null){
	  //驗證簽名
		float sessionmoney = Float.parseFloat(order.getAmount().toString());
		String finalmoney = String.format("%.2f", sessionmoney);
		finalmoney = finalmoney.replace(".", "");
		int intMoney = Integer.parseInt(finalmoney);			
		//總金額以分為單位,不帶小數點
	    String order_total_fee = String.valueOf(intMoney);
	    String fee_type  = (String) map.get("fee_type");
	    String bank_type  = (String) map.get("bank_type");
	    String cash_fee  = (String) map.get("cash_fee");
        String is_subscribe  = (String) map.get("is_subscribe");
	    String nonce_str  = (String) map.get("nonce_str");
	    String openid  = (String) map.get("openid");
	    String return_code  = (String) map.get("return_code");
	    String sub_mch_id  = (String) map.get("sub_mch_id");
	    String time_end  = (String) map.get("time_end");
	    String trade_type  = (String) map.get("trade_type");
	    String transaction_id  = (String) map.get("transaction_id");
                //需要對以下欄位進行簽名
        SortedMap<String, String> packageParams = new TreeMap<String, String>();
		packageParams.put("appid", appid);  
		packageParams.put("attach", order.getMember().getId().toString()); //用自己系統的資料:會員id
		packageParams.put("bank_type", bank_type);  
		packageParams.put("cash_fee", cash_fee);  
		packageParams.put("fee_type", fee_type);  	
   		packageParams.put("is_subscribe", is_subscribe);  
		packageParams.put("mch_id", partner);  
		packageParams.put("nonce_str", nonce_str);  	
		packageParams.put("openid", openid); 
		packageParams.put("out_trade_no", out_trade_no);
 		packageParams.put("result_code", result_code);  
		packageParams.put("return_code", return_code);  	
 		packageParams.put("sub_mch_id", sub_mch_id); 
		packageParams.put("time_end", time_end);
		packageParams.put("total_fee", order_total_fee);	//用自己系統的資料:訂單金額
		packageParams.put("trade_type", trade_type); 
		packageParams.put("transaction_id", transaction_id);
		RequestHandler reqHandler = new RequestHandler(request, response);
		reqHandler.init(appid, appsecret, partnerkey);		
		String endsign = reqHandler.createSign(packageParams);
		if(sign.equals(endsign)){//驗證簽名是否正確  官方簽名工具地址:https://pay.weixin.qq.com/wiki/tools/signverify/ 
			if("訂單沒有支付"){
				try{
				//處理自己的業務邏輯
				response.getWriter().write(setXml("SUCCESS", "OK"));	//告訴微信已經收到通知了
				}catch(Exception e){
					System.out.println("微信支付非同步通知異常");
				}
			}else if("訂單支付了"){
				response.getWriter().write(setXml("SUCCESS", "OK"));	//告訴微信已經收到通知了
			}
	
		}
	}
    }
	public static String setXml(String return_code,String return_msg){
		return "<xml><return_code><![CDATA["+return_code+"]]></return_code><return_msg><![CDATA["+return_msg+"]]></return_msg></xml>";
}
}
 

附上本文微信app支付開發所用到的工具類下載地址
http://download.csdn.net/detail/xu_xiao_ji/9516695