一、业务需求

  实现app微信支付,后端需要做生成预支付单,响应支付结果

二、业务流程

  查看官方文档

  https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_3

三、实现方法

  3.1 创建微信工具类  ConstantUtil

  

public class ConstantUtil {/*** 微信开发平台应用ID*/public static final String APP_ID="wx2421b1c4370ec43b";/*** 应用对应的凭证*/public static final String APP_SECRET="1add1a30ac87aa2db72f57a2375d8fec";/*** 应用对应的密钥*/public static final String APP_KEY="1add1a30ac87aa2db72f57a2375d8fec";/*** 微信支付商户号*/public static final String MCH_ID="10000100";/*** 商品描述*/public static final String BODY="充值";/*** 商户号对应的密钥*/public static final String PARTNER_key="*******"; /*** 商户id*/public static final String PARTNER_ID="*******"; /*** 常量固定值*/public static final String GRANT_TYPE="client_credential";/*** 获取预支付id的接口url*/public static String GATEURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";/*** 微信服务器回调通知url*/public static String NOTIFY_URL="http://url"; //可以访问的url/*** 微信服务器查询订单url*/public static String ORDER_QUERY="https://api.mch.weixin.qq.com/pay/orderquery";}

  3.2 生成预支付订单

  

 Map<String, Object> getOrder(@RequestParam(value = "totalFee") String totalFee, @RequestParam(value = "deviceInfo") String deviceInfo,@RequestParam(value = "attach") String attach,HttpServletRequest request, HttpServletResponse response)throws Exception {Map<String, Object> map = new HashMap<String, Object>();// 获取生成预支付订单的请求类PrepayIdRequestHandler prepayReqHandler = new PrepayIdRequestHandler(request, response);
//        String totalFee = request.getParameter("total_fee");int total_fee = (int) (Float.valueOf(totalFee) * 100);System.out.println("total:" + total_fee);System.out.println("total_fee:" + total_fee);prepayReqHandler.setParameter("appid", ConstantUtil.APP_ID);prepayReqHandler.setParameter("body", ConstantUtil.BODY);prepayReqHandler.setParameter("mch_id", ConstantUtil.MCH_ID);prepayReqHandler.setParameter("device_info", deviceInfo); //卡号prepayReqHandler.setParameter("attach", attach);//套餐值String nonce_str = WXUtil.getNonceStr();prepayReqHandler.setParameter("nonce_str", nonce_str);prepayReqHandler.setParameter("notify_url", ConstantUtil.NOTIFY_URL);out_trade_no = String.valueOf(UUID.next());prepayReqHandler.setParameter("out_trade_no", out_trade_no);prepayReqHandler.setParameter("spbill_create_ip", request.getRemoteAddr());String timestamp = WXUtil.getTimeStamp();prepayReqHandler.setParameter("time_start", timestamp);System.out.println(String.valueOf(total_fee));prepayReqHandler.setParameter("total_fee", String.valueOf(total_fee));prepayReqHandler.setParameter("trade_type", "APP");/*** 注意签名(sign)的生成方式,具体见官方文档(传参都要参与生成签名,且参数名按照字典序排序,最后接上APP_KEY,转化成大写)*/prepayReqHandler.setParameter("sign", prepayReqHandler.createMD5Sign());prepayReqHandler.setGateUrl(ConstantUtil.GATEURL);String prepayid = prepayReqHandler.sendPrepay();// 若获取prepayid成功,将相关信息返回客户端if (prepayid != null && !prepayid.equals("")) {String signs = "appid=" + ConstantUtil.APP_ID + "&noncestr=" + nonce_str + "&package=Sign=WXPay&partnerid="+ ConstantUtil.PARTNER_ID + "&prepayid=" + prepayid + "&timestamp=" + timestamp + "&key="+ ConstantUtil.APP_KEY;map.put("code", 0);map.put("info", "success");map.put("prepayid", prepayid);/*** 签名方式与上面类似*/map.put("sign", MD5Util.MD5Encode(signs, "utf8").toUpperCase());map.put("appid", ConstantUtil.APP_ID);map.put("device_info", deviceInfo);map.put("attach", attach);map.put("timestamp", timestamp);  //等于请求prepayId时的time_startmap.put("noncestr", nonce_str);   //与请求prepayId时值一致map.put("package", "Sign=WXPay");  //固定常量map.put("partnerid", ConstantUtil.PARTNER_ID);} else {map.put("code", 1);map.put("info", "获取prepayid失败");}return map;}

  3.3  异步通知客户结果

  

      PrintWriter writer = response.getWriter();InputStream inStream = request.getInputStream();ByteArrayOutputStream outSteam = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int len = 0;while ((len = inStream.read(buffer)) != -1) {outSteam.write(buffer, 0, len);}outSteam.close();inStream.close();String result = new String(outSteam.toByteArray(), "utf-8");System.out.println("微信支付通知结果:" + result);Map<String, String> map = null;try {/*** 解析微信通知返回的信息*/map = XMLUtil.doXMLParse(result);} catch (JDOMException e) {// TODO Auto-generated catch block
            e.printStackTrace();}

   官方文档中特别提醒:商户系统对于支付结果通知的内容一定要做签名验证,并校验返回的订单金额是否与商户侧的订单金额一致,防止数据泄漏导致出现“假通知”,造成资金损失

   支付结果通知内容做签名验证

    

   
//支付成功后sign校验String appid=map.get("appid");String transaction_id=map.get("transaction_id");String nonce_str =map.get("nonce_str");String bank_type =map.get("bank_type");String openid=map.get("openid");String sign =map.get("sign");String fee_type =map.get("fee_type");String mch_id =map.get("mch_id");String cash_fee =map.get("cash_fee");String device_info =map.get("device_info");String out_trade_no =map.get("out_trade_no");String total_fee =map.get("total_fee");String trade_type =map.get("trade_type");String result_code =map.get("result_code");String attach =map.get("attach");String time_end =map.get("time_end");String is_subscribe =map.get("is_subscribe");String return_code=map.get("return_code");

PrepayIdRequestHandler prepayReqHandler = new PrepayIdRequestHandler(request, response);prepayReqHandler.setParameter("appid",appid);prepayReqHandler.setParameter("attach",attach);prepayReqHandler.setParameter("bank_type",bank_type);prepayReqHandler.setParameter("cash_fee",cash_fee);prepayReqHandler.setParameter("device_info",device_info);prepayReqHandler.setParameter("fee_type",fee_type);prepayReqHandler.setParameter("is_subscribe",is_subscribe);prepayReqHandler.setParameter("mch_id",mch_id);prepayReqHandler.setParameter("nonce_str",nonce_str);prepayReqHandler.setParameter("openid",openid);prepayReqHandler.setParameter("out_trade_no",out_trade_no);prepayReqHandler.setParameter("result_code",result_code);prepayReqHandler.setParameter("return_code",return_code);prepayReqHandler.setParameter("time_end",time_end);prepayReqHandler.setParameter("total_fee",total_fee);prepayReqHandler.setParameter("trade_type",trade_type);prepayReqHandler.setParameter("transaction_id",transaction_id);

String endSigns =prepayReqHandler.createMD5Sign(); //支付结果通知的内容 签名校验

   商户金额的查询

  

     PrepayIdRequestHandler orderQueryHandler = new PrepayIdRequestHandler(request, response);orderQueryHandler.setParameter("appid",appid);orderQueryHandler.setParameter("mch_id",mch_id);orderQueryHandler.setParameter("out_trade_no",out_trade_no);orderQueryHandler.setParameter("nonce_str",nonce_str);orderQueryHandler.setParameter("sign",orderQueryHandler.createMD5Sign());orderQueryHandler.setGateUrl(ConstantUtil.ORDER_QUERY);String resXml = "";WeixinOrderBean orderBean =orderQueryHandler.selectOrder();

  应答微信 

if(sign.equals(endSigns) && Integer.parseInt(total_fee)==orderBean.getTotal_fee()){ // 签名通过并且返回的订单的金额与商户金额相同// 若支付成功,则告知微信服务器收到通知if (map.get("return_code").equals("SUCCESS")) {System.out.println("充值成功!");//PayRecord payRecord=payRecordService.get(Long.valueOf(map.get("out_trade_no")));System.out.println("订单号:" + Long.valueOf(map.get("out_trade_no")));String iccids = map.get("device_info");String monthNum = map.get("attach");          //根据自己的业务处理int count =trafficCardListService.selectExistTrafficCardByOutTradeNo(map.get("out_trade_no")); //查询商户订单号是否存在if(count==0){//不存在就插入List<MsisdnOrderBean> msisdnOrderList = trafficCardListService.selectTrafficCardRechargeResult(iccids, monthNum);if (msisdnOrderList.size() > 0) {for (MsisdnOrderBean msisdnOrderBean : msisdnOrderList) {msisdnOrderBean.setOutTradeNo(map.get("out_trade_no"));msisdnOrderBean.setDate(map.get("time_end"));msisdnOrderBean.setIccids(map.get("device_info"));// msisdnOrderBean.setTotalFee(Integer.parseInt(map.get("total_fee")));msisdnOrderBean.setTotalFee(BigDecimal.valueOf(Integer.parseInt(map.get("total_fee"))).divide(new BigDecimal(100)).doubleValue());msisdnOrderBean.setTransactionId(map.get("transaction_id"));msisdnOrderBean.setTrafficNo(DateUtils.getNowDataTime() + ApiUtils.getFourRandom()); //年月日时分秒+四位随机数
                            trafficCardListService.insertTrafficCardList(msisdnOrderBean);}}}resXml = XMLUtil.setXML("SUCCESS", "OK");} else {resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"+ "<return_msg><![CDATA[通知签名验证失败]]></return_msg>" + "</xml> ";logger.info("通知签名验证失败");}}else{resXml =XMLUtil.setXML("FAIL", "签名不一致");}writer.write(resXml);writer.flush();writer.close();

  运用到的 PrepayIdRequestHandler  工具类

public class PrepayIdRequestHandler extends RequestHandler {public PrepayIdRequestHandler(HttpServletRequest request,HttpServletResponse response) {super(request, response);}public String createMD5Sign() {StringBuffer sb = new StringBuffer();Set es = super.getAllParameters().entrySet();Iterator it = es.iterator();while (it.hasNext()) {Map.Entry entry = (Map.Entry) it.next();String k = (String) entry.getKey();String v = (String) entry.getValue();sb.append(k + "=" + v + "&");}String params=sb.append("key="+ConstantUtil.APP_KEY).substring(0);String sign = MD5Util.MD5Encode(params, "utf8");return sign.toUpperCase();}// 提交预支付public String sendPrepay() throws Exception {String prepayid = "";Set es=super.getAllParameters().entrySet();Iterator it=es.iterator();StringBuffer sb = new StringBuffer("<xml>");while(it.hasNext()){Map.Entry entry = (Map.Entry) it.next();String k = (String) entry.getKey();String v = (String) entry.getValue();sb.append("<"+k+">"+v+"</"+k+">");}sb.append("</xml>");String params=sb.substring(0);System.out.println("请求参数:"+params);String requestUrl = super.getGateUrl();System.out.println("请求url:"+requestUrl);TenpayHttpClient httpClient = new TenpayHttpClient();httpClient.setReqContent(requestUrl);String resContent = "";if (httpClient.callHttpPost(requestUrl, params)) {resContent = httpClient.getResContent();System.out.println("获取prepayid的返回值:"+resContent);Map<String,String> map=XMLUtil.doXMLParse(resContent);if(map.containsKey("prepay_id"))prepayid=map.get("prepay_id");}return prepayid;}// 查询订单public WeixinOrderBean selectOrder() throws Exception {Set es=super.getAllParameters().entrySet();Iterator it=es.iterator();StringBuffer sb = new StringBuffer("<xml>");while(it.hasNext()){Map.Entry entry = (Map.Entry) it.next();String k = (String) entry.getKey();String v = (String) entry.getValue();sb.append("<"+k+">"+v+"</"+k+">");}sb.append("</xml>");String params=sb.substring(0);System.out.println("请求参数:"+params);String requestUrl = super.getGateUrl();System.out.println("请求url:"+requestUrl);TenpayHttpClient httpClient = new TenpayHttpClient();httpClient.setReqContent(requestUrl);String resContent = "";WeixinOrderBean orderBean =new WeixinOrderBean();if (httpClient.callHttpPost(requestUrl, params)) {resContent = httpClient.getResContent();Map<String,String> map=XMLUtil.doXMLParse(resContent);if(map.size()>0){orderBean.setAppid(map.get("appid"));orderBean.setAttach(map.get("attach"));orderBean.setDevice_info(map.get("device_info"));orderBean.setBank_type(map.get("bank_type"));orderBean.setMch_id(map.get("mch_id"));orderBean.setNonce_str(map.get("nonce_str"));orderBean.setTotal_fee(Integer.parseInt(map.get("total_fee")));orderBean.setTrade_state(map.get("trade_state"));}}return orderBean;}
}

转载于:https://www.cnblogs.com/jihaibo/p/9036423.html

java 微信支付实现相关推荐

  1. java微信支付代码_Java微信支付之服务号支付代码示例

    Java微信支付之服务号支付实现,网上的java微信支付sdk和Demo基本上是水的,看着头疼所以我决心自己开始写Java微信支付之公众号支付,多的不说见下面源码,为了方便使用我分别用了两个Servl ...

  2. java微信支付超时_Java微信支付之关闭订单

    本文实例为大家分享了java微信支付之关闭订单的具体代码,供大家参考,具体内容如下 一.应用场景 商户订单支付失败需要生成新单号重新发起支付,要对原订单号调用关单,避免重复支付 系统下单后,用户支付超 ...

  3. Java微信支付API文档测试

    Java微信支付API文档测试(注意用的微信开发文档是什么支付) 本人用的刷卡支付( 之前看错了,一直在看扫码支付,心塞 ),如图 首先,做一系列准备,获取appid等等,可以写在一个配置文件里面,如 ...

  4. java微信支付v3系列——6.微信支付查询订单API

    目录 java微信支付v3系列--1.微信支付准备工作 java微信支付v3系列--2.微信支付基本配置 java微信支付v3系列--3.订单创建准备操作 java微信支付v3系列--4.创建订单的封 ...

  5. java微信支付v3系列——1.微信支付准备工作

    目录 java微信支付v3系列--1.微信支付准备工作 java微信支付v3系列--2.微信支付基本配置 java微信支付v3系列--3.订单创建准备操作 java微信支付v3系列--4.创建订单的封 ...

  6. java微信支付v3系列——4.创建订单的封装及使用

    目录 java微信支付v3系列--1.微信支付准备工作 java微信支付v3系列--2.微信支付基本配置 java微信支付v3系列--3.订单创建准备操作 java微信支付v3系列--4.创建订单的封 ...

  7. java微信支付v3系列——7.微信支付之申请退款

    目录 java微信支付v3系列--1.微信支付准备工作 java微信支付v3系列--2.微信支付基本配置 java微信支付v3系列--3.订单创建准备操作 java微信支付v3系列--4.创建订单的封 ...

  8. java微信支付v3系列——8.微信支付之退款成功回调

    目录 java微信支付v3系列--1.微信支付准备工作 java微信支付v3系列--2.微信支付基本配置 java微信支付v3系列--3.订单创建准备操作 java微信支付v3系列--4.创建订单的封 ...

  9. java微信支付v3系列——5.微信支付成功回调

    目录 java微信支付v3系列--1.微信支付准备工作 java微信支付v3系列--2.微信支付基本配置 java微信支付v3系列--3.订单创建准备操作 java微信支付v3系列--4.创建订单的封 ...

  10. java微信支付v3系列——3.订单创建准备操作

    目录 java微信支付v3系列--1.微信支付准备工作 java微信支付v3系列--2.微信支付基本配置 java微信支付v3系列--3.订单创建准备操作 java微信支付v3系列--4.创建订单的封 ...

最新文章

  1. 人生必须知道的十个为什么
  2. mysql syncbinlog_Mysql之sync-binlog参数
  3. Python编程基础:第四十一节 继承Inheritance
  4. vue 子页面调用父页面的参数_Flutter子组件调用父组件方法修改父组件参数
  5. html中.inner样式,关于通过innerHTML插入样式的问题
  6. 高分四号(GF4)——预处理(辐射定标、大气校正、正射校正、图像配准)
  7. 定时器 Corn时间表达式
  8. 航信三大系统ICS DCS CRS
  9. mysql 如何避免间隙锁_mysql 间隙锁
  10. ORACLE 中利用推理逻辑去算 上年同期 ,注意:ORACLE中查询条件是带有推理逻辑功能的,及oracle中的推理逻辑
  11. 公司邮箱如何注册?免费公司邮箱域名如何注册?
  12. java类求圆的面积周长_java编程 1. 设计一个求圆的面积和周长的类,要求:1计算当半径r,JAVA编程题。编写一个应用程序计算圆的周长和面积,设圆的半...
  13. mysql安装教程_mysql 5.5 安装配置方法图文教程
  14. cefsharp执行完js代码后获取返回值问题
  15. JS基本类型与无法定义的属性
  16. 吕本富:中国互联网太乱 完全没有游戏规则
  17. 当下的个人站长都用哪些模板做网站呢?
  18. crowd counting
  19. html文件相对路径引用
  20. 【游】优秀游戏场景分析

热门文章

  1. change element 原始值_change-element
  2. Java 中的位移运算符
  3. Nginx+Tomcat windows环境下简单集群搭建
  4. oracle常见问题
  5. C/C++还能混合编程
  6. 【转载】solr教程,值得刚接触搜索开发人员一看
  7. 爬虫基于ADSL动态获取ip
  8. spark.mllib:bagging方法
  9. spark.mllib源码阅读:GradientBoostedTrees
  10. mac下natapp使用