微信支付---公众号支付(2)

上篇一些需要配置和整体思路 都说清楚了 这篇直接来写代码。

你需要下载微信支付SDK(软件开发工具包) 一些工具类 搬砖时需要用到。 


(1)写一个接口Controller 接收响应前端请求的

@RequestMapping("wechat/pay") 

public ResultJson<PaymentOrder> publicWeChatPay(HttpServletRequest request,HttpServletResponse response){

                 //调用service层的服务

}

(2)创建一个订单   所谓的调用微信的统一下单接口。


URL地址:https://api.mch.weixin.qq.com/pay/unifiedorder

请求的参数(此处只显示必填的参数):

公众账号ID appid 微信公共号的ID(在微信公众号平台可以查看)

商户号  mch_id 商户id (在微信商户平台里可以查看)

/* 随机字符串 nonce_str 长度为32位以内。使用随机数生成算法。

这个随机字符串如何生成,这个详细说下

具体是使用UUID生成的

UUID.randomUUID().toString().replaceAll("-","").substring(0,32)。

在微信的SDK中有一个名为WXPayUtil的工具类中有专门生成的nonce_str的方法。

/*签名 sign  使用签名的生成算法计算的。 重点说一下,很多人过不去,就是这个签名错了。

第一步,设所有发送或者接收到的数据为集合M。咱们需要一个Map集合  存放咱们需要的参数。

而且需要对这个Map集合中所有非空的参数进行字典序排序 ,然后URL键值对的格式进行排序key1=value1&key2=value2…)拼接成字符串stringA。 

  1. ◆ 参数名ASCII码从小到大排序(字典序);
  2. ◆ 如果参数的值为空不参与签名;
  3. ◆ 参数名区分大小写;
  4. ◆ 验证调用返回或微信主动通知签名时,传送的sign参数不参与签名,将生成的签名与该sign值作校验。
  5. ◆ 微信接口可能增加字段,验证签名时必须支持增加的扩展字段 

map 中需要存放的数据:文档已经说的很清楚了(所有发送) 就是Map最少要放所有必填的一些参数

paraMap.put("appid", WXAuthUtil.APPID);  
paraMap.put("body", "服务费");  
paraMap.put("mch_id", WXAuthUtil.MCH_ID);//商户id  
 paraMap.put("nonce_str", WXPayUtil.generateNonceStr());  
 paraMap.put("openid", member.getOpenid());  
paraMap.put("spbill_create_ip", request.getRemoteAddr());  

 paraMap.put("trade_type", "JSAPI"); //交易类型(公众号支付)    

paraMap.put("notify_url", HIT_DEBIT);// 此路径是微信服务器调用支付结果通知路径   异步回调

paraMap.put("out_trade_no", "15508"+System.currentTimeMillis()+(int)(Math.random() * 10000));   

paraMap.put("total_fee", publicMoney); //金额   

第二步:有了这个stringA字符串之后,在和key拼接得到一个新的字符串。(key 是你账户密钥:在微信商户平台-》账户设置-》API安全-》密钥设置里),然后对这个新的字符串进行MD5加密运算,再将得到加密后的字符串转换为大写。OK 此刻得到的就是sign。

具体实现  微信的SDK中有一个名为:WXPayUtil的工具类其中有个方法WXPayUtil.generateSignature(paraMap, WXAuthUtil.KEY);

此方法返回一个字符串就是sign  默认加密方式为MD5,OK,到了这一步 咱们所有的参数都有了  该调用接口了。

第三步:调用下单URL

参数为xml字符串  把上面整理出来的参数 转换成xml格式的字符串 微信SDK       

  String xml = WXPayUtil.GetMapToXML(paraMap);  

//发送请求 SDK 

 xmlStr = HttpKit.post(url, xml);

// 微信把很多东西都给你写好了    只要把开发的思路整理清楚 就ok了

第三步:把返回的xml转换成map

map = WXPayUtil.xmlToMap(xmlStr);

再map中取出这个值 判断是否是SUCCESS

以下字段在return_code 和result_code都为SUCCESS的时候有返回 

<prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id>

返回成功 在xml中 也就是转换后的map中 取出prepay_id 

 if ("SUCCESS".equals(map.get("return_code"))&&"SUCCESS".equals(map.get("result_code"))) {      
    prepay_id = map.get("prepay_id");    

   } else {   

     System.out.println("调用微信支付出错,返回状态码:"+map.get("return_code")+",返回信息:"+map.get("return_msg"));  

       throw new ServiceException("80017");

 }


//通过调用下单接口 我们拿到了最重要的一个参数  prepay_id   下来就是整理参数 返回给前端 唤起支付 了

 String timeStamp = WXPayUtil.getCurrentTimestamp()+"";//获取当前时间戳(时分秒)  

 String nonceStr = WXPayUtil.generateNonceStr();   //随机字符串

 Map<String,String> payMap = new HashMap<String, String>();    
  payMap.put("appId", paraMap.get("appid"));
  payMap.put("timeStamp", timeStamp);
  payMap.put("nonceStr", nonceStr);    
  payMap.put("signType", "MD5");    

  payMap.put("package", "prepay_id=" + prepay_id);

  String paySign = WXPayUtil.generateSignature(payMap, WXAuthUtil.KEY);

  payMap.put("paySign", paySign);
    

 此paySign 与上面的sign不一样 上面的是访问统一下单接口要用的参数,此paySign要传递给前端的。

好了,现在基本已经搞了 参数都传递给前端了,现在前端都已经唤起了支付,支付页面已经出来了,输完密码后,支付成功,先调用异步支付

回调,然后当你点击完成后,会调用同步支付回调。也就是你前端js方法中写的一些东西     。那怕你写个alert()点击完成也会调用。

下节讲退款。













猜你喜欢

转载自blog.csdn.net/qq_33274797/article/details/80933125