The editor is here to say, I suggest you take a look at the payment flow chart provided by WeChat official, and then look at the following. The editor will not provide an account application here. Those preparations can be directly added to the code.
WeChat official process → click to open
Process summary: First, the APP sends a request for the product it wants to buy. A prepaid order is generated in the background, and then the information required for APP payment is returned to the APP payment. After the payment is successful, the WeChat server will call back the callback address you told the WeChat server to request the prepayment order. Execute your business logic after receiving the callback. And at the end, be sure to tell the WeChat server that you have received the callback, otherwise WeChat will call you back infinitely.
Here are a few caveats:
1. It is recommended that the order amount is not directly exposed and transmitted in the interaction to prevent tampering.
2. The general process is to design two tables in your own database when requesting prepaid orders, one is the payment order table and the other is the order flow table. The payment order table is designed with a status, not paid, paid. In prepaid orders, you can transmit your own order number out_trade_no , through this identification. After receiving the identification of the order, the status will be changed to paid, and information such as the recharge amount will be recorded in the flow meter.
3. In the callback, it is necessary to check whether the order has been processed, and then judge whether the actual payment amount matches the order amount. Prevent the actual payment amount from being tampered with.
4. The unit of WeChat is points, so remember to deal with it.
Ok now let's go directly to the code:
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 Jan 22, 2018 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; /** * Generate a prepaid order and get the 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); //----------------------Get the parameters passed by the App------------------- //get package id String meals = (String) paramMap.get("mealId"); Long mealId = Long.parseLong(meals); //Get package details Meal meal = mealService.getInfoByMealId(mealId); //get user id String userId = (String) request.getAttribute("userId"); logger.info("Meal price:"+meal.getPrice()); //Get the recharge channel String channelName = (String) paramMap.get("channelName"); // room id String roomId = (String) paramMap.get("roomId"); String privateRoomId = null; String receiveUserId = null; RechargeOrder rechargeOrder =new RechargeOrder(); if (null != paramMap.get("roomId")){//It fills //get the room id roomId = (String) paramMap.get("roomId"); rechargeOrder.setRoomId (Long.parseLong (roomId)); if (null != paramMap.get("privateRoomId")) { //Get the private room id privateRoomId = (String) paramMap.get("privateRoomId"); //Get the charged person according to the private room id Map<String, Object> mealmap = new HashMap<>(); mealmap.put("id", privateRoomId); List<PrivateRoomJson> m = privateRoomJsonService.returnInfo(mealmap); //Get the charged 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 Order number, here is generated by time plus random number, merchants can adjust it according to their own situation, as long as it is globally unique String strReq =OrderUtil.createOrderId(); //Set the recharge order entity rechargeOrder.setOrderId(strReq); rechargeOrder.setBuyUserId(Long.parseLong(userId)); rechargeOrder.setMealId(mealId); rechargeOrder.setPayMoney(meal.getPrice()); rechargeOrder.setPayType(channelName); //generate transaction order try { rechargeOrderService.insert(rechargeOrder); logger.info("Successful transaction order!"); } catch (Exception e) { e.printStackTrace (); logger.info("Failed to generate transaction order!"); } //Get the recharge amount; String total_fee= meal.getPrice()*100+""; //recharge amount String out_trade_no=strReq; //Order number String timestamp = WXUtil.getTimeStamp(); //timeout time String nonce_str = WXUtil.getNonceStr(); // Generate random string //------------------------------------------------------------ ** *** Unified order start***** ------------------------------------------------ --------------------- //3. Get the request class for generating a prepaid order PrepayIdRequestHandler prepayReqHandler = new PrepayIdRequestHandler(request, response); prepayReqHandler.setParameter("appid", ConstantUtil.APP_ID); //Platform application appId prepayReqHandler.setParameter("mch_id", ConstantUtil.MCH_ID); //Merchant ID prepayReqHandler.setParameter("nonce_str", nonce_str); //random string prepayReqHandler.setParameter("body", ConstantUtil.BUY_BODY); //Product description prepayReqHandler.setParameter("out_trade_no", out_trade_no); //订单号 prepayReqHandler.setParameter("total_fee",String.valueOf(total_fee)); //Order price prepayReqHandler.setParameter("spbill_create_ip", request.getRemoteAddr()); //Get client ip prepayReqHandler.setParameter("notify_url", ConstantUtil.NOTIFY_URL); //Callback notification prepayReqHandler.setParameter("trade_type", "APP"); //Payment type prepayReqHandler.setParameter("time_start", timestamp); //timestamp prepayReqHandler.setGateUrl(ConstantUtil.GATEURL); //Set the interface url of the prepayment id //3.3 Pay attention to the generation method of the signature (sign), see the official document for details (passing parameters must participate in the generation of the signature, and the parameter names are sorted in lexicographical order, and finally connected to APP_KEY, converted to uppercase) prepayReqHandler.setParameter("sign", prepayReqHandler.createMD5Sign()); //sign 签名 //3.4 Submit prepayment and get prepayid String prepayid = null; try { prepayid = prepayReqHandler.sendPrepay(); logger.debug("Prepay order id----:"+prepayid); } catch (Exception e) { e.printStackTrace (); } //------------------------------------------------------------ ** *** End of unified order ***** ------------------------------------------------ ------------------------ //3.5 If the prepayid is obtained successfully, return the relevant information to the client 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); //Prepay id map.put("package", "Sign=WXPay"); //fixed constant map.put("noncestr", nonce_str); //The same value as when requesting prepayId map.put("timestamp", timestamp); //equal to time_start when requesting prepayId map.put("sign", MD5Util.MD5Encode(signs, "utf8").toUpperCase());//The signature method is similar to the above result = "0"; errmsg = ""; } else { result = "-1"; errmsg = "Failed to get prepayid"; logger.info("Failed to get prepayid"); } return returnJson(map, result, errmsg); } /** * 9.2 Receive WeChat payment success notification * @param request * @param response * @throws IOException * @throws java.io.IOException * @throws ParseException */ public void getnotify()throws IOException, ParseException { //1. Create input and output streams 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. Convert the result String result = new String(outSteam.toByteArray(), "utf-8"); logger.info("WeChat payment notification result: " + result); Map<String, String> map = null; try { //3. Parse the information returned by WeChat notification map = XMLUtil.doXMLParse(result); logger.info("WeChat returns result: " + map); } catch (JDOMException e) { e.printStackTrace (); } // 4. If the payment is successful, notify the WeChat server to receive the notification 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 (Because it involves Alipay payment, the two are integrated in the callback)
@Override public boolean unifiedOrder(String pay_type,String out_trade_no,String money) { log.info("------Payment successful-----"); boolean flag = true; try { //Query order entity RechargeOrder rechargeOrder = rechargeOrderMapper.getInfoByOrderId(out_trade_no); if("2".equals(rechargeOrder.getState())||2==rechargeOrder.getState()){ log.info(".... has been successfully called back..."); } else if(rechargeOrder.getState().equals("1")||rechargeOrder.getState()==1){ //Determine whether the actual payment amount is consistent with the order amount String payMoney = money; log.info("Order Amount:"+rechargeOrder.getPayMoney()); String orderPayMoney = null; if(WawaConstantUtil.SYS_PAY_WECHAT.equalsIgnoreCase(pay_type)){ //WeChat payment orderPayMoney = rechargeOrder.getPayMoney()*100+""; } else { //Otherwise Alipay payment orderPayMoney = rechargeOrder.getPayMoney()+""; } log.info("orderPayMoney"+orderPayMoney+"----payMoney"+payMoney); if(orderPayMoney.equals(payMoney)){ //modify order status rechargeOrder.setState(Long.parseLong("2")); int n = rechargeOrderMapper.updateState(rechargeOrder); if(n>0){//The modification is successful, and the operation of adding an account is performed //Get the id of the recharger Long receiveUserId = rechargeOrder.getReceiveUserId(); //Get the package information according to the package id Meal meal= mealMapper.getInfoByMealId(rechargeOrder.getMealId()); //Get the coins in the package Long doll_coin = meal.getDoll_coin(); //Get the coins of the package reward Long reward_coin = meal.getReward_coin(); //Determine whether it is the first charge int sumCount = 0; UserGameConnectionJson userGameConnectionJson = userGameConnectionJsonMapper.getInfoById(rechargeOrder.getBuyUserId()); //Add first charge system message SysInformation sysInformation = new SysInformation(); if("1".equals(userGameConnectionJson.getIsFirstPay())){ sumCount=(int) (doll_coin+reward_coin); sysInformation.setUser_id(receiveUserId); sysInformation.setContent("Congratulations on your successful recharge, get "+sumCount+" coins."); 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("Congratulations on your successful first recharge, get "+sum+" coins. Reward you with "+meal.getFirst_reward_coin()+" coins."); sysInformation.setType(WawaConstantUtil.SYS_FIRSTPAY); //Modify the first charge status userGameConnectionJson.setIsFirstPay("1"); } /**Execute membership upgrade**/ UpgradeMembershipUtil.member(rechargeOrder.getBuyUserId()+"", rechargeOrder.getPayMoney()+""); //Add cumulative recharge amount userGameConnectionJson.setSumPayMoney(userGameConnectionJson.getSumPayMoney()+meal.getPrice()); //modify user association userGameConnectionJsonMapper.update(userGameConnectionJson); sysInformationMapper.insert(sysInformation); //Execute the service of adding coins Map<String, Object> accountMap =new HashMap<String, Object>(); accountMap.put("userId", receiveUserId); //Default recharge currency account accountMap.put("accountType", 1); accountMap.put("balance", sumCount); int m = userAccountMapper.addBalance(accountMap); //----Perform daily tasks---- Map<String,Object> map = new HashMap<String,Object>(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); String date = sdf.format(new Date()); log.info("Current date: "+date); map.put("userId", receiveUserId); map.put("statisticsDate",date); map.put("taskDate",date); DayTaskThread.startDayTask(InterfaceConstantUtil.PAY, map); if(m>0){//Added successfully //Add recharge flow 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); //The default recharge flow is recharge rechargeRecordMapper.insert(rechargeRecord); }else{ log.info(out_trade_no+"------Failed to recharge account-----"); } }else{ //Modify order status (failure) rechargeOrder.setState(Long.parseLong("0")); rechargeOrderMapper.updateState(rechargeOrder); log.info("------ Failed to modify order status-----"); } }else{ log.info("Illegal callback, the order amount is inconsistent with the callback amount."); } }else{ log.info("Failed order"); } } catch (Exception e) { flag=false; e.printStackTrace (); } return flag; }
Final tip: Just change the business logic inside to your own business logic.
Tools download address---click to arrive→
The editor will not explain it in detail here. If you have any questions, comments should be written. If you still have questions, you can contact QQ985548426. The editor has been online for a long time.