关于微信支付和支付宝支付java实现

简介: 目前支付宝支付和微信支付是算是目前app的标配了支付宝支付在更新过后有了官方专门的sdk和demo,所以相对而言比较简单,而微信支付稍微复杂一点,下面的文章会附实例代码,微信支付也是参考的github上的某位大神级人物的代码。

目前支付宝支付和微信支付是算是目前app的标配了

支付宝支付在更新过后有了官方专门的sdk和demo,所以相对而言比较简单,而微信支付稍微复杂一点,下面的文章会附实例代码,微信支付也是参考的github上的某位大神级人物的代码。

首先是微信支付

先准备各种数据,我一般都是放到配置类中,当然也可以放到数据库或者配置文件中

`public final class WxpayConfig  {

       /**

        *商家可以考虑读取配置文件

        */

       //微信开发平台应用id

       public static final String APP_ID = "wx8888888888888888";

       //财付通商户号

       public static final String PARTNER = "1900000109";//app请求的商户号

       public static final String MCHID = "1900000109";//预支付请求的商户号                

       //商户号对应的密钥

       public static final String PARTNER_KEY = "";

       //预支付接口

       public static final String PREPAY_URL =  "https://api.mch.weixin.qq.com/pay/unifiedorder"; 

       //查询订单接口

       public static final String QUERY_ORDER_URL = "https://api.mch.weixin.qq.com/pay/orderquery";

       //签名算法常量值

       public static final String SIGN_METHOD = "sha1";

       //异步通知地址

       public static final String NOTIFY_URL = “”;

       //交易类型

       public static final String TRADE_TYPE = "APP";

       //暂定包值

       public static final String PACKAGE = "Sign=WXPay";

       //返回状态成功

       public static final String SUCCESS = "SUCCESS";

       //返回状态失败

       public static final String FAIL = "FAIL";

}`

这是关于微信支付的封装的工具类,其中httpclient和md5加密的需要自己去封装工具类

