因为公司要求需要写支付宝支付与微信支付现在写完了,总结一下:
支付宝支付:
支付宝支付比较简单首先我说一下支付宝支付与微信支付大概的流程,就拿支付宝支付来说(微信同理)
首先去蚂蚁金服注册一下App 具体流程官方有,看下官方给的帮助就可以,支付宝支付首先是java服务器端生成预订单然后发送给蚂蚁服务器,稍后蚂蚁服务器会返回给你预处理信息,也就是说你生成订单之后请求蚂蚁服务器,有蚂蚁服务器把订单信息加签名之后返回给你,然后你拿着蚂蚁给你加签之后的订单信息直接给APP那边就可以(这里蚂蚁服务器返回的数据是不需要处理的可直接发给APP)然后APP接收到这个信息时会调起支付界面,支付成功之后,就会收到服务器返回给你的信息,支付成功或者失败,这时支付宝会返回结果,也就是异步通知,关于异步通知这里会返回两个,一个是返回给java服务器,一个是返回给APP,感觉返回APP的结果并不是很重要,无论是APP还是java服务器收到结果一定要给支付宝服务器返回结果,不然支付宝会给你发送好多次,发送几次记不清了,官方有说的很详细。这就是支付宝支付的整个流程。
下面是支付宝支付的代码:
支付宝有现成的sdk只要在你的java项目中使用了SDK相信这个支付是非常简单
//括号括起来的部分就是你自己在蚂蚁上边申请的一些配置
AlipayClient alipayClient = new DefaultAlipayClient(ZhifubaoConfig.URL, ZhifubaoConfig.App_id, ZhifubaoConfig.RSA_PRIVATE_KEY, "json", ZhifubaoConfig.input_charset, ZhifubaoConfig.ALIPAY_PUBLIC_KEY, ZhifubaoConfig.SIGNTYPE); AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest (); AlipayTradeAppPayModel model = new AlipayTradeAppPayModel(); model.setSubject("缴费订单"); model.setOutTradeNo(orderNo); model.setProductCode("QUICK_MSECURITY_PAY"); model.setTotalAmount(totalPrice.toString()); model.setBody(accountNumber); model.setPassbackParams(coinNum.toString()); request.setNotifyUrl(ZhifubaoConfig.Notify_url); request.setBizModel(model); String orderStr = ""; try { //这里和普通的接口调用不同,使用的是sdkExecute AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request); orderStr = response.getBody(); System.out.println(orderStr);//就是orderString 可以直接给客户端请求,无需再做处理。 } catch (AlipayApiException e) { e.printStackTrace(); } return orderStr; }
这个就是支付宝提供的sdk使用起来很方便,因为人家都给你写好了拿来直接使用就可以,以上代码是由java
服务器产生订单然后发给支付宝服务器由服务器帮你创建待支付订单,也就是上边说的订单加签直接返回给APP就能让APP唤醒支付宝支付。
关于微信及支付:微信支付我在微信支付官网找了半天也没找带微信提供的sdk(可能是因为知己笨吧)
微信生成预处理订单代码:
public static SortedMap
Unifiedorder.java代码:
** * 统一下单提交为微信的参数 */ public class Unifiedorder { private String appid;//微信分配的公众账号ID(企业号corpid即为此appId),例如:wxd678efh567hg6787 private String mch_id;//商户id private String nonce_str;//随机字符串:数字+大写字母的组合,32位 private String sign;//签名 private String body;//商品或支付单简要描述 private String out_trade_no;//商户系统内部的订单号 private int total_fee;//总金额 private String spbill_create_ip;//APP和网页支付提交[用户端ip],Native支付填调用微信支付API的机器IP。 private String notify_url;//接收微信支付异步通知回调地址 private String trade_type;//交易类型:JSAPI,NATIVE,APP private String device_info;//设备号 private Integer attach;//附加数据 public String getDevice_info() { return device_info; } public void setDevice_info(String device_info) { this.device_info = device_info; } public Integer getAttach() { return attach; } public void setAttach(Integer attach) { this.attach = attach; } public String getAppid() { return appid; } public String getMch_id() { return mch_id; } public String getNonce_str() { return nonce_str; } public String getSign() { return sign; } public String getBody() { return body; } public String getOut_trade_no() { return out_trade_no; } public int getTotal_fee() { return total_fee; } public String getSpbill_create_ip() { return spbill_create_ip; } public String getNotify_url() { return notify_url; } public String getTrade_type() { return trade_type; } public void setAppid(String appid) { this.appid = appid; } public void setMch_id(String mch_id) { this.mch_id = mch_id; } public void setNonce_str(String nonce_str) { this.nonce_str = nonce_str; } public void setSign(String sign) { this.sign = sign; } public void setBody(String body) { this.body = body; } public void setOut_trade_no(String out_trade_no) { this.out_trade_no = out_trade_no; } public void setTotal_fee(int total_fee) { this.total_fee = total_fee; } public void setSpbill_create_ip(String spbill_create_ip) { this.spbill_create_ip = spbill_create_ip; } public void setNotify_url(String notify_url) { this.notify_url = notify_url; } public void setTrade_type(String trade_type) { this.trade_type = trade_type; } public Unifiedorder(String appid, String mchId, String nonceStr, String sign, String body, String outTradeNo, int totalFee, String spbillCreateIp, String notifyUrl, String tradeType,String accountNumber,Integer coinNum ) { super(); this.appid = appid; mch_id = mchId; nonce_str = nonceStr; this.sign = sign; this.body = body; out_trade_no = outTradeNo; total_fee = totalFee; spbill_create_ip = spbillCreateIp; notify_url = notifyUrl; trade_type = tradeType; device_info=accountNumber; this.attach=coinNum; } }
HttpXmlUtil.java
import javax.net.ssl.HttpsURLConnection; import java.io.*; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; /** * post提交xml格式的参数 */ public class HttpXmlUtil { /** * 开始post提交参数到接口 * 并接受返回 * @param url * @param xml * @param method * @param contentType * @return */ public static String xmlHttpProxy(String url,String xml,String method,String contentType){ InputStream is = null; OutputStreamWriter os = null; try { URL _url = new URL(url); HttpURLConnection conn = (HttpURLConnection) _url.openConnection(); conn.setDoInput(true); conn.setDoOutput(true); conn.setRequestProperty("Content-type", "text/xml"); conn.setRequestProperty("Pragma:", "no-cache"); conn.setRequestProperty("Cache-Control", "no-cache"); conn.setRequestMethod("POST"); os = new OutputStreamWriter(conn.getOutputStream()); os.write(new String(xml.getBytes(contentType))); os.flush(); //返回值 is = conn.getInputStream(); return getContent(is, "utf-8"); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally{ try { if(os!=null){os.close();} if(is!=null){is.close();} } catch (IOException e) { e.printStackTrace(); } } return null; } /** * 解析返回的值 * @param is * @param charset * @return */ public static String getContent(InputStream is, String charset) { String pageString = null; InputStreamReader isr = null; BufferedReader br = null; StringBuffer sb = null; try { isr = new InputStreamReader(is, charset); br = new BufferedReader(isr); sb = new StringBuffer(); String line = null; while ((line = br.readLine()) != null) { sb.append(line + "\n"); } pageString = sb.toString(); } catch (Exception e) { e.printStackTrace(); } finally { try { if (is != null){ is.close(); } if(isr!=null){ isr.close(); } if(br!=null){ br.close(); } } catch (IOException e) { e.printStackTrace(); } sb = null; } return pageString; } /** * 构造xml参数 * @return */ public static String xmlInfo(Unifiedorder unifiedorder){ //构造xml参数的时候,至少有10个必传参数 /* *wx2421b1c4370ec43b APP支付测试10000100 1add1a30ac87aa2db72f57a2375d8fec http://wxpay.weixin.qq.com/pub_v2/pay/notify.v2.php 1415659990 14.23.150.211 1 APP 0CB01533B8C1EF103065174F50BCA001 */ if(unifiedorder!=null){ StringBuffer bf = new StringBuffer(); bf.append("" ); bf.append("" ); bf.append(unifiedorder.getAppid()); bf.append(""); bf.append("" ); bf.append(unifiedorder.getAttach()); bf.append(""); bf.append(""); bf.append(unifiedorder.getBody()); bf.append(""); bf.append("" ); bf.append(unifiedorder.getDevice_info()); bf.append(""); bf.append("" ); bf.append(unifiedorder.getMch_id()); bf.append(""); bf.append("" ); bf.append(unifiedorder.getOut_trade_no()); bf.append(""); bf.append("" ); bf.append(unifiedorder.getNonce_str()); bf.append(""); bf.append("" ); bf.append(unifiedorder.getNotify_url()); bf.append(""); bf.append("" ); bf.append(unifiedorder.getSign()); bf.append(""); bf.append("" ); bf.append(unifiedorder.getSpbill_create_ip()); bf.append(""); bf.append("" ); bf.append(unifiedorder.getTotal_fee()); bf.append(""); bf.append("" ); bf.append(unifiedorder.getTrade_type()); bf.append(""); bf.append(""); /* bf.append("bf.append(unifiedorder.getTime_start()); bf.append("]]>"); bf.append(" bf.append(unifiedorder.getTime_expire()); bf.append("]]>"); bf.append(" bf.append(unifiedorder.getDetail()); bf.append("]]>"); bf.append(" bf.append(unifiedorder.getAttach()); bf.append("]]>"); */ return bf.toString(); } return ""; } /** * post请求并得到返回结果 * @param requestUrl * @param requestMethod * @param output * @return */ public static String httpsRequest(String requestUrl, String requestMethod, String output) { try{ URL url = new URL(requestUrl); //打开到此 URL 的连接并返回一个用于从该连接读入的 InputStream HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); //如果打算使用 URL 连接进行输出,则将 DoOutput 标志设置为 true connection.setDoOutput(true); //打算使用 URL 连接进行输入,则将 DoInput 标志设置为 true connection.setDoInput(true); /* * 有些协议用于文档缓存。有时候能够进行“直通”并忽略缓存尤其重要, * 例如浏览器中的“重新加载”按钮。如果连接中的 UseCaches 标志为 true, * 则允许连接使用任何可用的缓存。如果为 false,则忽略缓存。 * 默认值来自 DefaultUseCaches,它默认为 true。 */ connection.setUseCaches(false); //设置 URL 请求的方法, connection.setRequestMethod(requestMethod); if (null != output) { OutputStream outputStream = connection.getOutputStream(); outputStream.write(output.getBytes("UTF-8")); outputStream.close(); } // 从输入流读取返回内容 InputStream inputStream = connection.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8"); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String str = null; StringBuffer buffer = new StringBuffer(); while ((str = bufferedReader.readLine()) != null) { buffer.append(str); } bufferedReader.close(); inputStreamReader.close(); inputStream.close(); inputStream = null; //指示近期服务器不太可能有其他请求。调用 disconnect() 并不意味着可以对其他请求重用此 HttpURLConnection 实例。 connection.disconnect(); return buffer.toString(); }catch(Exception ex){ ex.printStackTrace(); } return ""; } /** * 回调后将结果返回给微信 * @param return_code * @param return_msg * @return */ public static String backWeixin(String return_code,String return_msg){ try{ StringBuffer bf = new StringBuffer(); bf.append(" " ); bf.append("); bf.append(return_code); bf.append("]]>"); bf.append(" ); bf.append(return_msg); bf.append("]]>"); bf.append(""); return bf.toString(); }catch(Exception ex){ ex.printStackTrace(); } return ""; } }
ParseXMLUtils.java
import java.io.StringReader; import java.util.Iterator; import java.util.List; import cn.jiguang.common.utils.StringUtils; import org.apache.log4j.Logger; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.io.SAXReader; import org.jdom.input.SAXBuilder; import org.xml.sax.InputSource; public class ParseXMLUtils { private static Logger log = Logger.getLogger(ParseXMLUtils.class); /** * 1、DOM解析 */ public static void beginXMLParse(String xml){ Document doc = null; try { doc = DocumentHelper.parseText(xml); // 将字符串转为XML Element rootElt = doc.getRootElement(); // 获取根节点smsReport System.out.println("根节点是:"+rootElt.getName()); Iterator iters = rootElt.elementIterator("sendResp"); // 获取根节点下的子节点sms while (iters.hasNext()) { Element recordEle1 = (Element) iters.next(); Iterator iter = recordEle1.elementIterator("sms"); while (iter.hasNext()) { Element recordEle = (Element) iter.next(); String phone = recordEle.elementTextTrim("phone"); // 拿到sms节点下的子节点stat值 String smsID = recordEle.elementTextTrim("smsID"); // 拿到sms节点下的子节点stat值 System.out.println(phone+":"+smsID); } } } catch (DocumentException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } /** * 2、DOM4j解析XML(支持xpath) * 解析的时候自动去掉CDMA * @param xml */ public static void xpathParseXml(String xml){ try { StringReader read = new StringReader(xml); SAXReader saxReader = new SAXReader(); Document doc = saxReader.read(read); String xpath ="/xml/appid"; System.out.print(doc.selectSingleNode(xpath).getText()); } catch (DocumentException e) { e.printStackTrace(); } } /** * 3、JDOM解析XML * 解析的时候自动去掉CDMA * @param xml */ public static UnifiedorderResult jdomParseXml(String xml){ UnifiedorderResult unifieorderResult = new UnifiedorderResult(); try { StringReader read = new StringReader(xml); // 创建新的输入源SAX 解析器将使用 InputSource 对象来确定如何读取 XML 输入 InputSource source = new InputSource(read); // 创建一个新的SAXBuilder SAXBuilder sb = new SAXBuilder(); // 通过输入源构造一个Document org.jdom.Document doc; doc = (org.jdom.Document) sb.build(source); org.jdom.Element root = doc.getRootElement();// 指向根节点 Listlist = root.getChildren(); if(list != null && list.size() > 0){ boolean flag1 = true; boolean flag2 = true; for (org.jdom.Element element : list) { log.info("key是:"+element.getName()+",值是:"+element.getText()); if("return_code".equals(element.getName())){ if("FAIL".equals(element.getText())){ flag1 = false; }else{ unifieorderResult.setReturn_code(element.getText()); } } if("return_msg".equals(element.getName())){ if(element.getText() != null && !"OK".equals(element.getText())){//微信支付的第一个坑,这里返回了OK,23333 log.error("统一下单参数有误,错误原因为:"+element.getText()); return null; } } if(flag1){ if("appid".equals(element.getName())){ unifieorderResult.setAppid(element.getText()); } if("mch_id".equals(element.getName())){ unifieorderResult.setMch_id(element.getText()); } if("nonce_str".equals(element.getName())){ unifieorderResult.setNonce_str(element.getText()); } if("sign".equals(element.getName())){ unifieorderResult.setSign(element.getText()); } if("err_code".equals(element.getName())){ unifieorderResult.setErr_code(element.getText()); } if("err_code_des".equals(element.getName())){ unifieorderResult.setErr_code_des(element.getText()); } if("result_code".equals(element.getName())){ if("FAIL".equals(element.getText())){ flag2 = false; log.error("统一下单业务结果有误,无法返回预支付交易会话标识"); }else{ unifieorderResult.setResult_code(element.getText()); } } } if(flag1 && flag2 && flag2 == true){ if("trade_type".equals(element.getName())){ unifieorderResult.setTrade_type(element.getText()); } if("prepay_id".equals(element.getName())){ log.info("统一下单接口成功返回预支付交易会话标识!"); unifieorderResult.setPrepay_id(element.getText()); } } } return unifieorderResult; }else{ return null; } } catch (Exception e) { e.printStackTrace(); return null; } } public static boolean parseInt(String key){ if(!StringUtils.isEmpty(key)){ if(key.equals("total_fee")||key.equals("cash_fee")||key.equals("coupon_fee")||key.equals("coupon_count")||key.equals("coupon_fee_0")){ return true; } } return false; } }
上边的微信生成预订单处理有点多,我简单的总结一下什么意思,总体就是说把所有的请求参数都封装成一个实体类,然后通过dom4j转换成微信需要格式的XML然后通过http发送给微信服务器端就可以了。
以上就是微信与支付宝支付生成预订单处理信息的代码,有些乱。
最后说一下异步回调异步回调处理的不是很好,凑合能用可以再严谨一些
首先支付宝:
@RequestMapping(value = "/ZFBmobilePayNotify") public void alipayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception { logf.debug("进入支付宝回调函数"); // 获取支付宝POST过来反馈信息 Mapparams = new HashMap (); Map requestParams = request.getParameterMap(); for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) { String name = 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); } // 买家付款账号 String buyer_logon_id = params.get("buyer_logon_id"); BigDecimal total_amount = new BigDecimal(params.get("total_amount")); // 商户订单号 String out_trade_no = params.get("out_trade_no"); // 支付宝交易号 String trade_no = params.get("trade_no"); // 交易状态 String trade_status = params.get("trade_status"); //商户编号 String stord_id = params.get("body"); //充值硬币 Integer coin_num = Integer.parseInt(params.get("passback_params")); String extraParam = ""; int offset = out_trade_no.indexOf("_"); if (offset > -1) { extraParam = out_trade_no.substring(offset + 1); out_trade_no = out_trade_no.substring(0, offset); } boolean signVerified = AlipaySignature.rsaCheckV1(params, ZhifubaoConfig.ALIPAY_PUBLIC_KEY, ZhifubaoConfig.CHARSET, ZhifubaoConfig.SIGNTYPE); //调用SDK验证签名 if (signVerified) { if (trade_status.equals("TRADE_FINISHED") || trade_status.equals("TRADE_SUCCESS")) { Boolean falg = true; BigDecimal b2 = new BigDecimal(Double.toString(100)); total_amount=total_amount.multiply(b2); falg = accountCoinService.addPayMoney(stord_id, coin_num, total_amount, "1"); if (falg == false) { logf.debug("APIConsumeController--------------暂无商户记录"); } else { logf.debug("APIConsumeController--------------充值成功"); } } else { logf.debug("alipayNotify验证失败——商户订单号:" + out_trade_no + ";支付宝交易号:" + trade_no + ",交易状态:" + trade_status); response.getWriter().write("failure"); } response.getWriter().write("success"); } else { response.getWriter().write("failure"); logf.debug("logError================================支付宝解签失败"); } }
下面是微信异步回调:
/** * 微信回调函数 * * @param request * @param response * @return */ @RequestMapping(value = "/WXmobilePayNotify") public void WXalipayNotify(HttpServletRequest request, HttpServletResponse response) { SortedMapparameters = null; try { parameters = PayOrder.checkWxPayParam(request); } catch (Exception e) { logf.error("验证微信异步回调出错,错误为:" + e.getMessage()); } if (parameters != null) { try { response.getWriter().write(HttpXmlUtil.backWeixin("SUCCESS", "OK"));//没有分销 }catch (Exception e){ logf.error("====================== notify url error",e); } Boolean falg = true; falg = accountCoinService.addPayMoney(parameters.get("device_info").toString(), Integer.parseInt(parameters.get("attach").toString()), new BigDecimal(parameters.get("total_fee").toString()), "0"); if (falg) { logf.info("充值成功!"); } else { logf.info("充值失败!"); } } else { logf.info("微信回调验证失败。可能不是微信发来的通知。"); } }
最后说一下异步回调:这个异步回调是你在蚂蚁服务器那边配置的一个地址,这个地址外网必须能访问到,不然不会接收到异步回调通知,不能用 localhost:8080/xxx/xxx