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

目前支付宝支付和微信支付是算是目前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();


  }


  }

}`

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,198评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,663评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,985评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,673评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,994评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,399评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,717评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,407评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,112评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,371评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,891评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,255评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,881评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,010评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,764评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,412评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,299评论 2 260

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,087评论 18 139
  • 该文仅对于中间这种支付方式有参考价值哟 一、开发背景 在微信公众号中,需要进行微信支付且为微信公众号网页支付。 二...
    英文名叫夏天阅读 1,654评论 0 7
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,292评论 18 399
  • 文/添一抹岚 昨晚小妹的朋友圈里,贴出一张照片。不是她钟爱的自拍照,也不是春之蓝天白云,无限风光,她发的竟是老屋照...
    添一抹岚阅读 965评论 60 35
  • 以后等你工作了,会比现在更忙,比现在认识更多的人,处理更多的关系,参加更多更多的应酬,考虑更多的事情,就更加没有时...
    小草载着阳光阅读 109评论 0 0