1. Alipay new version simplifies the code, eliminating the need to own signature configuration parameters, stitching parameters troubles, plain and simple.
public static String buildAlipayRequest (AlipayVo alipayVo) { String alipayInfo = null ; // instantiate client AlipayClient alipayClient = new new DefaultAlipayClient (ALIPAY_URL, alipayVo.getAppId (), alipayVo.getAppPrivateKey (), the FORMAT, CHARSET_UTF8, alipayVo.getAlipayPublicKey (), sign_type); // instantiate API corresponding to the specific request class corresponding to the class name and an interface name, the current call interface name: alipay.trade.app.pay AlipayTradeAppPayRequest request = new new AlipayTradeAppPayRequest (); // the SDK package has lost the common parameters , where only incoming traffic parameters. The following methods sdk embodiment of model parameters into the (case of the model and take biz_content biz_content simultaneously present). AlipayTradeAppPayModel model =new new AlipayTradeAppPayModel (); model.setBody ( "AlipayTrade" ); model.setSubject (alipayVo.getSubject ()); model.setOutTradeNo (alipayVo.getOutTradeNo ()); model.setTimeoutExpress ( "30m" ); model.setTotalAmount (alipayVo .getTotalAmount ()); model.setProductCode ( "QUICK_MSECURITY_PAY" ); request.setBizModel (Model); request.setNotifyUrl (alipayVo.getNotifyUrl ()); the try { // here and different common interface calls, using sdkExecute AlipayTradeAppPayResponse = Response alipayClient.sdkExecute (Request); log.info (response.getBody ()); //Is orderString can give the client requests directly, do not need treatment. = alipayInfo response.getBody (); } the catch (AlipayApiException E) { e.printStackTrace (); } return alipayInfo; }
2. Because the project uses to filter, resulting in sign signed data in "+" is replaced by "" Can not get the original sign
java.security.SignatureException: Signature length not correct: got 253 but was expecting 256
Simple treatment is to replace to replace spaces with plus sign
sign = sign.replace(" ", "+");
3. Alipay relative to the document, the development of micro-letter more complicated, many of them need to develop their own implementation. Micro-channel tools, for reference.
public class WxpayUtil { private static final Logger log = LoggerFactory.getLogger(WxpayUtil.class); private static final String GATEURL = "https://api.mch.weixin.qq.com/pay/unifiedorder"; /** * 获取微信预支付prepayid * @param weixinpayVo * @return */ public static JSONObject buildWxpayRequest(WeixinpayVo weixinpayVo){ String noncestr = getNonceStr(); SortedMap<Object, Object> parameters = new TreeMap<Object, Object>(); Parameters.put ( "AppID", weixinpayVo.getAppid ()); // minute car prices - micro letter assigned public account ID (ie Enterprise corpid do this appId) parameters.put ( "mch_id", weixinpayVo. getMchid ()); // points cheqi - business micro channel number parameters.put ( "nonce_str", noncestr); // random string parameters.put ( "body", weixinpayVo.getSubject ()); // pay content parameters.put ( "out_trade_no", weixinpayVo.getOutTradeNo ()); // merchant Order number parameters.put ( "total_fee", change2Fen (weixinpayVo.getTotalAmount ())); // amount paid, in minutes parameters.put ( "spbill_create_ip", weixinpayVo.getSpbillCreateIp ()) ;// end IP parameters.put ( "notify_url", weixinpayVo.getNotifyUrl ()); // asynchronous request address parameters.put ( "trade_type", "APP"); // type of transaction App pay String sign = creatingSign (weixinpayVo.getPartnerKey () , the parameters); // minute car prices - parameters.put ( "Sign" , Sign); // value into a unified interface calls returned in XML format log.info ( "micro-channel payment request parameters:" + parameters.toString () ); String xmlString to = sendPost (GATEURL, parameters); the Map <String, String> Map = doXMLParse (xmlString to); log.info ( "micro-channel payment request parameters:" + (Map == null ? null:map.toString())); Prepayid String = as map.get ( "prepay_id"); // Get prepayId the JSONObject jsonObject = new new the JSONObject (); jsonObject.put ( "prepayid" , prepayid); jsonObject.put ( "noncestr" , noncestr); return jsonObject; } / ** * the POST request, Map mode data * @param URL request address * @param param request data * @param charset encoding * / public static String sendPost (String URL, Map <Object, Object> param) { StringBuffer buffer = new StringBuffer(); buffer.append("<xml>"); if (param != null && !param.isEmpty()) { for (Map.Entry<Object, Object> entry : param.entrySet()) { if(entry.getKey().equals("attach") || entry.getKey().equals("body") || entry.getKey().equals("sign")){ buffer.append("<"+entry.getKey()+">"); buffer.append("<![CDATA["+entry.getValue()+"]]>"); buffer.append("</"+entry.getKey()+">"); }else{ buffer.append("<"+entry.getKey()+">"); buffer.append(entry.getValue()); buffer.append("</"+entry.getKey()+">"); } } } buffer.append("</xml>"); PrintWriter out = null; BufferedReader in = null; String result = ""; try { URL realUrl = newThe URL (URL); // open a connection and the URL the URLConnection Conn = realUrl.openConnection (); // set the common request attribute conn.setRequestProperty ( "Accept", "* / *" ); conn.setRequestProperty ( " Connection "," the Keep-Alive " ); conn.setRequestProperty ( " User-Agent "," the Mozilla / 4.0 (compatible; MSIE 6.0; the Windows NT 5.1; SVl) " ); // send a POST request must set the following two lines conn .setDoOutput ( to true ); conn.setDoInput ( to true ); // Get URLConnection object corresponding to the output stream out =new new the PrintWriter (conn.getOutputStream ()); // send a request parameter Out.print (Buffer); // the flush buffered output stream out.flush (); // define BufferedReader input stream to read the URL of the response in = new new the BufferedReader ( new new the InputStreamReader (conn.getInputStream (), "UTF-. 8" )); String Line; the while (! (= in.readLine Line ()) = null ) { Result + = Line; } } the catch (Exception E) { e.printStackTrace (); } // Use finally block to close the output stream, the input stream finally { the try { IF (OUT =! Null ) { the out.close (); } IF (in =! Null ) { in.close (); } } the catch (IOException EX) { ex.printStackTrace (); } } return Result; } / ** * generates signature * @param partnerkey * @param characterEncoding * @param parameters * @return https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=4_3 */ public static String creatingSign(String PartnerKey, SortedMap<Object, Object> parameters) { StringBuffer sb = new StringBuffer(); Iterator it = parameters.entrySet().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=" + PartnerKey); return MD5Util.MD5Encode(sb.toString(), "UTF-8").toUpperCase(); } /** * 金额元-> 分 * @param money * @return */ public static int change2Fen(String money){ if(null==money){ return 0; } Return new new the BigDecimal (Money) .multiply ( new new the BigDecimal (100 )) intValue ();. } / ** * <P> (converted into units of the elements (except 100)) </ P> * / / ** the amount of minute format * / public static Final String CURRENCY_FEN_REGEX = "\\ - [0-9] +?" ; public static String change2Yuan (String aMOUNT) throws Exception { return String.valueOf ( new new the BigDecimal (aMOUNT). Divide ( new new the BigDecimal (100 ))); } / ** * <P> (the 32-bit random string, anti-replay) </ P> * / public static String getNonceStr() { Random random = new Random(); return MD5Util.MD5Encode(String.valueOf(random.nextInt(10000)), "UTF-8"); } /** * 获取时间戳 * @return */ public static String getTimeStamp() { return String.valueOf(System.currentTimeMillis() / 1000); } /** * 获取ip地址 * @param request * @return */ public static String getIpAddr(HttpServletRequest request) { String ip = request.getHeader("x-forwarded-for"); if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } return ip; } / ** * String XML parsing stream object type the InputStream * parsed xml, returned to the first stage element pairs. If the first stage element has a child node, the value of this node is a child node xml data. * @Param strXML * @return * @throws JDOMException * @throws IOException * / public static the Map <String, String> doXMLParse (String strXML) { IF ( null == strXML || "" .equals (strXML)) { return null ; } the Map <String, String> Map = new new the HashMap <String, String> (); InputStream in =null; try{ in = new ByteArrayInputStream(strxml.getBytes("UTF-8")); SAXBuilder builder = new SAXBuilder(); builder.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); builder.setFeature("http://xml.org/sax/features/external-general-entities", false); builder.setFeature("http://xml.org/sax/features/external-parameter-entities", false); builder.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); Document doc = builder.build(in); Element root = doc.getRootElement(); List list = root.getChildren(); Iterator it = list.iterator(); while(it.hasNext()) { Element e = (Element) it.next(); String k = e.getName(); String v = ""; List children = e.getChildren(); if(children.isEmpty()) { v = e.getTextNormalize(); } else { v = getChildrenText(children); } map.put(k, v); } }catch (Exception e){ e.printStackTrace(); }finally { if(in!=null){ //关闭流 IOUtils.closeQuietly(in); } } return map; } /** * 获取子结点的xml * @param children * @return String */ private static String getChildrenText(List children) { StringBuffer sb = new StringBuffer(); if(!children.isEmpty()) { Iterator it = children.iterator(); while(it.hasNext()) { Element e = (Element) it.next(); String name = e.getName(); String value = e.getTextNormalize(); List list = e.getChildren(); sb.append("<" + name + ">"); if(!list.isEmpty()) { sb.append(getChildrenText(list)); } sb.append(value); sb.append("</" + name + ">"); } } return sb.toString(); } public static String setResultXML(String return_code, String return_msg) { return "<xml><return_code><![CDATA[" + return_code + "]]></return_code><return_msg><![CDATA[" + return_msg + "]]></return_msg></xml>"; } }
4. The micro-channel payment process, obtaining single unified prepayid, then assembled Mobile Originated request parameters return payment.
- Note that, noncestr random string parameter is the same in the two request
- Micro-letter signature parameters partnerkey, key settings Path: micro-channel merchant platform (pay.weixin.qq.com) -> Account Settings -> API Security -> Key Settings
- The amount is based on micro-channel sub- units