Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 351|回复: 0

[默认分类] Java开源生鲜电商平台-支付模块的设计与架构(源码可下载)

[复制链接]
  • TA的每日心情
    开心
    2021-12-13 21:45
  • 签到天数: 15 天

    [LV.4]偶尔看看III

    发表于 2018-5-16 11:03:25 | 显示全部楼层 |阅读模式
    java开源生鲜电商平台-支付模块的设计与架构(源码可下载)
    开源生鲜电商平台支付目前支持支付宝与微信。针对的是APP端(android or IOS)

    1。 数据库表设计。
      

    说明:无论是支付宝还是微信支付,都会有一个服务端的回调,业务根据回调的结果处理相应的业务逻辑。
               pay_logs这个表主要是记录相关的用户支付信息。是一个日志记录。
                比如:谁付款的,什么时候付款的,订单号多少,是支付宝还是微信,支付状态是支付成功还是支付失败,还是未支付。
          
               特别注意:订单主表也有类似的回调信息。这样用多张表记录相应的信息,可以统计相应的业务指标,包括用户的行为分析等。
      
                关于表的设计,我的经验分享是:如果可以,核心业务表一定要有一个日志记录表,如果可以,可以用时间轴等方式进行数据的插入,与时间轴的显示。
                时间轴可以清楚的知道用户的行为点,帮助更加清晰的设计业务流程与系统架构。            
      
    相应的支付宝回调代码如下:(注意,这个业务模块属于买家。)

      
    APP调用后端的业务代码

    1. /***
    2. * APP端调用请求支付宝
    3. */
    4. @RestController
    5. @RequestMapping("/buyer")
    6. public class AlipayController extends BaseController
    7. {
    8.     private static final Logger logger = LoggerFactory.getLogger(AlipayController.class);
    9.     /**
    10.      * 服务器通知地址
    11.      */
    12.     private static final String NOTIFY_URL="";
    13.    
    14.     /**待支付*/
    15.     private static final int PAY_LOGS_READY=0;
    16.    
    17.     @Autowired
    18.     private OrderInfoService orderInfoService;
    19.    
    20.     @Autowired
    21.     private BuyerService buyerService;
    22.    
    23.     @Autowired
    24.     private PayLogsService payLogsService;/**
    25.      * APP端请求调用支付宝
    26.      * @param request
    27.      * @param response
    28.      * @return
    29.      */
    30.     @RequestMapping(value="/alipay/invoke",method={RequestMethod.GET,RequestMethod.POST})
    31.     public JsonResult alipayInvoke(HttpServletRequest req, HttpServletResponse resp)
    32.     {
    33.         String result="";
    34.         try
    35.         {
    36.             /**订单号*/
    37.             String orderNumber=this.getNotNull("orderNumber", req);
    38.                     
    39.             /**金额*/
    40.             String money=this.getNotNull("money", req);
    41.             
    42.             /**优惠券id*/
    43.             String couponReceiveId = req.getParameter("couponReceiveId");
    44.             
    45.             if(StringUtils.isBlank(orderNumber) || StringUtils.isBlank(money))
    46.             {
    47.                 return new JsonResult(JsonResultCode.FAILURE,"请求参数有误,请稍后重试","");
    48.             }
    49.             
    50.             //对比金额
    51.             OrderInfo orderInfo=this.orderInfoService.getOrderInfoByOrderNumber(orderNumber);
    52.             if(orderInfo==null)
    53.             {
    54.                 return new JsonResult(JsonResultCode.FAILURE,"订单号不存在,请稍后重试","");
    55.             }
    56.             
    57.             //获取订单的金额
    58.             BigDecimal orderAmount=orderInfo.getOrderAmount();
    59.             
    60.             //减余额
    61.             Long buyerId=orderInfo.getBuyerId();
    62.             
    63.             Buyer buyer=this.buyerService.getBuyerById(buyerId);
    64.             
    65.             //用户余额
    66.             BigDecimal balanceMoney=buyer.getBalanceMoney();
    67.             
    68.             //计算最终需要给支付宝的金额
    69.             BigDecimal payAmount=orderAmount.subtract(balanceMoney);
    70.             
    71.             //买家支付时抵扣优惠券
    72.             if(StringUtils.isNotBlank(couponReceiveId)){
    73.                 Long id = Long.parseLong(couponReceiveId);
    74.                 payAmount = couponReceiveService.deductionCouponMoney(id, orderNumber, payAmount);
    75.             }
    76.             
    77.             logger.info("[AlipayController][alipayInvoke] orderNumber:" +orderNumber +" money:" +money+" orderAmount:"+orderAmount+" balanceMoney:"+balanceMoney+" payAmount:" +payAmount);
    78.             
    79.             //考虑重复订单的问题,会产生重复日志
    80.             PayLogs payLogs=this.payLogsService.getPayLogsByOrderNumber(orderNumber);
    81.             
    82.             if(payLogs==null)
    83.             {
    84.                 //创建订单日志
    85.                 PayLogs logs=new PayLogs();
    86.                 logs.setUserId(buyerId);
    87.                 logs.setOrderId(orderInfo.getOrderId());
    88.                 logs.setOrderNumber(orderNumber);
    89.                 logs.setOrderAmount(payAmount);
    90.                 logs.setStatus(PAY_LOGS_READY);
    91.                 logs.setCreateTime(new Date());
    92.                 int payLogsResult=payLogsService.addPayLogs(logs);
    93.                 logger.info("[AlipayController][alipayInvoke] 创建订单日志结果:" + (payLogsResult>0));
    94.             }else
    95.             {
    96.                 logger.info("[AlipayController][alipayInvoke] 创建重复订单");
    97.             }
    98.             
    99.         
    100.             AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do","","", "json","UTF-8","","RSA2");
    101.             AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
    102.             AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
    103.             model.setBody("");
    104.             model.setSubject("xxx");
    105.             model.setOutTradeNo(orderNumber);
    106.             model.setTimeoutExpress("15m");
    107.             model.setTotalAmount(payAmount.toString());
    108.             model.setProductCode("QUICK_MSECURITY_PAY");
    109.             request.setBizModel(model);
    110.             request.setNotifyUrl(NOTIFY_URL);
    111.             
    112.             AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
    113.             result=response.getBody();
    114.             logger.info("[AlipayController][alipayNotify] result: " +result);
    115.         } catch (AlipayApiException ex)
    116.         {
    117.             logger.error("[AlipayController][alipayNotify] exception:",ex);
    118.             return new JsonResult(JsonResultCode.FAILURE,"系统错误,请稍后重试","");
    119.         }
    120.         return new JsonResult(JsonResultCode.SUCCESS,"操作成功",result);
    121.     }
    122. }
    复制代码


      
    支付宝服务端回调代码
      

    1. import java.io.IOException;
    2. import java.math.BigDecimal;
    3. import java.util.Date;
    4. import java.util.Enumeration;
    5. import java.util.HashMap;
    6. import java.util.Iterator;
    7. import java.util.Map;
    8. import javax.servlet.ServletOutputStream;
    9. import javax.servlet.http.HttpServletRequest;
    10. import javax.servlet.http.HttpServletResponse;
    11. import org.apache.commons.lang3.StringUtils;
    12. import org.slf4j.Logger;
    13. import org.slf4j.LoggerFactory;
    14. import org.springframework.beans.factory.annotation.Autowired;
    15. import org.springframework.stereotype.Controller;
    16. import org.springframework.web.bind.annotation.RequestMapping;
    17. import org.springframework.web.bind.annotation.RequestMethod;
    18. import com.alipay.api.AlipayApiException;
    19. import com.alipay.api.internal.util.AlipaySignature;
    20. /**
    21. * alipay 支付宝服务端回调
    22. * 参考文档:https://docs.open.alipay.com/204/105301/
    23. * 对于App支付产生的交易,支付宝会根据原始支付API中传入的异步通知地址notify_url,通过POST请求的形式将支付结果作为参数通知到商户系统。
    24. */
    25. @Controller
    26. @RequestMapping("/buyer")
    27. public class AlipayNotifyController extends BaseController {
    28.     private static final Logger logger = LoggerFactory.getLogger(AlipayNotifyController.class);
    29.     private static final String ALIPAYPUBLICKEY = "";
    30.     private static final String CHARSET = "UTF-8";
    31.     /**支付成功*/
    32.     private static final int PAY_LOGS_SUCCESS=1;
    33.    
    34.     @Autowired
    35.     private OrderInfoService orderInfoService;
    36.    
    37.    
    38.     @RequestMapping(value = "/alipay/notify", method = { RequestMethod.GET, RequestMethod.POST })
    39.     public void alipayNotify(HttpServletRequest request, HttpServletResponse response) throws IOException
    40.     {
    41.         String url=request.getRequestURL().toString();
    42.         
    43.         logger.info("AlipayNotifyController.alipayNotify.s+tart");
    44.         
    45.         logger.info("[AlipayNotifyController][alipayNotify] url:" +url);
    46.         
    47.         ServletOutputStream out = response.getOutputStream();
    48.         //支付宝交易号
    49.         String alipayTradeNo=this.getNotNull("trade_no", request);
    50.         
    51.         //商户订单号
    52.         String outerTradeNo=this.getNotNull("out_trade_no", request);
    53.         
    54.         //买家支付宝用户号
    55.         String buyerId=this.getNotNull("buyer_id", request);
    56.         
    57.         //买家支付宝账号
    58.         String buyerLogonId=this.getNotNull("buyer_logon_id", request);
    59.         
    60.         //交易状态
    61.         String tradeStatus=this.getNotNull("trade_status", request);
    62.         
    63.         //订单金额,精确到小数点后2位
    64.         String money=getNotNull("total_amount", request);
    65.         
    66.         logger.info("[AlipayNotifyController][alipayNotify] tradeStatus:" +tradeStatus+" money:"+money);
    67.         
    68.         StringBuffer buf = new StringBuffer();
    69.         if (request.getMethod().equalsIgnoreCase("POST"))
    70.         {
    71.             Enumeration<String> em = request.getParameterNames();
    72.             for (; em.hasMoreElements();)
    73.             {
    74.                 Object o = em.nextElement();
    75.                 buf.append(o).append("=").append(request.getParameter(o.toString())).append(",");
    76.             }
    77.             logger.info("回调 method:post]http://" + request.getServerName() + request.getServletPath() + " [<prams:" + buf + ">]");
    78.         } else
    79.         {
    80.             buf.append(request.getQueryString());
    81.             logger.info("回调 method:get]http://" + request.getServerName() + request.getServletPath() + "?" + request.getQueryString());
    82.         }
    83.         
    84.         //检验支付宝参数
    85.         if(!verifyAlipay(request))
    86.         {
    87.                out.print("fail");
    88.                return;
    89.         }
    90.         
    91.         //交易成功
    92.         if("TRADE_SUCCESS".equalsIgnoreCase(tradeStatus))
    93.         {
    94.             try
    95.             {
    96.                 if(StringUtils.isNotBlank(outerTradeNo))
    97.                 {
    98.                     //查询当前订单信息
    99.                     OrderInfo info=this.orderInfoService.getOrderInfoByOrderNumber(outerTradeNo);
    100.                     
    101.                     if(info==null)
    102.                     {
    103.                         logger.error("[AlipayNotifyController][alipayNotify] info:" +info);
    104.                         out.print("fail");
    105.                            return;
    106.                     }
    107.                     
    108.                     //订单信息
    109.                     OrderInfo orderInfo=new OrderInfo();
    110.                     orderInfo.setOrderNumber(outerTradeNo);   
    111.                     orderInfo.setCardCode("alipay");
    112.                     orderInfo.setCardName("支付宝");
    113.                     orderInfo.setCardNumber(buyerLogonId);
    114.                     orderInfo.setCardOwner(buyerId);
    115.                     orderInfo.setPayTime(new Date());
    116.                     orderInfo.setOuterTradeNo(alipayTradeNo);
    117.                     orderInfo.setPayStatus(PayStatus.PAY_SUCCESS);
    118.                     orderInfo.setTradeStatus(TradeStatus.TRADE_PROGRESS);
    119.                     orderInfo.setPayAmount(new BigDecimal(money));
    120.                     orderInfo.setBuyerId(info.getBuyerId());
    121.                     
    122.                     //付款日志
    123.                     PayLogs payLogs=new PayLogs();
    124.                     payLogs.setOrderNumber(outerTradeNo);
    125.                     payLogs.setOuterTradeNo(alipayTradeNo);
    126.                     payLogs.setStatus(PAY_LOGS_SUCCESS);
    127.                     
    128.                     orderInfoService.payReturn(orderInfo,payLogs);
    129.                     out.print("success");
    130.                     return;
    131.                 }
    132.             }catch(Exception ex)
    133.             {
    134.                 logger.error("[AlipayNotifyController][payReturn] 出现了异常:",ex);
    135.                 out.print("success");
    136.                 return;
    137.             }
    138.         }else
    139.         {
    140.             out.print("fail");
    141.             return;
    142.         }
    143.     }
    144.     /**
    145.      * 检验支付宝
    146.      * @param request
    147.      * @return
    148.      */
    149.     @SuppressWarnings("rawtypes")
    150.     public boolean verifyAlipay(HttpServletRequest request)
    151.     {
    152.         boolean flag=true;
    153.         
    154.         // 获取支付宝POST过来反馈信息
    155.         Map<String, String> params = new HashMap<String, String>();
    156.         Map requestParams = request.getParameterMap();
    157.         for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
    158.             String name = (String) iter.next();
    159.             String[] values = (String[]) requestParams.get(name);
    160.             String valueStr = "";
    161.             for (int i = 0; i < values.length; i++) {
    162.                 valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
    163.             }
    164.             params.put(name, valueStr);
    165.         }
    166.         try
    167.         {
    168.             flag= AlipaySignature.rsaCheckV1(params, ALIPAYPUBLICKEY, CHARSET, "RSA2");
    169.         } catch (AlipayApiException e) {
    170.             e.printStackTrace();
    171.             flag=false;
    172.         }
    173.         return flag;
    174.     }
    175. }
    复制代码


      
    APP支付成功后,其实支付宝或者微信都会告诉你是否成功,只是这种通知是不可靠的,最可靠的的一种方式是支付宝或者微信的服务端回调。
    根据回调处理相关的业务。
      
    相应的微信回调代码如下:(注意,这个业务模块属于买家。)
      

      
    APP调用微信:

    1. /***
    2. * APP端调用请求微信
    3. */
    4. @RestController
    5. @RequestMapping("/buyer")
    6. public class WeiXinController extends BaseController
    7. {
    8.     private static final Logger logger = LoggerFactory.getLogger(WeiXinController.class);
    9.    
    10.     /**待支付*/
    11.     private static final int PAY_LOGS_READY=0;
    12.    
    13.     @Autowired
    14.     private OrderInfoService orderInfoService;
    15.    
    16.     @Autowired
    17.     private BuyerService buyerService;
    18.    
    19.     @Autowired
    20.     private PayLogsService payLogsService;
    21.    
    22.     @Autowired
    23.     private CouponReceiveService couponReceiveService;
    24.    
    25.     /**
    26.      * APP端请求调用微信
    27.      * @param request
    28.      * @param response
    29.      * @return
    30.      */
    31.     @RequestMapping(value="/weixin/invoke",method={RequestMethod.GET,RequestMethod.POST})
    32.     public JsonResult weixinInvoke(HttpServletRequest req, HttpServletResponse resp)
    33.     {
    34.         try
    35.         {
    36.             /**订单号*/
    37.             String orderNumber=this.getNotNull("orderNumber", req);
    38.                     
    39.             /**金额*/
    40.             String money=this.getNotNull("money", req);
    41.             
    42.             /**优惠券id*/
    43.             String couponReceiveId = req.getParameter("couponReceiveId");
    44.             
    45.             if(StringUtils.isBlank(orderNumber) || StringUtils.isBlank(money))
    46.             {
    47.                 return new JsonResult(JsonResultCode.FAILURE,"请求参数有误,请稍后重试","");
    48.             }
    49.             
    50.             //对比金额
    51.             OrderInfo orderInfo=this.orderInfoService.getOrderInfoByOrderNumber(orderNumber);
    52.             if(orderInfo==null)
    53.             {
    54.                 return new JsonResult(JsonResultCode.FAILURE,"订单号不存在,请稍后重试","");
    55.             }
    56.             
    57.             //获取订单的金额
    58.             BigDecimal orderAmount=orderInfo.getOrderAmount();
    59.             
    60.             //减余额
    61.             Long buyerId=orderInfo.getBuyerId();
    62.             
    63.             Buyer buyer=this.buyerService.getBuyerById(buyerId);
    64.             
    65.             //用户余额
    66.             BigDecimal balanceMoney=buyer.getBalanceMoney();
    67.             
    68.             //计算最终需要给微信的金额
    69.             BigDecimal payAmount=orderAmount.subtract(balanceMoney);
    70.             
    71.             //买家支付时抵扣优惠券
    72.             if(StringUtils.isNotBlank(couponReceiveId)){
    73.                 Long id = Long.parseLong(couponReceiveId);
    74.                 payAmount = couponReceiveService.deductionCouponMoney(id, orderNumber, payAmount);
    75.             }
    76.             
    77.             logger.info("[WeiXinController][weixinInvoke] orderNumber:" +orderNumber +" money:" +money+" orderAmount:"+orderAmount+" balanceMoney:"+balanceMoney+" payAmount:" +payAmount);
    78.             
    79.             //考虑重复订单的问题,会产生重复日志
    80.             PayLogs payLogs=this.payLogsService.getPayLogsByOrderNumber(orderNumber);
    81.             
    82.             if(payLogs==null)
    83.             {
    84.                 //创建订单日志
    85.                 PayLogs logs=new PayLogs();
    86.                 logs.setUserId(buyerId);
    87.                 logs.setOrderId(orderInfo.getOrderId());
    88.                 logs.setOrderNumber(orderNumber);
    89.                 logs.setOrderAmount(payAmount);
    90.                 logs.setStatus(PAY_LOGS_READY);
    91.                 logs.setCreateTime(new Date());
    92.                 int payLogsResult=payLogsService.addPayLogs(logs);
    93.                 logger.info("[WeiXinController][weixinInvoke] 创建订单日志结果:" + (payLogsResult>0));
    94.             }else
    95.             {
    96.                 logger.info("[WeiXinController][weixinInvoke] 创建重复订单");
    97.             }
    98.             
    99.             //微信开始
    100.             SortedMap<Object,Object> paramMap = new TreeMap<Object,Object>();  
    101.             paramMap.put("appid", WeiXinUtil.APPID);
    102.             paramMap.put("mch_id", WeiXinUtil.MCHID);
    103.             
    104.             String nonceStr=RandomUtil.generateString(8);
    105.             // 随机字符串   
    106.             paramMap.put("nonce_str", nonceStr);
    107.             paramMap.put("body","魔笛食材");// 商品描述  
    108.             paramMap.put("out_trade_no", orderNumber);// 商户订单编号  
    109.             paramMap.put("total_fee",Math.round(payAmount.doubleValue()*100));
    110.             //IP地址
    111.             String ip=IpUtils.getIpAddr(req);
    112.             paramMap.put("spbill_create_ip",ip);
    113.             paramMap.put("notify_url", WeiXinUtil.NOTIFYURL);// 回调地址  
    114.             paramMap.put("trade_type",WeiXinUtil.TRADETYPE);// 交易类型APP  
    115.             String sign=createSign(paramMap);
    116.             paramMap.put("sign", sign);// 数字签证  
    117.             logger.info("weixin支付请求IP:" +ip+ " sign:" +sign);
    118.             
    119.             String xml = getRequestXML(paramMap);   
    120.             
    121.             String content = HttpClientUtil.getInstance().sendHttpPost(WeiXinUtil.URL,xml,"UTF-8");
    122.             
    123.             logger.info("weixin支付请求的内容content:" +content);
    124.             
    125.             JSONObject jsonObject = JSONObject.fromObject(XmltoJsonUtil.xml2JSON(content));
    126.             
    127.             JSONObject resultXml = jsonObject.getJSONObject("xml");
    128.             
    129.             //返回的编码
    130.             JSONArray returnCodeArray =resultXml.getJSONArray("return_code");
    131.             
    132.             //返回的消息
    133.             JSONArray returnMsgArray =resultXml.getJSONArray("return_msg");
    134.             
    135.             //结果编码
    136.             JSONArray resultCodeArray =resultXml.getJSONArray("result_code");
    137.             
    138.             String returnCode= (String)returnCodeArray.get(0);
    139.             
    140.             String returnMsg= (String)returnMsgArray.get(0);
    141.             
    142.             String resultCode = (String)resultCodeArray.get(0);
    143.             
    144.             logger.info("[WeiXinController][weixinInvoke] returnCode: " +returnCode+" returnMsg:"+returnMsg +" resultCode:"+resultCode);
    145.             
    146.             if(resultCode.equalsIgnoreCase("FAIL"))
    147.             {  
    148.                 return new JsonResult(JsonResultCode.FAILURE,"微信统一订单下单失败","");
    149.             }
    150.             
    151.             if(resultCode.equalsIgnoreCase("SUCCESS"))
    152.             {
    153.                 JSONArray prepayIdArray =resultXml.getJSONArray("prepay_id");
    154.                
    155.                 String prepayId= (String)prepayIdArray.get(0);
    156.                
    157.                 WeiXinBean weixin=new WeiXinBean();
    158.                 weixin.setAppid(WeiXinUtil.APPID);
    159.                 weixin.setPartnerid(WeiXinUtil.MCHID);
    160.                 weixin.setNoncestr(nonceStr);
    161.                 weixin.setPrepayid(prepayId);
    162.                 String timestamp=System.currentTimeMillis()/1000+"";
    163.                 weixin.setTimestamp(timestamp);
    164.                 //最终返回签名
    165.                 SortedMap<Object,Object> apiMap = new TreeMap<Object,Object>();  
    166.                 apiMap.put("appid", WeiXinUtil.APPID);
    167.                 apiMap.put("partnerid", WeiXinUtil.MCHID);
    168.                 apiMap.put("prepayid", prepayId);
    169.                 apiMap.put("package","Sign=WXPay");
    170.                 apiMap.put("noncestr",nonceStr);
    171.                 apiMap.put("timestamp", timestamp);
    172.                 //再次签名
    173.                 weixin.setSign(createSign(apiMap));
    174.                 return new JsonResult(JsonResultCode.SUCCESS,"微信统一订单下单成功",weixin);
    175.             }            
    176.             return new JsonResult(JsonResultCode.FAILURE,"操作失败","");
    177.         } catch (Exception ex)
    178.         {
    179.             logger.error("[WeiXinController][weixinInvoke] exception:",ex);
    180.             return new JsonResult(JsonResultCode.FAILURE,"系统错误,请稍后重试","");
    181.         }
    182.     }
    183.     //拼接xml 请求路径
    184.     @SuppressWarnings({"rawtypes"})
    185.     private String getRequestXML(SortedMap<Object, Object> parame){  
    186.         StringBuffer buffer = new StringBuffer();  
    187.         buffer.append("<xml>");  
    188.         Set set = parame.entrySet();  
    189.         Iterator iterator = set.iterator();  
    190.         while(iterator.hasNext()){  
    191.             Map.Entry entry = (Map.Entry) iterator.next();  
    192.             String key =String.valueOf(entry.getKey());  
    193.             String value = String.valueOf(entry.getValue());
    194.             //过滤相关字段sign  
    195.             if("sign".equalsIgnoreCase(key)){  
    196.                 buffer.append("<"+key+">"+"<![CDATA["+value+"]]>"+"</"+key+">");  
    197.             }else{  
    198.                 buffer.append("<"+key+">"+value+"</"+key+">");  
    199.             }            
    200.         }  
    201.         buffer.append("</xml>");  
    202.         return buffer.toString();  
    203.     }
    204.    
    205.     //创建md5 数字签证  
    206.     @SuppressWarnings({"rawtypes"})
    207.     private String createSign(SortedMap<Object, Object> param){
    208.          StringBuffer buffer = new StringBuffer();  
    209.             Set set = param.entrySet();  
    210.             Iterator<?> iterator = set.iterator();  
    211.             while(iterator.hasNext()){  
    212.                 Map.Entry entry = (Map.Entry) iterator.next();  
    213.                 String key = String.valueOf(entry.getKey());  
    214.                 Object value =String.valueOf(entry.getValue());  
    215.                 if(null != value && !"".equals(value) && !"sign".equals(key) && !"key".equals(key)){  
    216.                     buffer.append(key+"="+value+"&");  
    217.                 }            
    218.             }  
    219.             buffer.append("key="+WeiXinUtil.APIKEY);  
    220.             String sign =EncryptUtil.getMD5(buffer.toString()).toUpperCase();   
    221.             return sign;
    222.     }
    223. }
    复制代码


      
    微信回调接口:
      
      
      

    1. /**
    2. * weixin 微信服务端回调
    3. */
    4. @Controller
    5. @RequestMapping("/buyer")
    6. public class WeiXinNotifyController extends BaseController {
    7.     private static final Logger logger = LoggerFactory.getLogger(WeiXinNotifyController.class);
    8.     /**支付成功*/
    9.     private static final int PAY_LOGS_SUCCESS=1;
    10.    
    11.     @Autowired
    12.     private OrderInfoService orderInfoService;
    13.    
    14.     @Autowired
    15.     private CouponReceiveService couponReceiveService;
    16.    
    17.     @Autowired
    18.     private GroupsService groupsService;
    19.    
    20.     @RequestMapping(value = "/weixin/notify", method = { RequestMethod.GET, RequestMethod.POST })
    21.     public void weixinNotify(HttpServletRequest request, HttpServletResponse response) throws IOException
    22.     {
    23.         String url=request.getRequestURL().toString();
    24.         logger.info("WeiXinNotifyController.weixinNotify.start-->url:" +url);
    25.         try
    26.         {
    27.             StringBuffer buf = new StringBuffer();
    28.             if (request.getMethod().equalsIgnoreCase("POST"))
    29.             {
    30.                 Enumeration<String> em = request.getParameterNames();
    31.                 for (; em.hasMoreElements();)
    32.                 {
    33.                     Object o = em.nextElement();
    34.                     buf.append(o).append("=").append(request.getParameter(o.toString())).append(",");
    35.                 }
    36.                 logger.info("回调 method:post]http://" + request.getServerName() + request.getServletPath() + " [<prams:" + buf + ">]");
    37.             } else
    38.             {
    39.                 buf.append(request.getQueryString());
    40.                 logger.info("回调 method:get]http://" + request.getServerName() + request.getServletPath() + "?" + request.getQueryString());
    41.             }
    42.             
    43.             request.setCharacterEncoding("UTF-8");   
    44.             response.setCharacterEncoding("UTF-8");   
    45.             response.setContentType("text/html;charset=UTF-8");   
    46.             response.setHeader("Access-Control-Allow-Origin", "*");     
    47.             InputStream in=request.getInputStream();   
    48.             ByteArrayOutputStream out=new ByteArrayOutputStream();   
    49.             byte[] buffer =new byte[1024];   
    50.             int len=0;   
    51.             while((len=in.read(buffer))!=-1){   
    52.                 out.write(buffer, 0, len);   
    53.             }   
    54.             out.close();   
    55.             in.close();   
    56.             String content=new String(out.toByteArray(),"utf-8");//xml数据   
    57.             
    58.             logger.info("[WeiXinNotifyController][weixinNotify] content:" +content);
    59.             
    60.             //日志显示,存在为空的情况.
    61.             if(StringUtils.isBlank(content))
    62.             {
    63.                 logger.error("[WeiXinNotifyController][weixinNotify] content is blank,please check it");
    64.                 response.getWriter().write(setXml("FAIL", "ERROR"));
    65.                 return;
    66.             }
    67.             
    68.             JSONObject jsonObject = JSONObject.fromObject(XmltoJsonUtil.xml2JSON(content));
    69.             
    70.             JSONObject resultXml = jsonObject.getJSONObject("xml");
    71.             JSONArray returnCode =  resultXml.getJSONArray("return_code");  
    72.             String code = (String)returnCode.get(0);
    73.             
    74.             if(code.equalsIgnoreCase("FAIL"))
    75.             {  
    76.                 response.getWriter().write(setXml("SUCCESS", "OK"));
    77.                 return;
    78.             }else if(code.equalsIgnoreCase("SUCCESS"))
    79.             {  
    80.                 //商户订单号即订单编号
    81.                 String outerTradeNo =String.valueOf(resultXml.getJSONArray("out_trade_no").get(0));
    82.                
    83.                 //微信交易订单号
    84.                 String tradeNo = String.valueOf(resultXml.getJSONArray("transaction_id").get(0));
    85.                
    86.                 //交易状态
    87.                 String resultCode = String.valueOf(resultXml.getJSONArray("result_code").get(0));
    88.                
    89.                 //金额
    90.                 String money =String.valueOf(resultXml.getJSONArray("total_fee").get(0));
    91.                
    92.                 //微信的用户ID
    93.                 String openId =String.valueOf(resultXml.getJSONArray("openid").get(0));
    94.                
    95.                 logger.info("[WeiXinNotifyController][weixinNotify] resultCode:" +resultCode+" money:"+money);
    96.                
    97.                 //根据这个判断来获取订单交易是否OK
    98.                 if(!resultCode.equalsIgnoreCase("SUCCESS"))
    99.                 {
    100.                     response.getWriter().write(setXml("FAIL", "ERROR"));
    101.                     return;
    102.                 }
    103.                
    104.                 try
    105.                 {
    106.                     if(StringUtils.isNotBlank(outerTradeNo))
    107.                     {
    108.                         //查询当前订单信息
    109.                         OrderInfo info=this.orderInfoService.getOrderInfoByOrderNumber(outerTradeNo);
    110.                         
    111.                         if(info==null)
    112.                         {
    113.                             logger.error("[WeiXinNotifyController][weixinNotify] info:" +info);
    114.                             response.getWriter().write(setXml("FAIL", "ERROR"));
    115.                             return;
    116.                         }
    117.                         
    118.                         //订单信息
    119.                         OrderInfo orderInfo=new OrderInfo();
    120.                         orderInfo.setOrderNumber(outerTradeNo);   
    121.                         orderInfo.setCardCode("weixin");
    122.                         orderInfo.setCardName("微信支付");
    123.                         orderInfo.setCardNumber(openId);
    124.                         orderInfo.setCardOwner(openId);
    125.                         orderInfo.setPayTime(new Date());
    126.                         orderInfo.setOuterTradeNo(tradeNo);
    127.                         orderInfo.setPayStatus(PayStatus.PAY_SUCCESS);
    128.                         orderInfo.setTradeStatus(TradeStatus.TRADE_PROGRESS);
    129.                         orderInfo.setPayAmount(new BigDecimal(money).divide(new BigDecimal(100)));
    130.                         orderInfo.setBuyerId(info.getBuyerId());
    131.                         
    132.                         //付款日志
    133.                         PayLogs payLogs=new PayLogs();
    134.                         payLogs.setOrderNumber(outerTradeNo);
    135.                         payLogs.setOuterTradeNo(tradeNo);
    136.                         payLogs.setStatus(PAY_LOGS_SUCCESS);
    137.                         
    138.                         orderInfoService.payReturn(orderInfo,payLogs);
    139.                         
    140.                         //回写团购成功状态
    141.                         groupsService.updateGbStatusByOrderNumber(outerTradeNo);
    142.                         response.getWriter().write(setXml("SUCCESS", "OK"));
    143.                         try
    144.                         {
    145.                             //更新优惠券状态为已用
    146.                             couponReceiveService.updateStatus(outerTradeNo);
    147.                         }catch(Exception ex){
    148.                             logger.error("[AlipayNotifyController][payReturn] 更新优惠券状态异常:",ex);
    149.                         }
    150.                         return;
    151.                     }
    152.                 }catch(Exception ex)
    153.                 {
    154.                     logger.error("[WeiXinNotifyController][payReturn] 出现了异常:",ex);
    155.                     response.getWriter().write(setXml("SUCCESS", "OK"));
    156.                     return;
    157.                 }
    158.             }            
    159.         }catch(Exception e){
    160.             logger.error("[WeiXinNotifyController][weixinNotify] exception:" ,e);
    161.             response.getWriter().write(setXml("SUCCESS", "OK"));
    162.             return;
    163.         }  
    164.     }  
    165.     //返回微信服务  
    166.     private String setXml(String returnCode,String returnMsg)
    167.     {   
    168.        return "<xml><return_code><![CDATA["+returnCode+"]]></return_code><return_msg><![CDATA["+returnMsg+"]]></return_msg></xml>";   
    169.     }   
    170. }
    复制代码


        Java开源生鲜电商平台-支付表的设计与架构(源码可下载),如果需要下载的话,可以在我的github下面进行下载。  
      
    相关的运营截图如下:
      

      
      

    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-4-30 06:51 , Processed in 0.404421 second(s), 50 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表