`public class  WxpayUtil {

       /**

        *随机串

        * @return

        */

       public static String getNonceStr() {

              Random random = new Random();

              return  MD5Util.getMD5String(String.valueOf(random.nextInt(10000)));

       }

       /**

        *时间戳

        * @return

        */

       public static String getTimeStamp() {

              return  String.valueOf(System.currentTimeMillis() / 1000);

       }

       /**

        *解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。

        * @param strxml

        * @return

        * @throws JDOMException

        * @throws IOException

        */

       @SuppressWarnings("unchecked")

       public static Map  parseToMap(String strXml) throws JDOMException, IOException {

              strXml =  strXml.replaceFirst("encoding=\".*\"",  "encoding=\"UTF-8\"");

              if(null == strXml ||  "".equals(strXml)) {

                     return null;

              }

              Map m = new  HashMap<>();


              InputStream in = new  ByteArrayInputStream(strXml.getBytes("UTF-8"));

              SAXBuilder builder = new  SAXBuilder();

              Document doc =  builder.build(in);

              Element root =  doc.getRootElement();

              List list =  root.getChildren();

              Iterator it =  list.iterator();

              while(it.hasNext()) {

                     Element e = it.next();

                     String k = e.getName();

                     String v = "";

                     List  children = e.getChildren();

                     if(children.isEmpty()) {

                            v =  e.getTextNormalize();

                     } else {

                            v =  getChildrenText(children);

                     }

                     m.put(k, v);

              }

              //关闭流

              in.close();

              return m;

       }


       /**

        *获取子结点的xml

        * @param children

        * @return String

        */

       @SuppressWarnings("unchecked")

       private static String  getChildrenText(List children) {

              StringBuffer sb = new  StringBuffer();

              if(!children.isEmpty()) {

                     Iterator  it = children.iterator();

                     while(it.hasNext()) {

                            Element e =  it.next();

                            String name =  e.getName();

                            String value =  e.getTextNormalize();

                            List  list = e.getChildren();

                            sb.append("<"  + name + ">");

                            if(!list.isEmpty())  {

                                   sb.append(getChildrenText(list));

                            }

                            sb.append(value);

                            sb.append("");

                     }

              }

              return sb.toString();

       }

       /**

        *只支持String,并且value非空

        * @param map

        * @return

        */

       public static String  parseToXml(Map map){

              StringBuffer sb = new  StringBuffer("");

              for(Map.Entry entry : map.entrySet()){

                     sb.append("<"+entry.getKey()+">");

                     sb.append("");

                     sb.append("");

              }

              sb.append("");

              return sb.toString();

       }


       /**

     * POST提交XML对象

     * @param document

     */ 


    public static String postXmlClient(String  url,String xmlParams) throws Exception { 


//         return  HttpUtils.postXmlEntity(url, xmlParams).getContent();

     return  HttpClient.postRequest(url, xmlParams);

    } 

}


这是关于微信支付一些参数处理的方法

public class  WxpayHelper {

        /**

     *除去数组中的空值和签名参数

     * @param sArray签名参数组

     * @return去掉空值与签名参数后的新签名参数组

     */

    public static Map  paraFilter(Map sArray) {

        Map result =  new HashMap();

        if (sArray == null || sArray.size()  <= 0) {

            return result;

        }

        for (String key : sArray.keySet()) {

            String value = sArray.get(key);

            if (value == null ||  value.equals("") || key.equalsIgnoreCase("sign") ||  key.equalsIgnoreCase("key")) {

                continue;

            }

            result.put(key, value);

        }

        return result;

    }


    /**

     *把数组所有元素,并按照“参数=参数值”的模式用“&”字符拼接成字符串

     * @param params需要参与字符拼接的参数组

     * @param sorts   是否需要排序 true 或者false

     * @return拼接后字符串

     */

    public static String  createLinkString(Map params) {

        List keys = new  ArrayList(params.keySet());

        Collections.sort(keys);

        String prestr = "";

        for (int i = 0; i < keys.size();  i++) {

            String key = keys.get(i);

            String value = params.get(key);

            if (i == keys.size() - 1) {//拼接时,不包括最后一个&字符

                prestr = prestr + key +  "=" + value;

            } else {

                prestr = prestr + key +  "=" + value + "&";

            }

        }

        return prestr;

    }


    /**

     *验签响应签名

     * @param paras

     * @return

     */

    public static boolean  verify(Map paras){

     String  sign = paras.get("sign");

     if(StringUtils.isBlank(sign))  return false;

     return  sign.equals(WxpayBuilder.buildRequestMysign(paraFilter(paras)));

    }


    /**

     *响应成功

     * @param loggerAgent -日志代理

     * @return String

     */

    /*public static String yes(ILoggerAgent  loggerAgent){

     Map  return_wx = new HashMap<>();

     return_wx.put("return_code",  WxpayConfig.SUCCESS);

     loggerAgent.payParamsLogger(null  , "WX-NOTIFY", false, return_wx);

     return  WxpayUtil.parseToXml(return_wx);

    }*/

   }


public class  WxpayBuilder {

        /**

     *生成签名结果

     * @param sPara要签名的数组

     * @return签名结果字符串

     */

       public static String  buildRequestMysign(Map sPara) {

     String  prestr =  WxpayHelper.createLinkString(sPara)+"&key="+WxpayConfig.PARTNER_KEY;

     LogFactory.getInstance().getLogger().debug("微信支付签名的字符串:"+prestr);

        return  MD5Util.getMD5String(prestr).toUpperCase();

    }


    public static Map  buildRequestPara(Map sParaTemp) {

        //除去数组中的空值和签名参数

        Map sPara =  WxpayHelper.paraFilter(sParaTemp);

        //生成签名结果

        String mysign =  buildRequestMysign(sPara);


  LogFactory.getInstance().getLogger().debug("微信支付签名数据:"+mysign);

        //签名结果与签名方式加入请求提交参数组中

        sPara.put("sign", mysign);

        return sPara;

    }

}`

使用例程

