小编在此说一声,建议去看一下微信官方提供的支付流程图,以及其他的之后再看下面的。小编在此就不提供账号申请,那些准备工作了,直接上代码。
流程总结:首先APP发送一个请求,想购买的商品。后台生成一个预支付订单,然后将APP支付所需要的信息返回给App支付即可。支付成功后,微信服务器回调你请求预支付订单告诉微信服务器的回调地址。收到回调后执行你的业务逻辑。并在最后一定要告诉微信服务器你已收到回调,不然微信会无限回调你。
以下有几个注意事项:
1、建议订单金额不在交互中直接暴露传输,防止篡改。
2、一般流程是在请求预支付的订单的时候在自己数据库中设计两张表,一张是支付订单表,一张是订单流水表。支付订单表设计一个状态,未支付,已支付。在预支付订单中可传输自己的订单号out_trade_no,通过这个标识。收到该订单的标识就将状态改成已支付,且在流水表中记录充值金额之类的信息。
3、在回调中需要订单是否已被处理过,再判断实际支付金额和订单金额是否匹配。防止实际支付金额被篡改。
4、微信的单位是分哦,所以记得处理一下。
好的现在我们就直接上代码:
controller
package com.irandoo.support.wxpay.action; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.text.ParseException; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jdom2.JDOMException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Controller; import com.alibaba.fastjson.JSON; import com.irandoo.app.interf.json.PrivateRoomJson; import com.irandoo.app.interf.service.PrivateRoomJsonService; import com.irandoo.support.wxpay.handler.PrepayIdRequestHandler; import com.irandoo.support.wxpay.model.RechargeOrder; import com.irandoo.support.wxpay.service.RechargeOrderService; import com.irandoo.support.wxpay.util.ConstantUtil; import com.irandoo.support.wxpay.util.MD5Util; import com.irandoo.support.wxpay.util.OrderUtil; import com.irandoo.support.wxpay.util.WXUtil; import com.irandoo.support.wxpay.util.XMLUtil; import com.irandoo.xhep.base.action.BaseAction; import com.irandoo.xhep.base.model.Meal; import com.irandoo.xhep.base.service.MealService; import com.irandoo.xhep.base.service.RechargeRecordService; import com.irandoo.xhep.base.service.UserAccountService; import com.irandoo.xhep.base.util.WawaConstantUtil; /** *<p>Title:WeiXinPayController </p> *<p>Description:</p> *<p>Company:</p> *@author sun *@date 2018年1月22日10:01:19 */ @Controller("wechatPayAction") @Scope("prototype") public class WechatPayAction extends BaseAction { /** * */ private static final long serialVersionUID = 4071603624936342541L; private Log logger = LogFactory.getLog(WechatPayAction.class); @Autowired MealService mealService; @Autowired RechargeOrderService rechargeOrderService; @Autowired UserAccountService userAccountService; @Autowired RechargeRecordService rechargeRecordService; @Autowired PrivateRoomJsonService privateRoomJsonService; /** * 生成预支付订单,获取prepayId * @param request * @param response * @return * @throws Exception */ public String wxPay(){ String o = request.getParameter("object"); Map<String,Object> paramMap = (Map<String,Object>)JSON.parse(o); //----------------------获取App传过来的参数------------------- //获取套餐id String meals = (String) paramMap.get("mealId"); Long mealId = Long.parseLong(meals); //获取套餐详细信息 Meal meal = mealService.getInfoByMealId(mealId); //获取用户id String userId = (String) request.getAttribute("userId"); logger.info("套餐价格:"+meal.getPrice()); //获取充值渠道 String channelName = (String) paramMap.get("channelName"); //房间id String roomId = (String) paramMap.get("roomId"); String privateRoomId = null; String receiveUserId = null; RechargeOrder rechargeOrder =new RechargeOrder(); if (null != paramMap.get("roomId")){//它充 //获取房间id roomId = (String) paramMap.get("roomId"); rechargeOrder.setRoomId(Long.parseLong(roomId)); if (null != paramMap.get("privateRoomId")) { //获取包房id privateRoomId = (String) paramMap.get("privateRoomId"); //根据包房id获取被充人 Map<String, Object> mealmap = new HashMap<>(); mealmap.put("id", privateRoomId); List<PrivateRoomJson> m = privateRoomJsonService.returnInfo(mealmap); //获取被充人id receiveUserId = m.get(0).getCreator();; rechargeOrder.setReceiveUserId(Long.parseLong(receiveUserId)); rechargeOrder.setPrivateRoomId(Long.parseLong(privateRoomId)); } }else{//自充 receiveUserId = userId; rechargeOrder.setReceiveUserId(Long.parseLong(receiveUserId)); } Map<String, Object> map=new HashMap<String, Object>(); //2.5 订单号,此处用时间加随机数生成,商户根据自己情况调整,只要保持全局唯一就行 String strReq =OrderUtil.createOrderId(); //设置充值订单实体 rechargeOrder.setOrderId(strReq); rechargeOrder.setBuyUserId(Long.parseLong(userId)); rechargeOrder.setMealId(mealId); rechargeOrder.setPayMoney(meal.getPrice()); rechargeOrder.setPayType(channelName); //生成交易订单 try { rechargeOrderService.insert(rechargeOrder); logger.info("成功交易单成功!"); } catch (Exception e) { e.printStackTrace(); logger.info("生成交易单失败!"); } //获取充值金额; String total_fee= meal.getPrice()*100+""; //充值金额 String out_trade_no=strReq; //订单号 String timestamp = WXUtil.getTimeStamp(); //超时时间 String nonce_str = WXUtil.getNonceStr(); // 生成随机字符串 //---------------------------------------------- ***** 统一下单开始 ***** ----------------------------------------------------------- //3.获取生成预支付订单的请求类 PrepayIdRequestHandler prepayReqHandler = new PrepayIdRequestHandler(request, response); prepayReqHandler.setParameter("appid", ConstantUtil.APP_ID); //平台应用appId prepayReqHandler.setParameter("mch_id", ConstantUtil.MCH_ID); //商户号 prepayReqHandler.setParameter("nonce_str", nonce_str); //随机字符串 prepayReqHandler.setParameter("body", ConstantUtil.BUY_BODY); //商品描述 prepayReqHandler.setParameter("out_trade_no", out_trade_no); //订单号 prepayReqHandler.setParameter("total_fee",String.valueOf(total_fee)); //订单价格 prepayReqHandler.setParameter("spbill_create_ip", request.getRemoteAddr()); //获取客户端ip prepayReqHandler.setParameter("notify_url", ConstantUtil.NOTIFY_URL); //回调通知 prepayReqHandler.setParameter("trade_type", "APP"); //支付类型 prepayReqHandler.setParameter("time_start", timestamp); //时间戳 prepayReqHandler.setGateUrl(ConstantUtil.GATEURL); //设置预支付id的接口url //3.3 注意签名(sign)的生成方式,具体见官方文档(传参都要参与生成签名,且参数名按照字典序排序,最后接上APP_KEY,转化成大写) prepayReqHandler.setParameter("sign", prepayReqHandler.createMD5Sign()); //sign 签名 //3.4 提交预支付,获取prepayid String prepayid = null; try { prepayid = prepayReqHandler.sendPrepay(); logger.debug("预支付订单id----:"+prepayid); } catch (Exception e) { e.printStackTrace(); } //---------------------------------------------- ***** 统一下单 结束 ***** -------------------------------------------------------------- //3.5 若获取prepayid成功,将相关信息返回客户端 String result = null; String errmsg = null; if (prepayid != null && !prepayid.equals("")) { String signs = "appid=" + ConstantUtil.APP_ID + "&noncestr=" + nonce_str + "&package=Sign=WXPay"+ "&partnerid="+ ConstantUtil.PARTNER_ID + "&prepayid=" + prepayid + "×tamp=" + timestamp+ "&key="+ ConstantUtil.APP_KEY; map.put("appid", ConstantUtil.APP_ID); map.put("partnerid", ConstantUtil.PARTNER_ID); //商家id map.put("prepayid", prepayid); //预支付id map.put("package", "Sign=WXPay"); //固定常量 map.put("noncestr", nonce_str); //与请求prepayId时值一致 map.put("timestamp", timestamp); //等于请求prepayId时的time_start map.put("sign", MD5Util.MD5Encode(signs, "utf8").toUpperCase());//签名方式与上面类似 result = "0"; errmsg = ""; } else { result = "-1"; errmsg = "获取prepayid失败"; logger.info("获取prepayid失败"); } return returnJson(map, result, errmsg); } /** * 9.2 接收微信支付成功通知 * @param request * @param response * @throws IOException * @throws java.io.IOException * @throws ParseException */ public void getnotify()throws IOException, ParseException { //1.创建输入输出流 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(); //2.将结果转换 String result = new String(outSteam.toByteArray(), "utf-8"); logger.info("微信支付通知结果:" + result); Map<String, String> map = null; try { //3.解析微信通知返回的信息 map = XMLUtil.doXMLParse(result); logger.info("微信返回结果:" + map); } catch (JDOMException e) { e.printStackTrace(); } // 4.若支付成功,则告知微信服务器收到通知 if (map != null && map.get("result_code").toString().equalsIgnoreCase("SUCCESS")) { String out_trade_no = map.get("out_trade_no"); String wechatMoney = map.get("total_fee"); rechargeOrderService.unifiedOrder(WawaConstantUtil.SYS_PAY_WECHAT, out_trade_no, wechatMoney); } String notifyStr = XMLUtil.setXML("ERROR", ""); writer.write(notifyStr); writer.flush(); } }
serviceImpl (因为牵扯到支付宝支付,所以回调中将两个整合到一起了)
@Override public boolean unifiedOrder(String pay_type,String out_trade_no,String money) { log.info("------支付成功-----"); boolean flag = true; try { //查询订单实体 RechargeOrder rechargeOrder = rechargeOrderMapper.getInfoByOrderId(out_trade_no); if("2".equals(rechargeOrder.getState())||2==rechargeOrder.getState()){ log.info("....已经回调成功过了....."); } else if(rechargeOrder.getState().equals("1")||rechargeOrder.getState()==1){ //判断实付金额与订单金额是否一致 String payMoney = money; log.info("订单金额 :"+rechargeOrder.getPayMoney()); String orderPayMoney = null; if(WawaConstantUtil.SYS_PAY_WECHAT.equalsIgnoreCase(pay_type)){ //微信支付 orderPayMoney = rechargeOrder.getPayMoney()*100+""; } else { //否则支付宝支付 orderPayMoney = rechargeOrder.getPayMoney()+""; } log.info("orderPayMoney"+orderPayMoney+"----payMoney"+payMoney); if(orderPayMoney.equals(payMoney)){ //修改订单状态 rechargeOrder.setState(Long.parseLong("2")); int n = rechargeOrderMapper.updateState(rechargeOrder); if(n>0){//修改成功,执行添加账户的操作 //获取充值人的id Long receiveUserId = rechargeOrder.getReceiveUserId(); //根据套餐id获取套餐信息 Meal meal= mealMapper.getInfoByMealId(rechargeOrder.getMealId()); //获取套餐里的币 Long doll_coin = meal.getDoll_coin(); //获取套餐奖励的币 Long reward_coin = meal.getReward_coin(); //判断是否是首充 int sumCount = 0; UserGameConnectionJson userGameConnectionJson = userGameConnectionJsonMapper.getInfoById(rechargeOrder.getBuyUserId()); //添加首充系统消息 SysInformation sysInformation = new SysInformation(); if("1".equals(userGameConnectionJson.getIsFirstPay())){ sumCount=(int) (doll_coin+reward_coin); sysInformation.setUser_id(receiveUserId); sysInformation.setContent("恭喜您充值成功,获得"+sumCount+"个币。"); sysInformation.setType(WawaConstantUtil.SYS_PAY); }else{ sumCount=(int) (doll_coin+reward_coin+meal.getFirst_reward_coin()); sysInformation.setUser_id(receiveUserId); Long sum = doll_coin+reward_coin; sysInformation.setContent("恭喜您首充次充值成功,获得"+sum+"个币。奖励您"+meal.getFirst_reward_coin()+"个币。"); sysInformation.setType(WawaConstantUtil.SYS_FIRSTPAY); //修改首充状态 userGameConnectionJson.setIsFirstPay("1"); } /**执行会员升级**/ UpgradeMembershipUtil.member(rechargeOrder.getBuyUserId()+"", rechargeOrder.getPayMoney()+""); //添加累计充值金额 userGameConnectionJson.setSumPayMoney(userGameConnectionJson.getSumPayMoney()+meal.getPrice()); //修改用户关联 userGameConnectionJsonMapper.update(userGameConnectionJson); sysInformationMapper.insert(sysInformation); //执行添加币的服务 Map<String, Object> accountMap =new HashMap<String, Object>(); accountMap.put("userId", receiveUserId); //默认充值币账户 accountMap.put("accountType", 1); accountMap.put("balance", sumCount); int m = userAccountMapper.addBalance(accountMap); //----执行每日任务---- Map<String,Object> map = new HashMap<String,Object>(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); String date = sdf.format(new Date()); log.info("当前日期:"+date); map.put("userId", receiveUserId); map.put("statisticsDate",date); map.put("taskDate",date); DayTaskThread.startDayTask(InterfaceConstantUtil.PAY, map); if(m>0){//添加成功 //添加充值流水 RechargeRecord rechargeRecord = new RechargeRecord(); if(null!=rechargeOrder.getRoomId()){ rechargeRecord.setRoom_id(rechargeOrder.getRoomId()); } rechargeRecord.setUser_id(rechargeOrder.getBuyUserId()); rechargeRecord.setMeal_id(rechargeOrder.getMealId()); rechargeRecord.setRecharge_order_id(out_trade_no); rechargeRecord.setRecharge_user_id(rechargeOrder.getReceiveUserId()); rechargeRecord.setOrder_money(meal.getPrice()); rechargeRecord.setExchange_coin(new Integer(meal.getDoll_coin()+"")); rechargeRecord.setReward_coin(new Integer(meal.getReward_coin()+"")); rechargeRecord.setPay_type(rechargeOrder.getPayType()); rechargeRecord.setPay_money(rechargeOrder.getPayMoney()); rechargeRecord.setType(1); //默认充值充值流水为充值 rechargeRecordMapper.insert(rechargeRecord); }else{ log.info(out_trade_no+"------充值账户失败-----"); } }else{ //修改订单状态(失败) rechargeOrder.setState(Long.parseLong("0")); rechargeOrderMapper.updateState(rechargeOrder); log.info("------修改订单状态失败-----"); } }else{ log.info("非法回调,订单金额与回调金额不一致."); } }else{ log.info("失败订单"); } } catch (Exception e) { flag=false; e.printStackTrace(); } return flag; }
最后提示:将里面的业务逻辑改成你自己的业务逻辑就好了。
小编在此就不细细说明了,有什么问题注释应该都写了,还有要问题的,可以联系QQ985548426.小编长期在线。