其中业务接口信息,参考https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_7&index=3


  `     /**

        *微信订单逻辑

        *

        * @throws Exception

        */

       public 

  Map wxPayLogic() throws Exception {

              //微信业务代码

              Map xmlData  = new HashMap();

              xmlData.put("appid",  WxpayConfig.APP_ID);

              xmlData.put("mch_id",  WxpayConfig.MCHID);

              xmlData.put("nonce_str",  WxpayUtil.getNonceStr());

              xmlData.put("out_trade_no",);

              xmlData.put("total_fee",);

              xmlData.put("spbill_create_ip",“”);

              //从数据字典里面去主机地址

              DataDictionary dataDictionary =  dataDictionaryService.getDicByKey("PAY_CALLBACK");

              xmlData.put("notify_url",  dataDictionary.getValue() + WxpayConfig.NOTIFY_URL);

              xmlData.put("trade_type",  WxpayConfig.TRADE_TYPE);

              xmlData.put("body",  "");

              //少写签名

              Map result  = WxpayBuilder.buildRequestPara(xmlData);

              // Map  result = WxpayHelper.paraFilter(xmlData);

              String xmlParams =  WxpayUtil.parseToXml(result);

              LogFactory.getInstance().getLogger().debug("微信支付请求报文:" + xmlParams);

              String xmlResult =  WxpayUtil.postXmlClient(WxpayConfig.PREPAY_URL, xmlParams);

              Map map =  WxpayUtil.parseToMap(xmlResult);

              LogFactory.getInstance().getLogger().debug("微信支付返回报文:" + JsonHelper.toJson(map));

              //返回时SUCCESS

              if  (WxpayConfig.SUCCESS.equals(map.get("return_code"))) {

                     //验证返回是否成功

                     if  (WxpayConfig.SUCCESS.equals(map.get("result_code"))) {

                            //除去签名和空值

                            Map paraFilter = WxpayHelper.paraFilter(map);

                            //获得签名

                            String mysign =  WxpayBuilder.buildRequestMysign(paraFilter);

                            //验证签名

                            if  (mysign.equals(map.get("sign"))) {

                                   String  prepay_id = map.get("prepay_id");

                                   //验证签名成功

                    //进行操作

                            } else {

                                   //签名验证失败

                                   LogFactory.getInstance().getLogger().debug("微信支付验证签名失败");

                            }

                     } else {

                            // result_code返回失败

                            String err_code =  map.get("err_code");

                            String  err_code_des = map.get("err_code_des");

                            chargeRecord.setCauses(err_code+err_code_des);

                            LogFactory.getInstance().getLogger().debug("微信支付结果失败:失败码为"+err_code+",失败原因是"+err_code_des);

                            chargeRecord.setState(2);

                     }

              } else {

                     // return_code返回失败

                     String return_msg =  map.get("return_msg");

                     LogFactory.getInstance().getLogger().debug("微信支付返回失败:返回消息为:" + return_msg);

                     return null;

              }

              //微信支付

              Map  mapBack = new HashMap<>();

              mapBack.put("appid",  WxpayConfig.APP_ID);

              mapBack.put("partnerid",  WxpayConfig.PARTNER);

              mapBack.put("prepayid",  chargeRecord.getOpenId());

              mapBack.put("package",  WxpayConfig.PACKAGE);

              mapBack.put("noncestr",  WxpayUtil.getNonceStr());

              mapBack.put("timestamp",  WxpayUtil.getTimeStamp());

              return  WxpayBuilder.buildRequestPara(mapBack);

       }`

支付异步回传

接收到异步通知之后,才算是付款成功

`@Controller

@RequestMapping(value  = "/api")

public class  WxPayCallbackController extends BaseController {


       @Autowired

       OrderLogic orderLogic;

       @Autowired

       RedisFactory redisFactory;

       @Autowired

       ApplicationContext applicationContext;


       @RequestMapping(value =  "/wxPayCallback", method = RequestMethod.POST)

       @ResponseBody

       public String  wxPayCallback(@RequestBody String body) {

              MDC.put("seqID",  SeqIdGenerator.generate());//日志序列

              LogFactory.getInstance().getPayCallbackLogger().info("接收到微信的异步支付结果通知信息data=" + body);

              Map  resultMap = new HashMap<>();

              if  (StringUtils.isNotBlank(body)) {

                     try {

                            Map map = WxpayUtil.parseToMap(body);

                            //返回代码

                            if  (WxpayConfig.SUCCESS.equals(map.get("return_code"))) {

                                   //验证签名

                                   if  (WxpayHelper.verify(map)) {

                                          //验证业务结果是否成功

                                          String  outTradeNo = map.get("out_trade_no");

                                          if  (WxpayConfig.SUCCESS.equals(map.get("result_code"))) {

                                                 //设置支付类型,1为支付宝,2为微信

                                                 map.put("payType","2");

                           //通过所有验证,启动事件,通过spring的监听器进行监听,并执行付款成功后的业务

                                                 applicationContext.publishEvent(new  OrderFinishEvent(map));

                                          }  else {

                                                 //业务结果失败

                                                 LogFactory.getInstance().getPayCallbackLogger().info("接收到微信的异步支付业务结果失败");

                                                 orderLogic.updateState(outTradeNo,2);

                                                 resultMap.put("return_code",  WxpayConfig.SUCCESS);

                                          }

                                   } else {

                                          //签名失败

                                          LogFactory.getInstance().getPayCallbackLogger().info("接收到微信的异步支付签名失败");

                                          resultMap.put("return_code",  WxpayConfig.FAIL);

                                          resultMap.put("return_msg",  "签名失败");

                                   }

                            } else {

                                   //返回结果失败

                                   LogFactory.getInstance().getPayCallbackLogger().info("接收到微信的异步支付返回结果失败");

                                   resultMap.put("return_code",  WxpayConfig.FAIL);

                                   resultMap.put("return_msg",  "参数格式校验错误");

                            }

                     } catch (Exception e) {

                            e.printStackTrace();

                     }

              } else {

                     //返回结果为空

                     LogFactory.getInstance().getPayCallbackLogger().info("参数格式校验错误");

                     resultMap.put("return_code",  WxpayConfig.FAIL);

                     resultMap.put("return_msg",  "参数格式校验错误");

              }

              return  WxpayUtil.parseToXml(resultMap);

       }


}`

付款成功统一处理事件监听

`@Component

public class OrderFinishLister {




  @EventListener


  public void onApplicationEvent(OrderFinishEvent event){//这里不能抛出异常,外层无法处理,会造成中断


  try {

            Map params =  (HashMap) event.getSource();

            String payType =  params.get("payType");

            String outTradeNo =  params.get("out_trade_no");

            String trade_no = null;

            String buyerLogonId = null;

            String buyerId = null;

            String transactionId = null;

            UserOrder order = null;



  if("1".equals(payType)){

                //支付宝

                 trade_no =  params.get("trade_no");

                 buyerLogonId =  params.get("buyer_logon_id");

                 buyerId =  params.get("buyer_id");

                 //执行付款成功后的业务逻辑


  LogFactory.getInstance().getLogger().debug("支付宝获取支付更新状态:" + outTradeNo);

            }else  if("2".equals(payType)){

                //微信

                 transactionId =  params.get("transaction_id");

                //执行微信付款成功后的业务逻辑


  LogFactory.getInstance().getLogger().debug("微信获取支付更新状态:" + outTradeNo);

            }


  }catch (Exception e){

            e.printStackTrace();


  }


  }

}`

这就是单独的微信支付业务流程

相关文章
|
4月前
|
Java API Spring
打造未来电商新引擎:揭秘Java可扩展API设计,让支付与物流灵活如丝,引领电商时代潮流!
【8月更文挑战第30天】本文通过电商平台案例,探讨了如何设计可扩展的Java API。首先定义支付和物流服务的接口与抽象类,然后实现具体服务,接着引入工厂模式或依赖注入管理服务实例,最后通过配置实现灵活扩展。这种设计确保了应用架构的灵活性和长期稳定性。
63 3
|
2月前
|
应用服务中间件 网络安全 Apache
Discuz! X3.5 开启ssl证书加密后微信、公众号无消息、支付宝通讯中断等
Discuz! X3.5 开启ssl证书加密后微信、公众号无消息、支付宝通讯中断等、支付宝支付实际支付成功,显示未支付等,都属于通讯中断,需要联系DZ官方付费修改程序,屏蔽防CC!
62 4
|
4月前
|
Java 数据库连接 缓存
Hibernate性能调优:五大秘籍,让应用效能飙升,告别慢如蜗牛的加载,体验丝滑般流畅!
【8月更文挑战第31天】本文深入探讨了提升Hibernate应用性能的五大技巧,包括选择合适的缓存策略、优化查询语句、合理使用Eager与Lazy加载、批量操作与事务管理以及利用索引和数据库优化。通过正确配置多级缓存、分页查询、延迟加载、批量处理及合理创建索引,能够显著提高应用响应速度与吞吐量,改善用户体验。这些技巧需根据具体应用场景灵活调整,以实现最佳性能优化效果。
212 0
|
4月前
|
JavaScript 前端开发 Java
|
5月前
|
存储
支付系统36-------订单表优化,添加payment_type字段,无论是微信支付还是支付宝支付都放到 t_order_info表中了,payment_type用来判断支付宝还是微信支付的
支付系统36-------订单表优化,添加payment_type字段,无论是微信支付还是支付宝支付都放到 t_order_info表中了,payment_type用来判断支付宝还是微信支付的
|
6月前
|
PHP 开发工具
php免费用免认证的微信支付宝支付
php免费用免认证的微信支付宝支付
44 5
|
6月前
|
JSON Java 数据安全/隐私保护
一篇文章讲明白Java第三方支付接入案例(支付宝)
一篇文章讲明白Java第三方支付接入案例(支付宝)
317 0
|
2月前
|
JSON 小程序 JavaScript
uni-app开发微信小程序的报错[渲染层错误]排查及解决
uni-app开发微信小程序的报错[渲染层错误]排查及解决
664 7
|
2月前
|
小程序 JavaScript 前端开发
uni-app开发微信小程序:四大解决方案,轻松应对主包与vendor.js过大打包难题
uni-app开发微信小程序:四大解决方案,轻松应对主包与vendor.js过大打包难题
735 1